diff --git a/macro/sts/geometry/create_positionlist_plus4.C b/macro/sts/geometry/create_positionlist_plus4.C new file mode 100644 index 0000000000000000000000000000000000000000..dae32cc79bbe8fed9d90eec10844fcfe218a0334 --- /dev/null +++ b/macro/sts/geometry/create_positionlist_plus4.C @@ -0,0 +1,84 @@ +//forward declaration +void loop_over_nodes(TObjArray*, TString&, std::map<TString, TVector3> & ); + +void create_positionlist_plus4(TString inFileName="") +{ + + if (inFileName.Length() > 0 ) { + cout << "Open file " << inFileName << endl; + TFile* f = new TFile(inFileName); + if ( ! f->IsOpen() ) { + std::cout << "create_tgeonode_list: geometry file " << inFileName << " is not accessible!" << std::endl; + return; + } + gGeoManager = (TGeoManager*) f->Get("FAIRGeom"); + } + + std::map<TString, TVector3> matlist; + + TGeoNode* topNode = gGeoManager->GetTopNode(); + TString Path{"/top_1/"}; + TObjArray* nodes = topNode->GetNodes(); + if ( 1 != nodes->GetEntriesFast()) { + std::cerr << "There should be only one node in the top node which is the detector keeping volume" << std::endl; + return; + } + TGeoNode* node = static_cast<TGeoNode*>(nodes->At(0)); + TString TopNodeName{node->GetName()}; + // Replace the trailing _1 by _0 which is the correct number in the full geometry + // TopNodeName.Replace(TopNodeName.Length()-1,1,"0"); + Path = Path + TopNodeName + "/"; + + std::cout << "{\""<< Path << "\", \"" << node->GetMedium()->GetName() << "\"}," << std::endl; + + gGeoManager->cd(Path); + TGeoMatrix *globalmatrix = gGeoManager->GetCurrentMatrix(); + + Double_t local[3]{0., 0., 0.}; + Double_t global[3]{0., 0., 0.}; + globalmatrix->LocalToMaster(local, global); + + matlist[Path] = TVector3(global[0], global[1], global[2]); + + TObjArray* detectornodes = node->GetNodes(); + loop_over_nodes(detectornodes, Path, matlist); + + ofstream myfile; + myfile.open ("example.txt"); + for (auto& info: matlist) { + std::cout << info.first << ", " << info.second.X() << ", " + << info.second.Y() << ", " << info.second.Z() + 4.0 << std::endl; + myfile << info.first << ", " << info.second.X() << ", " + << info.second.Y() << ", " << info.second.Z() + 4.0 << "\n"; +// original +// std::cout << info.first << ", " << info.second.X() << ", " +// << info.second.Y() << ", " << info.second.Z() << std::endl; +// myfile << info.first << ", " << info.second.X() << ", " +// << info.second.Y() << ", " << info.second.Z() << "\n"; + } + myfile.close(); + + RemoveGeoManager(); +} + +void loop_over_nodes(TObjArray* nodes, TString& path, std::map<TString, TVector3>& matlist) +{ + for (Int_t iNode = 0; iNode < nodes->GetEntriesFast(); iNode++) { + TGeoNode* node = static_cast<TGeoNode*>(nodes->At(iNode)); + TString Fullpath = path + node->GetName() +"/"; + + gGeoManager->cd(Fullpath); + TGeoMatrix *globalmatrix = gGeoManager->GetCurrentMatrix(); + + Double_t local[3]{0., 0., 0.}; + Double_t global[3]{0., 0., 0.}; + globalmatrix->LocalToMaster(local, global); + + matlist[Fullpath] = TVector3(global[0], global[1], global[2]); + + TObjArray* subnodes = node->GetNodes(); + if (nullptr != subnodes) { + loop_over_nodes(subnodes, Fullpath, matlist); + } + } +} diff --git a/macro/sts/geometry/create_stsgeo_v19j.C b/macro/sts/geometry/create_stsgeo_v19j.C new file mode 100644 index 0000000000000000000000000000000000000000..32eb89bad57a50eebf6b4f6878c9ba26c3cd1d53 --- /dev/null +++ b/macro/sts/geometry/create_stsgeo_v19j.C @@ -0,0 +1,2325 @@ +/****************************************************************************** + ** Creation of STS geometry in ROOT format (TGeo). + ** + ** @file create_stsgeo_v19j.C + ** @author Volker Friese <v.friese@gsi.de> + ** @since 15 June 2012 + ** @date 09.05.2014 + ** @author Tomas Balog <T.Balog@gsi.de> + ** + ** v19j: use overlap and distance parameters from CAD model + ** v19h: put STS stations from v19d at z-positions = 260; 365; 470; 575; 680; 785; 890; 995 mm + ** v19g: place a box with services around v19e + ** v19f: place a box with services around v19d + ** v19e: increase spacing between stations by +10 mm from 100 mm + ** v19d: increase spacing between stations by + 5 mm from 100 mm + ** v19c: drop station 8 and increase spacing between remaining 7 stations from 10 cm to 12 c + ** v19b: introduce FEB orientation in ladder numbering (LadderType went from 2 to 3 digits) + ** v19a: import passive materials from gdml file + ** extend CF ladder structures and cables towards FEE plane + ** change CF ladder frame shape + ** v18d: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu (based on v18b) + ** v18c: fixed cut-out windows in cooling plates, improve the box shape/materials + ** v18b: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu + ** v18a: adds 9 cooling/holding plates and a box around the setup + ** v16g: v16g is the new standard geometry from November 2017 + ** v16g: switch from stations to units - left / right ("Unit01L", "Unit01R") + ** v16f: switch from stations to units + ** - split in upstream / downstream and left / right parts + ** - named Unit0xUR, Unit0xUL, Unit0xDR, Unit0xDL + ** v16e: switch from stations to units - upstream / downstream ("Unit01U", "Unit01D") + ** v16d: skip keeping volumes of sts and stations + ** v16c: like v16b, but senors of ladders beampipe next to beampipe + ** shifted closer to the pipe, like in the CAD model + ** v16b: like v16a, but yellow sensors removed + ** v16a: derived from v15c (no cones), but with sensor types renamed: + ** 2 -> 1, 3 -> 2, 4 -> 3, 5 -> 4, 1 -> 5 + ** + ** v15c: as v15b without cones + ** v15b: introduce modified carbon ladders from v13z + ** v15a: with flipped ladder orientation for stations 0,2,4,6 to match CAD design + ** + ** TODO: + ** + ** DONE: + ** v15b - use carbon macaroni as ladder support + ** v15b - introduce a small gap between lowest sensor and carbon ladder + ** v15b - build small cones for the first 2 stations + ** v15b - within a station the ladders of adjacent units should not touch eachother - set gkLadderGapZ to 10 mm + ** v15b - for all ladders set an even number of ladder elements + ** v15b - z offset of cones to ladders should not be 0.3 by default, but 0.26 + ** v15b - within a station the ladders should be aligned in z, defined either by the unit or the ladder with most sensors + ** v15b - get rid of cone overlap in stations 7 and 8 - done by adapting rHole size + ** + ** The geometry hierarachy is: + ** + ** 1. Sensors (see function CreateSensors) + ** The sensors are the active volumes and the lowest geometry level. + ** They are built as TGeoVolumes, shape box, material silicon. + ** x size is determined by strip pitch 58 mu and 1024 strips + ** plus guard ring of 1.3 mm at each border -> 6.1992 cm. + ** Sensor type 1 is half of that (3.0792 cm). + ** y size is determined by strip length (2.2 / 4.2 / 6.3 cm) plus + ** guard ring of 1.3 mm at top and bottom -> 2.46 / 4.46 / 6.46 cm. + ** z size is a parameter, to be set by gkSensorThickness. + ** + ** 2. Sectors (see function CreateSectors) + ** Sectors consist of several chained sensors. These are arranged + ** vertically on top of each other with a gap to be set by + ** gkChainGapY. Sectors are constructed as TGeoVolumeAssembly. + ** The sectors are auxiliary volumes used for proper placement + ** of the sensor(s) in the module. They do not show up in the + ** final geometry. + ** + ** 3. Modules (see function ConstructModule) + ** A module is a readout unit, consisting of one sensor or + ** a chain of sensors (see sector) and a cable. + ** The cable extends from the top of the sector vertically to the + ** top of the halfladder the module is placed in. The cable and module + ** volume thus depend on the vertical position of the sector in + ** the halfladder. The cables consist of silicon with a thickness to be + ** set by gkCableThickness. + ** Modules are constructed as TGeoVolume, shape box, medium gStsMedium. + ** The module construction can be switched off (gkConstructCables) + ** to reproduce older geometries. + ** + ** 4. Halfladders (see function ConstructHalfLadder) + ** A halfladder is a vertical assembly of several modules. The modules + ** are placed vertically such that their sectors overlap by + ** gkSectorOverlapY. They are displaced in z direction to allow for the + ** overlap in y by gkSectorGapZ. + ** The horizontal placement of modules in the halfladder can be choosen + ** to left aligned or right aligned, which only matters if sensors of + ** different x size are involved. + ** Halfladders are constructed as TGeoVolumeAssembly. + ** + ** 5. Ladders (see function CreateLadders and ConstructLadder) + ** A ladder is a vertical assembly of two halfladders, and is such the + ** vertical building block of a station. The second (bottom) half ladder + ** is rotated upside down. The vertical arrangement is such that the + ** inner sectors of the two halfladders have the overlap gkSectorOverlapY + ** (function CreateLadder) or that there is a vertical gap for the beam + ** hole (function CreateLadderWithGap). + ** Ladders are constructed as TGeoVolumeAssembly. + ** + ** 6. Stations (see function ConstructStation) + ** A station represents one layer of the STS geometry: one measurement + ** at (approximately) a given z position. It consist of several ladders + ** arranged horizontally to cover the acceptance. + ** The ladders are arranged such that there is a horizontal overlap + ** between neighbouring ladders (gkLadderOverLapX) and a vertical gap + ** to allow for this overlap (gkLadderGapZ). Each second ladder is + ** rotated around its y axis to face away from or into the beam. + ** Stations are constructed as TGeoVolumes, shape box minus tube (for + ** the beam hole), material gStsMedium. + ** + ** 7. STS + ** The STS is a volume hosting the entire detectors system. It consists + ** of several stations located at different z positions. + ** The STS is constructed as TGeoVolume, shape box minus cone (for the + ** beam pipe), material gStsMedium. The size of the box is computed to + ** enclose all stations. + *****************************************************************************/ + + +// Remark: With the proper steering variables, this should exactly reproduce +// the geometry version v11b of A. Kotynia's described in the ASCII format. +// The only exception is a minimal difference in the z position of the +// sectors/sensors. This is because of ladder types 2 and 4 containing the half +// sensors around the beam hole (stations 1,2 and 3). In v11b, the two ladders +// covering the beam hole cannot be transformed into each other by rotations, +// but only by a reflection. This means they are constructionally different. +// To avoid introducing another two ladder types, the difference in z position +// was accepted. + + +// Differences to v12: +// gkChainGap reduced from 1 mm to 0 +// gkCableThickness increased from 100 mum to 200 mum (2 cables per module) +// gkSectorOverlapY reduced from 3 mm to 2.4 mm +// New sensor types 05 and 06 +// New sector types 07 and 08 +// Re-definiton of ladders (17 types instead of 8) +// Re-definiton of station from new ladders + + +#include <iomanip> +#include <iostream> +#include "TGeoManager.h" + +#include "TGeoTube.h" +#include "TGeoPara.h" +#include "TGeoCone.h" +#include "TGeoTrd2.h" +#include "TGeoCompositeShape.h" +#include "TGeoXtru.h" +#include "TGeoPhysicalNode.h" + +// forward declarations +Int_t CreateSensors(); +Int_t CreateSectors(); +Int_t CreateLadders(); +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength); +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY); +TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ); +TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation); +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile); +void PostProcessGdml(TGeoVolume* gdmlTop); +void CheckVolume(TGeoVolume* volume); +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren = kTRUE); +Double_t BeamPipeRadius(Double_t z); +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x); +TGeoVolume* ConstructSmallCone(Double_t coneDz); +TGeoVolume* ConstructBigCone(Double_t coneDz); + +// ------------- Version highlight ----------------------------------- + +const std::string gVersionHighlight = R"( +Summary: + This version adds passive materials imported from GDML model to the STS geometry: + * Taken from and largely correspond to mechanical CAD drawings of the detector + * Thermal insulation box: + - made out of carbon sandwitch panel (2mm carbon fiber sheet + layer of carbon foam + 2mm carbon fiber sheet) + - front window of complex shape with interface to MVD / target chamber + - back window with large aperture (2000 x 1200 mm) square cut into carbon foam + * Structural units: + - made of 2 complex shape aluminum C-Frames, 15mm thick + - placed at 25, 35, ... ,105 cm absolute Z + - contain front-end and power distribution boxes with equivalent X_0 values + + Scripted geometry tweaks: + * Ladders and cables are extended towards the read-out planes having same lengths in respective rows + * Adjusted form and shape of carbon ladder structures from L-type to X-type + * Reduced verbosity of this file + + Sensor arrangement is the same as in version v16g + + !! Important for this version is the discrepancy from the mechanical CAD w.r.t. front wall. + The square window was replaced by a round one to avoid overlaps with present beam pipe designs, e.g. pipe_v16b_1e +)"; + +// ------------- Steering variables ----------------------------------- + +// ---> Horizontal width of sensors [cm] +const Double_t gkSensorSizeX = 6.2; // was 6.2092; // 6.2 - Oleg CAD 15/05/2020 + +// ---> Thickness of sensors [cm] +const Double_t gkSensorThickness = 0.03; + +// ---> Vertical gap between chained sensors [cm] +const Double_t gkChainGapY = 0.00; + +// ---> Thickness of cables [cm] +const Double_t gkCableThickness = 0.02; + +// ---> Horizontal overlap of neighbouring ladders [cm] +const Double_t gkLadderOverlapX = 0.25; // delta X - Oleg CAD 14/05/2020 + +// ---> Vertical overlap of neighbouring sectors in a ladder [cm] +const Double_t gkSectorOverlapY = 0.46; // delta Y - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring sectors in a ladder [cm] +const Double_t gkSectorGapZ = 0.12; // delta Z pitch = 0.15 - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring ladders [cm] +const Double_t gkLadderGapZ = 1.00; // delta Z prime - Oleg CAD 14/05/2020 + +// ---> Gap in z between lowest sector to carbon support structure [cm] +const Double_t gkSectorGapZFrame = 0.10; +// gkSectorGapZFrame is not used anymore 05/05/2020 +// Oleg CAD 05/05/2020 // there should be a 2.8 mm gap between the bottom side of the sensor and the top ledge of the carbon ladder + +// ---> Switch to construct / not to construct readout cables +const Bool_t gkConstructCables = kTRUE; + +// ---> Switch to construct / not to construct frames +const Bool_t gkConstructCones = kFALSE; // kTRUE; // switch this false by default for v15c and v16x +const Bool_t gkConstructFrames = kTRUE; // kFALSE; // switch this true by default for v15c and v16x +const Bool_t gkConstructSmallFrames = kTRUE; // kFALSE; +const Bool_t gkCylindricalFrames = kTRUE; // kFALSE; + +// ---> Size of the frame +const Double_t gkFrameThickness = 0.2; +const Double_t gkThinFrameThickness = 0.05; +const Double_t gkFrameStep = 4.0; // size of frame cell along y direction + +const Double_t gkCylinderDiaInner = 0.07; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) +const Double_t gkCylinderDiaOuter = 0.15; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) + +// ---> Switch to import / not to import the Passive materials from GDML file +const Bool_t gkImportPassive = kTRUE; + +// ---------------------------------------------------------------------------- + + +// -------------- Parameters of beam pipe in the STS region -------------- +// ---> Needed to compute stations and STS such as to avoid overlaps +const Double_t gkPipeZ1 = 22.0; +const Double_t gkPipeR1 = 1.8; +const Double_t gkPipeZ2 = 50.0; +const Double_t gkPipeR2 = 1.8; +const Double_t gkPipeZ3 = 125.0; +const Double_t gkPipeR3 = 5.5; + +//DE const Double_t gkPipeZ1 = 27.0; +//DE const Double_t gkPipeR1 = 1.05; +//DE const Double_t gkPipeZ2 = 160.0; +//DE const Double_t gkPipeR2 = 3.25; +// ---------------------------------------------------------------------------- + +//TString unitName[16] = // names of units for v16e +// { "Unit00D", +// "Unit01U", "Unit01D", +// "Unit02U", "Unit02D", +// "Unit03U", "Unit03D", +// "Unit04U", "Unit04D", +// "Unit05U", "Unit05D", +// "Unit06U", "Unit06D", +// "Unit07U", "Unit07D", +// "Unit08U" }; + +//TString unitName[32] = // names of units for v16f +// { "Unit00DR", "Unit00DL", +// "Unit01UR", "Unit01UL", "Unit01DR", "Unit01DL", +// "Unit02UR", "Unit02UL", "Unit02DR", "Unit02DL", +// "Unit03UR", "Unit03UL", "Unit03DR", "Unit03DL", +// "Unit04UR", "Unit04UL", "Unit04DR", "Unit04DL", +// "Unit05UR", "Unit05UL", "Unit05DR", "Unit05DL", +// "Unit06UR", "Unit06UL", "Unit06DR", "Unit06DL", +// "Unit07UR", "Unit07UL", "Unit07DR", "Unit07DL", +// "Unit08UR", "Unit08UL" }; + +TString unitName[32] = // names of units for v16g - while merging D and U parts + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", "Unit01R", "Unit01L", + "Unit02R", "Unit02L", "Unit02R", "Unit02L", + "Unit03R", "Unit03L", "Unit03R", "Unit03L", + "Unit04R", "Unit04L", "Unit04R", "Unit04L", + "Unit05R", "Unit05L", "Unit05R", "Unit05L", + "Unit06R", "Unit06L", "Unit06R", "Unit06L", + "Unit07R", "Unit07L", "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +TString unitName18[18] = // names of units for v16g + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", + "Unit02R", "Unit02L", + "Unit03R", "Unit03L", + "Unit04R", "Unit04L", + "Unit05R", "Unit05L", + "Unit06R", "Unit06L", + "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +// ------------- Other global variables ----------------------------------- +// ---> STS medium (for every volume except silicon) +TGeoMedium* gStsMedium = NULL; // will be set later +// ---> TGeoManager (too lazy to write out 'Manager' all the time +TGeoManager* gGeoMan = NULL; // will be set later +// ---------------------------------------------------------------------------- + + + + +// ============================================================================ +// ====== Main function ===== +// ============================================================================ + +void create_stsgeo_v19j(const char* geoTag="v19j") +{ + + // ------- Geometry file name (output) ---------------------------------- + TString geoFileName = "sts_"; + geoFileName = geoFileName + geoTag + ".geo.root"; + // -------------------------------------------------------------------------- + + + // ------- Open info file ----------------------------------------------- + TString infoFileName = geoFileName; + infoFileName.ReplaceAll("root", "info"); + fstream infoFile; + infoFile.open(infoFileName.Data(), fstream::out); + infoFile << "STS geometry created with create_stsgeo_v19j.C" << endl; + infoFile << gVersionHighlight << endl; + infoFile << "Global variables: " << endl; + infoFile << "Sensor thickness = " << gkSensorThickness << " cm" << endl; + infoFile << "Vertical gap in sensor chain = " + << gkChainGapY << " cm" << endl; + infoFile << "Vertical overlap of sensors = " + << gkSectorOverlapY << " cm" << endl; + infoFile << "Gap in z between neighbour sensors = " + << gkSectorGapZ << " cm" << endl; + infoFile << "Horizontal overlap of sensors = " + << gkLadderOverlapX << " cm" << endl; + infoFile << "Gap in z between neighbour ladders = " + << gkLadderGapZ << " cm" << endl; + if ( gkConstructCables ) + infoFile << "Cable thickness = " << gkCableThickness << " cm" << endl; + else + infoFile << "No cables" << endl; + infoFile << endl; + infoFile << "Beam pipe: R1 = " << gkPipeR1 << " cm at z = " + << gkPipeZ1 << " cm" << endl; + infoFile << "Beam pipe: R2 = " << gkPipeR2 << " cm at z = " + << gkPipeZ2 << " cm" << endl; + infoFile << "Beam pipe: R3 = " << gkPipeR3 << " cm at z = " + << gkPipeZ3 << " cm" << endl; + // -------------------------------------------------------------------------- + + + // ------- Load media from media file ----------------------------------- + FairGeoLoader* geoLoad = new FairGeoLoader("TGeo","FairGeoLoader"); + FairGeoInterface* geoFace = geoLoad->getGeoInterface(); + TString geoPath = gSystem->Getenv("VMCWORKDIR"); + TString medFile = geoPath + "/geometry/media.geo"; + geoFace->setMediaFile(medFile); + geoFace->readMedia(); + gGeoMan = gGeoManager; + // -------------------------------------------------------------------------- + + + // ----------------- Get and create the required media ----------------- + FairGeoMedia* geoMedia = geoFace->getMedia(); + FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder(); + + // ---> air + FairGeoMedium* mAir = geoMedia->getMedium("air"); + if ( ! mAir ) Fatal("Main", "FairMedium air not found"); + geoBuild->createMedium(mAir); + TGeoMedium* air = gGeoMan->GetMedium("air"); + if ( ! air ) Fatal("Main", "Medium air not found"); + + // ---> silicon + FairGeoMedium* mSilicon = geoMedia->getMedium("silicon"); + if ( ! mSilicon ) Fatal("Main", "FairMedium silicon not found"); + geoBuild->createMedium(mSilicon); + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + if ( ! silicon ) Fatal("Main", "Medium silicon not found"); + + // ---> carbon + FairGeoMedium* mCarbon = geoMedia->getMedium("carbon"); + if ( ! mCarbon ) Fatal("Main", "FairMedium carbon not found"); + geoBuild->createMedium(mCarbon); + TGeoMedium* carbon = gGeoMan->GetMedium("carbon"); + if ( ! carbon ) Fatal("Main", "Medium carbon not found"); + + // ---> STSBoxCarbonFoam + FairGeoMedium* mSTSBoxCarbonFoam = geoMedia->getMedium("STSBoxCarbonFoam"); + if ( ! mSTSBoxCarbonFoam ) Fatal("Main", "FairMedium STSBoxCarbonFoam not found"); + geoBuild->createMedium(mSTSBoxCarbonFoam); + TGeoMedium* STSBoxCarbonFoam = gGeoMan->GetMedium("STSBoxCarbonFoam"); + if ( ! STSBoxCarbonFoam ) Fatal("Main", "Medium STSBoxCarbonFoam not found"); + + // ---> STSBoxCarbonFibre + FairGeoMedium* mSTSBoxCarbonFibre = geoMedia->getMedium("STSBoxCarbonFibre"); + if ( ! mSTSBoxCarbonFibre ) Fatal("Main", "FairMedium STSBoxCarbonFibre not found"); + geoBuild->createMedium(mSTSBoxCarbonFibre); + TGeoMedium* STSBoxCarbonFibre = gGeoMan->GetMedium("STSBoxCarbonFibre"); + if ( ! STSBoxCarbonFibre ) Fatal("Main", "Medium STSBoxCarbonFibre not found"); + + // ---> STScable + FairGeoMedium* mSTScable = geoMedia->getMedium("STScable"); + if ( ! mSTScable ) Fatal("Main", "FairMedium STScable not found"); + geoBuild->createMedium(mSTScable); + TGeoMedium* STScable = gGeoMan->GetMedium("STScable"); + if ( ! STScable ) Fatal("Main", "Medium STScable not found"); + + // ---> Aluminium + FairGeoMedium* mAluminium = geoMedia->getMedium("aluminium"); + if ( ! mAluminium ) Fatal("Main", "FairMedium aluminium not found"); + geoBuild->createMedium(mAluminium); + TGeoMedium* aluminium = gGeoMan->GetMedium("aluminium"); + if ( ! aluminium ) Fatal("Main", "Medium aluminium not found"); + + // --- + gStsMedium = air; + // -------------------------------------------------------------------------- + + + // -------------- Create geometry and top volume ------------------------- + gGeoMan = (TGeoManager*)gROOT->FindObject("FAIRGeom"); +// gGeoMan->SetName("STSgeom"); + TGeoVolume* top = new TGeoVolumeAssembly("top"); +// TGeoBBox* topbox= new TGeoBBox("", 120., 120., 120.); +// TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air")); + gGeoMan->SetTopVolume(top); + // -------------------------------------------------------------------------- + + + // -------------- Create media ------------------------------------------ + /* + cout << endl; + cout << "===> Creating media...."; + cout << CreateMedia(); + cout << " media created" << endl; + TList* media = gGeoMan->GetListOfMedia(); + for (Int_t iMedium = 0; iMedium < media->GetSize(); iMedium++ ) { + cout << "Medium " << iMedium << ": " + << ((TGeoMedium*) media->At(iMedium))->GetName() << endl; + } + gStsMedium = gGeoMan->GetMedium("air"); + if ( ! gStsMedium ) Fatal("Main", "medium sts_air not found"); + */ + // -------------------------------------------------------------------------- + + + // --------------- Create sensors --------------------------------------- + cout << endl << endl; + cout << "===> Creating sensors...." << endl << endl; + infoFile << endl << "Sensors: " << endl; + Int_t nSensors = CreateSensors(); + for (Int_t iSensor = 1; iSensor <= nSensors; iSensor++) { + TString name = Form("Sensor%02d",iSensor); + TGeoVolume* sensor = gGeoMan->GetVolume(name); + + // add color to sensors + if (iSensor == 1) + sensor->SetLineColor(kRed); + if (iSensor == 2) + sensor->SetLineColor(kGreen); + if (iSensor == 3) + sensor->SetLineColor(kBlue); + if (iSensor == 4) + sensor->SetLineColor(kAzure); + if (iSensor == 5) + sensor->SetLineColor(kYellow); + if (iSensor == 6) + sensor->SetLineColor(kYellow); + if (iSensor == 7) + sensor->SetLineColor(kYellow); + + CheckVolume(sensor); + CheckVolume(sensor, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create sectors -------------------------------------- + cout << endl << endl; + cout << "===> Creating sectors...." << endl; + // infoFile << endl << "Sectors: " << endl; + Int_t nSectors = CreateSectors(); + for (Int_t iSector = 1; iSector <= nSectors; iSector++) { + // cout << endl; + TString name = Form("Sector%02d", iSector); + TGeoVolume* sector = gGeoMan->GetVolume(name); + CheckVolume(sector); + // CheckVolume(sector, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create ladders -------------------------------------- + cout << endl << endl; + cout << "===> Creating ladders...." << endl; + infoFile << endl << "Ladders:" << endl; + + TString name = ""; + TGeoVolume* ladder; + + + Int_t nLadders = CreateLadders(); + for (Int_t iLadder = 1; iLadder <= nLadders; iLadder++) { + cout << endl; +// v19a TString name = Form("LadderType%02d", iLadder); +// v19b + name = Form("LadderType0%02d", iLadder); + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + // CheckVolume(ladder->GetNode(0)->GetVolume(), infoFile, kFALSE); + + cout << "DF: ladder name: " << name << endl << endl; + + name = Form("LadderType1%02d", iLadder); + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + // CheckVolume(ladder->GetNode(0)->GetVolume(), infoFile, kFALSE); + + cout << "DF: ladder name: " << name << endl << endl; + } + // -------------------------------------------------------------------------- + + + // ---------------- Create cones ---------------------------------------- + Double_t coneDz = 1.64; + TGeoVolume* coneSmallVolum = ConstructSmallCone(coneDz); + if (!coneSmallVolum) Fatal("ConstructSmallCone", "Volume Cone not found"); + TGeoVolume* coneBigVolum = ConstructBigCone(coneDz); + if (!coneBigVolum) Fatal("ConstructBigCone", "Volume Cone not found"); + // -------------------------------------------------------------------------- + + + // ---------------- Create stations ------------------------------------- + cout << endl << endl; + cout << "===> Creating stations...." << endl; + infoFile << endl << "Stations: " << endl; + Int_t angle = 0; + nLadders = 0; + Int_t ladderTypes[16]; // there are max 16 ladders in one layer + TGeoTranslation* statTrans = NULL; + + // TGeoVolume *mystation[8]; // stations + // TGeoVolume *myunit[16]; // units + TGeoVolume *myunit[32]; // units + +// Int_t statPos[8] = { 30, 40, 50, 60, 70, 80, 90, 100 }; // z positions of stations +// Int_t statPos[16] = { 28, 32, 38, 42, 48, 52, 58, 62, +// 68, 72, 78, 82, 88, 92, 98,102 }; // z positions of units +// Int_t statPos[16] = { 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units +// Int_t statPos18[18] = { 30, 30, // expanded for placement of Unit00 +// 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units + // v19h + Double_t statPos[16] = { 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of units + Double_t statPos18[18] = { 26.0, 26.0, // expanded for placement of Unit00 + 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of unit + +// // v19d +// Double_t statPos[16] = { 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units +// Double_t statPos18[18] = { 30.0, 30.0, // expanded for placement of Unit00 +// 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units + +////Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.9 , 3.7 , 3.7 , 4.2 , 4.2 }; // size of cutouts in stations +// Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.43, 3.04, 3.35, 3.96, 4.2 }; // size of cutouts in stations, derived from gapXYZ[x][1]/2 + + Int_t cone_size[8] = { 0, 0, 0, 1, 1, 1, 1, 1 }; // size of cones: 0 = small, 1 = large + + Double_t cone_offset[2] = { 0.305, 0.285 }; + +// Int_t allLadderTypes[8][16]= +// { { -1, -1, -1, -1, 10, 109, 9, 101, 1, 109, 9, 110, -1, -1, -1, -1 }, // station 1 +// { -1, -1, 111, 10, 110, 9, 109, 2, 102, 9, 109, 10, 110, 11, -1, -1 }, // station 2 +// { -1, -1, 14, 113, 12, 112, 12, 103, 3, 112, 12, 112, 13, 114, -1, -1 }, // station 3 +// { -1, 15, 114, 13, 112, 12, 112, 4, 104, 12, 112, 12, 113, 14, 115, -1 }, // station 4 +// { -1, 119, 18, 117, 17, 116, 16, 105, 5, 116, 16, 117, 17, 118, 19, -1 }, // station 5 +// { -1, 19, 118, 17, 117, 16, 116, 6, 106, 16, 116, 17, 117, 18, 119, -1 }, // station 6 +// { 21, 119, 18, 120, 20, 120, 20, 107, 7, 120, 20, 120, 20, 118, 19, 121 }, // station 7 +// { 119, 17, 123, 22, 122, 22, 122, 8, 108, 22, 122, 22, 122, 23, 117, 19 } }; // station 8 + +//============================================================================================== + +// explanation: type xyzz +// where x = carbon ladder orientation +// where y = FEB box orientation +// where zz = sensor arrangement on ladder +// with FEB orientation - v19b + Int_t allUnitTypes[16][16]= + { { -1, -1, -1, -1, 10, 0, 9, 0, 101, 0, 109, 0, -1, -1, -1, -1 }, // unit00D Station01 00 + { -1, -1, -1, -1, 0, 1109, 0, 1101, 0, 1009, 0, 1010, -1, -1, -1, -1 }, // unit01U Station01 01 + + { -1, -1, 0, 10, 0, 9, 0, 2, 0, 109, 0, 110, 0, 111, -1, -1 }, // unit01D Station02 02 + { -1, -1, 1111, 0, 1110, 0, 1109, 0, 1002, 0, 1009, 0, 1010, 0, -1, -1 }, // unit02U Station02 03 + + { -1, -1, 14, 0, 12, 0, 12, 0, 103, 0, 112, 0, 113, 0, -1, -1 }, // unit02D Station03 04 + { -1, -1, 0, 1113, 0, 1112, 0, 1103, 0, 1012, 0, 1012, 0, 1014, -1, -1 }, // unit03U Station03 05 + + { -1, 15, 0, 13, 0, 12, 0, 4, 0, 112, 0, 112, 0, 114, 0, -1 }, // unit03D Station04 06 + { -1, 0, 1114, 0, 1112, 0, 1112, 0, 1004, 0, 1012, 0, 1013, 0, 1015, -1 }, // unit04U Station04 07 + + { -1, 0, 18, 0, 17, 0, 16, 0, 105, 0, 116, 0, 117, 0, 119, -1 }, // unit04D Station05 08 + { -1, 1119, 0, 1117, 0, 1116, 0, 1105, 0, 1016, 0, 1017, 0, 1018, 0, -1 }, // unit05U Station05 09 + + { -1, 19, 0, 17, 0, 16, 0, 6, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05D Station06 10 + { -1, 0, 1118, 0, 1117, 0, 1116, 0, 1006, 0, 1016, 0, 1017, 0, 1019, -1 }, // unit06U Station06 11 + + { 21, 0, 25, 0, 20, 0, 20, 0, 107, 0, 120, 0, 120, 0, 127, 0 }, // unit06D Station07 12 + { 0, 1127, 0, 1120, 0, 1120, 0, 1107, 0, 1020, 0, 1020, 0, 1025, 0, 1021 }, // unit07U Station07 13 + + { 0, 24, 0, 22, 0, 22, 0, 8, 0, 122, 0, 122, 0, 123, 0, 126 }, // unit07D Station08 14 + { 1126, 0, 1123, 0, 1122, 0, 1122, 0, 1008, 0, 1022, 0, 1022, 0, 1024, 0 } }; // unit08U Station08 15 + +//============================================================================================== + +// without FEB orientation - v19a +// v19a Int_t allUnitTypes[16][16]= +// v19a { { -1, -1, -1, -1, 10, 0, 9, 0, 1, 0, 9, 0, -1, -1, -1, -1 }, // unit00D Station01 00 +// v19a { -1, -1, -1, -1, 0, 109, 0, 101, 0, 109, 0, 110, -1, -1, -1, -1 }, // unit01U Station01 01 +// v19a { -1, -1, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, -1, -1 }, // unit01D Station02 02 +// v19a { -1, -1, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, -1, -1 }, // unit02U Station02 03 +// v19a { -1, -1, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, -1, -1 }, // unit02D Station03 04 +// v19a { -1, -1, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, -1, -1 }, // unit03U Station03 05 +// v19a { -1, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, -1 }, // unit03D Station04 06 +// v19a { -1, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, -1 }, // unit04U Station04 07 +// v19a { -1, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, -1 }, // unit04D Station05 08 +// v19a { -1, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05U Station05 09 +// v19a { -1, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, -1 }, // unit05D Station06 10 +// v19a { -1, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, -1 }, // unit06U Station06 11 +// v19a { 21, 0, 25, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 27, 0 }, // unit06D Station07 12 +// v19a { 0, 127, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 125, 0, 121 }, // unit07U Station07 13 +// v19a { 0, 24, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 26 }, // unit07D Station08 14 +// v19a { 126, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 124, 0 } }; // unit08U Station08 15 + + +// unitTypes[0] = { 0, 0, 0, 0, 10, 0, 9, 0, 1, 0, 9, 0, 0, 0, 0, 0 }; // unit 0D +// unitTypes[1] = { 0, 0, 0, 0, 0, 109, 0, 101, 0, 109, 0, 110, 0, 0, 0, 0 }; // unit 1U +// unitTypes[2] = { 0, 0, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, 0, 0 }; // unit 1D +// unitTypes[3] = { 0, 0, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, 0, 0 }; // unit 2U +// unitTypes[4] = { 0, 0, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, 0, 0 }; // unit 2D +// unitTypes[5] = { 0, 0, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, 0, 0 }; // unit 3U +// unitTypes[6] = { 0, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, 0 }; // unit 3D +// unitTypes[7] = { 0, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, 0 }; // unit 4U +// unitTypes[8] = { 0, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, 0 }; // unit 4D +// unitTypes[9] = { 0, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, 0 }; // unit 5U +// unitTypes[10] = { 0, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, 0 }; // unit 5D +// unitTypes[11] = { 0, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, 0 }; // unit 6U +// unitTypes[12] = { 21, 0, 18, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 19, 0 }; // unit 6D +// unitTypes[13] = { 0, 119, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 118, 0, 121 }; // unit 7U +// unitTypes[14] = { 0, 17, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 19 }; // unit 7D +// unitTypes[15] = { 119, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 117, 0 }; // unit 8U + + +// // generate unit +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) +// for (Int_t iLadder = 0; iLadder < 16; iLadder++) +// { +// allUnitTypes[iUnit][iLadder] = 0; +// if ((iUnit % 2 == 0) && (allLadderTypes[iUnit/2][iLadder] < 100)) // if carbon structure is oriented upstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// if ((iUnit % 2 == 1) && (allLadderTypes[iUnit/2][iLadder] >= 100)) // if carbon structure is oriented downstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// } + + + // dump unit + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << "DE unitTypes[" << iUnit << "] = { "; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + { + cout << allUnitTypes[iUnit][iLadder]; + if (iLadder < 15) + cout << ", "; + else + cout << " };"; + } + cout << endl; + } + + + // --- Units 01 - 16 + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << endl; + + nLadders = 0; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + if (allUnitTypes[iUnit][iLadder] >= 0) + { + ladderTypes[nLadders] = allUnitTypes[iUnit][iLadder]; + cout << "DE ladderTypes[" << nLadders << "] = " << allUnitTypes[iUnit][iLadder] << ";" << endl; + nLadders++; + } +// myunit[iUnit] = ConstructUnit(iUnit, nLadders, ladderTypes); +// myunit[iUnit] = ConstructUnit(iUnit*2+0, nLadders, ladderTypes); +// myunit[iUnit*2+0] = ConstructUnit(0, iUnit*2+0, nLadders, ladderTypes); +// myunit[iUnit*2+1] = ConstructUnit(1, iUnit*2+1, nLadders, ladderTypes); + myunit[iUnit*2+0] = ConstructUnit(0, iUnit*2+0, nLadders, ladderTypes, iUnit/2+1); + myunit[iUnit*2+1] = ConstructUnit(1, iUnit*2+1, nLadders, ladderTypes, iUnit/2+1); + +// if (gkConstructCones) { +// if (iUnit%2 == 0) +// angle = 90; +// else +// angle = -90; +// +// // upstream +// TGeoRotation* coneRot11 = new TGeoRotation; +// coneRot11->RotateZ(angle); +// coneRot11->RotateY(180); +// TGeoCombiTrans* conePosRot11 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-cone_offset[cone_size[iUnit]]-gkLadderGapZ/2., coneRot11); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 1, conePosRot11); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 1, conePosRot11); +// +// // downstream +// TGeoRotation* coneRot12 = new TGeoRotation; +// coneRot12->RotateZ(angle); +// TGeoCombiTrans* conePosRot12 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+cone_offset[cone_size[iUnit]]+gkLadderGapZ/2., coneRot12); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 2, conePosRot12); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 2, conePosRot12); +// +// myunit[iUnit]->GetShape()->ComputeBBox(); +// } + +// CheckVolume(myunit[iUnit]); +// CheckVolume(myunit[iUnit], infoFile); + if ((iUnit%2 == 0)||(iUnit == 15)) + { + CheckVolume(myunit[iUnit*2+0]); + CheckVolume(myunit[iUnit*2+0], infoFile); + CheckVolume(myunit[iUnit*2+1]); + CheckVolume(myunit[iUnit*2+1], infoFile); + } + infoFile << "Position z = " << statPos[iUnit] << endl; + } + // -------------------------------------------------------------------------- + + + // --------------- Create STS volume ------------------------------------ + cout << endl << endl; + cout << "===> Creating STS...." << endl; + +// // --- Determine size of STS box +// Double_t stsX = 0.; +// Double_t stsY = 0.; +// Double_t stsZ = 0.; +// Double_t stsBorder = 2*5.; // 5 cm space for carbon ladders on each side +// for (Int_t iStation = 1; iStation<=8; iStation++) { +// TString statName = Form("Station%02d", iStation); +// TGeoVolume* station = gGeoMan->GetVolume(statName); +// TGeoBBox* shape = (TGeoBBox*) station->GetShape(); +// stsX = TMath::Max(stsX, 2.* shape->GetDX() ); +// stsY = TMath::Max(stsY, 2.* shape->GetDY() ); +// cout << "Station " << iStation << ": Y " << stsY << endl; +// } +// // --- Some border around the stations +// stsX += stsBorder; +// stsY += stsBorder; +// stsZ = ( statPos[7] - statPos[0] ) + stsBorder; +// +// // --- Create box around the stations +// new TGeoBBox("stsBox", stsX/2., stsY/2., stsZ/2.); +// cout << "size of STS box: x " << stsX << " - y " << stsY << " - z " << stsZ << endl; +// +// // --- Create cone hosting the beam pipe +// // --- One straight section with constant radius followed by a cone +// Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +// Double_t z2 = gkPipeZ2; +// Double_t z3 = statPos[7] + 0.5 * stsBorder; // end of STS box +// Double_t r1 = BeamPipeRadius(z1); +// Double_t r2 = BeamPipeRadius(z2); +// Double_t r3 = BeamPipeRadius(z3); +// r1 += 0.01; // safety margin +// r2 += 0.01; // safety margin +// r3 += 0.01; // safety margin +// +// cout << endl; +// cout << z1 << " " << r1 << endl; +// cout << z2 << " " << r2 << endl; +// cout << z3 << " " << r3 << endl; +// +// cout << endl; +// cout << "station1 : " << BeamPipeRadius(statPos[0]) << endl; +// cout << "station2 : " << BeamPipeRadius(statPos[1]) << endl; +// cout << "station3 : " << BeamPipeRadius(statPos[2]) << endl; +// cout << "station4 : " << BeamPipeRadius(statPos[3]) << endl; +// cout << "station5 : " << BeamPipeRadius(statPos[4]) << endl; +// cout << "station6 : " << BeamPipeRadius(statPos[5]) << endl; +// cout << "station7 : " << BeamPipeRadius(statPos[6]) << endl; +// cout << "station8 : " << BeamPipeRadius(statPos[7]) << endl; +// +// // TGeoPcon* cutout = new TGeoPcon("stsCone", 0., 360., 3); // 2.*TMath::Pi(), 3); +// // cutout->DefineSection(0, z1, 0., r1); +// // cutout->DefineSection(1, z2, 0., r2); +// // cutout->DefineSection(2, z3, 0., r3); +// new TGeoTrd2("stsCone1", r1, r2, r1, r2, (z2-z1)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans1 = new TGeoTranslation("trans1", 0., 0., -(z3-z1)/2.+(z2-z1)/2.); +// trans1->RegisterYourself(); +// new TGeoTrd2("stsCone2", r2, r3, r2, r3, (z3-z2)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans2 = new TGeoTranslation("trans2", 0., 0., +(z3-z1)/2.-(z3-z2)/2.); +// trans2->RegisterYourself(); +// +////DE Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +////DE Double_t z2 = statPos[7] + 0.5 * stsBorder; // end of STS box +////DE Double_t slope = (gkPipeR2 - gkPipeR1) / (gkPipeZ2 - gkPipeZ1); +////DE Double_t r1 = gkPipeR1 + slope * (z1 - gkPipeZ1); // at start of STS +////DE Double_t r2 = gkPipeR1 + slope * (z2 - gkPipeZ1); // at end of STS +////DE r1 += 0.1; // safety margin +////DE r2 += 0.1; // safety margin +////DE // new TGeoCone("stsCone", stsZ/2., 0., r1, 0., r2); +////DE new TGeoTrd2("stsCone", r1, r2, r1, r2, stsZ/2.); + + + // // Create holding/cooling plates + // static std::vector< std::vector<Double_t> > plateSizes = { + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // }; + + // // 8-vertex cut-outs { minWidth, maxWidth, minHeight, maxHeight } + // static std::vector< std::vector<Double_t> > plateCutOuts = { + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 17.6, 47.6 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 49.0, 79.0 }, + // { 85.5,115.5, 51.5, 82.8 }, + // { 85.5,115.5, 59.0, 91.4 }, + // { 85.5,115.5, 68.0, 99.0 }, + // }; + + // for (Int_t iPlate = 0; iPlate < 9; iPlate++) { + // Int_t iUnit = iPlate * 2; + // TGeoBBox* outerPlate = new TGeoBBox(Form("outerPlate%02d",iPlate), + // plateSizes[iPlate][0], plateSizes[iPlate][1], plateSizes[iPlate][2]); + + // TGeoBBox* unitShapeR = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+0])->GetShape(); + // TGeoBBox* unitShapeL = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+1])->GetShape(); + + // Double_t maxDx = (unitShapeR->GetDX() + unitShapeL->GetDX()) / 2.; + // Double_t maxDy = TMath::Max(unitShapeR->GetDY(), unitShapeL->GetDY()); + // cout << maxDy << endl; + + // Double_t* cutOutX = new Double_t[8]; + // Double_t* cutOutY = new Double_t[8]; + + // cutOutX[0] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[0] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[1] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[1] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[2] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[2] = 1/2. * plateCutOuts[iPlate][2]; + // cutOutX[3] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[3] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[4] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[4] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[5] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[5] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[6] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[6] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[7] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[7] = 1/2. * plateCutOuts[iPlate][2]; + + // TGeoXtru* cutOutShape = new TGeoXtru(2); + // cutOutShape->SetName(Form("innerPlate%02d", iPlate)); + // cutOutShape->DefinePolygon(8, cutOutX, cutOutY); + // cutOutShape->DefineSection(0, -1*plateSizes[iPlate][2]-1e-7); + // cutOutShape->DefineSection(1, +1*plateSizes[iPlate][2]+1e-7); + + // TGeoShape* plateShape = new TGeoCompositeShape(Form("PlateShape%02d",iPlate), Form("outerPlate%02d-innerPlate%02d",iPlate,iPlate)); + // TGeoVolume* plate = new TGeoVolume(Form("Plate%02d", iPlate), plateShape, gGeoManager->GetMedium("aluminium")); + // plate->SetLineColor(kRed); + // plate->SetTransparency(65); + // plate->GetShape()->ComputeBBox(); + // } + + // --- Create STS volume + TString stsName = "sts_"; + stsName += geoTag; + +// TGeoShape* stsShape = new TGeoCompositeShape("stsShape", +// "stsBox-stsCone1:trans1-stsCone2:trans2"); +// TGeoVolume* sts = new TGeoVolume(stsName.Data(), stsShape, gStsMedium); + + Double_t stsBorder = 2 * 5.; + + TGeoVolume* sts = new TGeoVolumeAssembly(stsName.Data()); + + // --- Place stations in the STS + Double_t stsPosZ = 0.5 * ( statPos[15] + statPos[0] ); // todo units: update statPos[7] + // cout << "stsPosZ " << stsPosZ << " " << statPos[15] << " " << statPos[0] << "*****" << endl; + +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) { + for (Int_t iUnit = 0; iUnit < 18; iUnit++) { +// for (Int_t iUnit = 0; iUnit < 32; iUnit++) { + TGeoVolume* station = gGeoMan->GetVolume(unitName18[iUnit]); +// Double_t posZ = statPos[iUnit] - stsPosZ; + Double_t posZ = statPos18[iUnit] - stsPosZ; +// Double_t posZ = statPos[iUnit/2] - stsPosZ; + TGeoTranslation* trans = new TGeoTranslation(0., 0., posZ); + sts->AddNode(station, iUnit+1, trans); + sts->GetShape()->ComputeBBox(); + } + +// // --- Import passive elements from GDML file +// if (gkImportPassive) { +// ImportPassive(sts, geoTag, infoFile); +// } + + cout << endl; + CheckVolume(sts); + // -------------------------------------------------------------------------- + + + // --------------- Finish ----------------------------------------------- + TGeoTranslation* stsTrans = new TGeoTranslation(0., 0., stsPosZ); + top->AddNode(sts, 1, stsTrans); + top->GetShape()->ComputeBBox(); + cout << endl << endl; + + CheckVolume(top); + cout << endl << endl; + gGeoMan->CloseGeometry(); +// gGeoMan->CheckOverlaps(0.0001); +// gGeoMan->PrintOverlaps(); +// gGeoMan->CheckOverlaps(0.0001, "s"); +// gGeoMan->PrintOverlaps(); + gGeoMan->Test(); + + TFile* geoFile = new TFile(geoFileName, "RECREATE"); + top->Write(); + cout << endl; + cout << "Geometry " << top->GetName() << " written to " + << geoFileName << endl; + geoFile->Close(); + + TString geoFileName_ = "sts_"; + geoFileName_ = geoFileName_ + geoTag + "_geo.root"; + + geoFile = new TFile(geoFileName_, "RECREATE"); + gGeoMan->Write(); // use this is you want GeoManager format in the output + geoFile->Close(); + + TString geoFileName__ = "sts_"; + geoFileName_ = geoFileName__ + geoTag + "-geo.root"; + sts->Export(geoFileName_); + + geoFile = new TFile(geoFileName_, "UPDATE"); + stsTrans->Write(); + geoFile->Close(); + + // gGeoManager->FindVolumeFast("LadderType10_CarbonElement")->Draw("ogl"); + top->Draw("ogl"); + gGeoManager->SetVisLevel(8); + + infoFile.close(); + +} +// ============================================================================ +// ====== End of main function ===== +// ============================================================================ + + + + + +// **************************************************************************** +// ***** Definition of media, sensors, sectors and ladders ***** +// ***** ***** +// ***** Decoupled from main function for better readability ***** +// **************************************************************************** + + +/** =========================================================================== + ** Create media + ** + ** Currently created: air, active silicon, passive silion + ** + ** Not used for the time being + **/ +Int_t CreateMedia() { + + Int_t nMedia = 0; + Double_t density = 0.; + + // --- Material air + density = 1.205e-3; // [g/cm^3] + TGeoMixture* matAir = new TGeoMixture("sts_air", 3, density); + matAir->AddElement(14.0067, 7, 0.755); // Nitrogen + matAir->AddElement(15.999, 8, 0.231); // Oxygen + matAir->AddElement(39.948, 18, 0.014); // Argon + + // --- Material silicon + density = 2.33; // [g/cm^3] + TGeoElement* elSi = gGeoMan->GetElementTable()->GetElement(14); + TGeoMaterial* matSi = new TGeoMaterial("matSi", elSi, density); + + + // --- Air (passive) + TGeoMedium* medAir = new TGeoMedium("air", nMedia++, matAir); + medAir->SetParam(0, 0.); // is passive + medAir->SetParam(1, 1.); // is in magnetic field + medAir->SetParam(2, 20.); // max. field [kG] + medAir->SetParam(6, 0.001); // boundary crossing precision [cm] + + + // --- Active silicon for sensors + TGeoMedium* medSiAct = new TGeoMedium("silicon", + nMedia++, matSi); + medSiAct->SetParam(0, 1.); // is active + medSiAct->SetParam(1, 1.); // is in magnetic field + medSiAct->SetParam(2, 20.); // max. field [kG] + medSiAct->SetParam(6, 0.001); // boundary crossing precisison [cm] + + // --- Passive silicon for cables + TGeoMedium* medSiPas = new TGeoMedium("carbon", + nMedia++, matSi); + medSiPas->SetParam(0, 0.); // is passive + medSiPas->SetParam(1, 1.); // is in magnetic field + medSiPas->SetParam(2, 20.); // max. field [kG] + medSiPas->SetParam(6, 0.001); // boundary crossing precisison [cm] + + return nMedia; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sensors + ** + ** Sensors are created as volumes with box shape and active silicon as medium. + ** Four kinds of sensors: 3.2x2.2, 6.2x2.2, 6.2x4.2, 6.2x6.2 + **/ +Int_t CreateSensors() { + + Int_t nSensors = 0; + + Double_t xSize = 0.; + Double_t ySize = 0.; + Double_t zSize = gkSensorThickness; + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + + + // --- Sensor type 01: Small sensor (6.2 cm x 2.2 cm) + xSize = gkSensorSizeX; + ySize = 2.2; + TGeoBBox* shape_sensor01 = new TGeoBBox("sensor01", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor01", shape_sensor01, silicon); + nSensors++; + + + // --- Sensor type 02: Medium sensor (6.2 cm x 4.2 cm) + xSize = gkSensorSizeX; + ySize = 4.2; + TGeoBBox* shape_sensor02 = new TGeoBBox("sensor02", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor02", shape_sensor02, silicon); + nSensors++; + + + // --- Sensor type 03: Big sensor (6.2 cm x 6.2 cm) + xSize = gkSensorSizeX; + ySize = 6.2; + TGeoBBox* shape_sensor03 = new TGeoBBox("sensor03", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor03", shape_sensor03, silicon); + nSensors++; + + + // --- Sensor type 04: Big sensor (6.2 cm x 12.4 cm) + xSize = gkSensorSizeX; + ySize = 12.4; + TGeoBBox* shape_sensor04 = new TGeoBBox("sensor04", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor04", shape_sensor04, silicon); + nSensors++; + + + // below are extra small sensors, those are not available in the CAD model + + // --- Sensor Type 05: Half small sensor (4 cm x 2.5 cm) + xSize = 4.0; + ySize = 2.5; + TGeoBBox* shape_sensor05 = new TGeoBBox("sensor05", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor05", shape_sensor05, silicon); + nSensors++; + + + // --- Sensor type 06: Additional "in hole" sensor (3.1 cm x 4.2 cm) + xSize = 3.1; + ySize = 4.2; + TGeoBBox* shape_sensor06 = new TGeoBBox("sensor06", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor06", shape_sensor06, silicon); + nSensors++; + + + // --- Sensor type 07: Mini Medium sensor (1.5 cm x 4.2 cm) + xSize = 1.5; + ySize = 4.2; + TGeoBBox* shape_sensor07 = new TGeoBBox("sensor07", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor07", shape_sensor07, silicon); + nSensors++; + + + return nSensors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sectors + ** + ** A sector is either a single sensor or several chained sensors. + ** It is implemented as TGeoVolumeAssembly. + ** Currently available: + ** - single sensors of type 1 - 4 + ** - two chained sensors of type 4 + ** - three chained sensors of type 4 + **/ +Int_t CreateSectors() { + + Int_t nSectors = 0; + + TGeoVolume* sensor01 = gGeoMan->GetVolume("Sensor01"); + TGeoVolume* sensor02 = gGeoMan->GetVolume("Sensor02"); + TGeoVolume* sensor03 = gGeoMan->GetVolume("Sensor03"); + TGeoVolume* sensor04 = gGeoMan->GetVolume("Sensor04"); + TGeoVolume* sensor05 = gGeoMan->GetVolume("Sensor05"); + TGeoVolume* sensor06 = gGeoMan->GetVolume("Sensor06"); + TGeoVolume* sensor07 = gGeoMan->GetVolume("Sensor07"); + // TGeoBBox* box4 = (TGeoBBox*) sensor04->GetShape(); + + // --- Sector type 1: single sensor of type 1 + TGeoVolumeAssembly* sector01 = new TGeoVolumeAssembly("Sector01"); + sector01->AddNode(sensor01, 1); + sector01->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 2: single sensor of type 2 + TGeoVolumeAssembly* sector02 = new TGeoVolumeAssembly("Sector02"); + sector02->AddNode(sensor02, 1); + sector02->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 3: single sensor of type 3 + TGeoVolumeAssembly* sector03 = new TGeoVolumeAssembly("Sector03"); + sector03->AddNode(sensor03, 1); + sector03->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 4: single sensor of type 4 + TGeoVolumeAssembly* sector04 = new TGeoVolumeAssembly("Sector04"); + sector04->AddNode(sensor04, 1); + sector04->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 5: single sensor of type 5 + TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); + sector05->AddNode(sensor05, 1); + sector05->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 6: single sensor of type 6 + TGeoVolumeAssembly* sector06 = new TGeoVolumeAssembly("Sector06"); + sector06->AddNode(sensor06, 1); + sector06->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 7: single sensor of type 7 + TGeoVolumeAssembly* sector07 = new TGeoVolumeAssembly("Sector07"); + sector07->AddNode(sensor07, 1); + sector07->GetShape()->ComputeBBox(); + nSectors++; + +// // --- Sector type 5: two sensors of type 4 +// TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); +// Double_t shift5 = 0.5 * gkChainGapY + box4->GetDY(); +// TGeoTranslation* transD5 = +// new TGeoTranslation("td", 0., -1. * shift5, 0.); +// TGeoTranslation* transU5 = +// new TGeoTranslation("tu", 0., shift5, 0.); +// sector05->AddNode(sensor04, 1, transD5); +// sector05->AddNode(sensor04, 2, transU5); +// sector05->GetShape()->ComputeBBox(); +// nSectors++; + + return nSectors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create ladders + ** + ** Ladders are the building blocks of the stations. They contain + ** several modules placed one after the other along the z axis + ** such that the sectors are arranged vertically (with overlap). + ** + ** A ladder is constructed out of two half ladders, the second of which + ** is rotated in the x-y plane by 180 degrees and displaced + ** in z direction. + **/ +Int_t CreateLadders() { + + Int_t nLadders = 0; + + // --- Some variables + Int_t nSectors = 0; + Int_t sectorTypes[10]; + TGeoBBox* shape = NULL; + TString s0name; + TString hlname; + char align; + TGeoVolume* s0vol = NULL; + TGeoVolume* halfLadderU = NULL; + TGeoVolume* halfLadderD = NULL; + + // --- Ladders 01-23 + Int_t allSectorTypes[27][6] = { { 1, 2, 3, 3, 0, -1 }, // ladder 01 - 5 - last column defines alignment of small sensors + { 1, 2, 3, 3, 0, 0 }, // ladder 02 - 5 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, -1 }, // ladder 03 - 6 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 04 - 6 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, -1 }, // ladder 05 - 7 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 06 - 7 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 07 - last column defines alignment of small sensors + { 3, 4, 4, 4, 0, 0 }, // ladder 08 - last column defines alignment of small sensors + { 1, 1, 2, 3, 3, 0 }, // ladder 09 - last column defines alignment of small sensors + { 1, 1, 2, 2, 3, 0 }, // ladder 10 - last column defines alignment of small sensors + { 2, 2, 0, 0, 0, 0 }, // ladder 11 - last column defines alignment of small sensors + { 2, 2, 2, 3, 4, 0 }, // ladder 12 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 13 - last column defines alignment of small sensors + { 2, 3, 4, 0, 0, 0 }, // ladder 14 - last column defines alignment of small sensors + { 3, 3, 0, 0, 0, 0 }, // ladder 15 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 16 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 17 - last column defines alignment of small sensors + { 3, 4, 4, 0, 0, 0 }, // ladder 18 - last column defines alignment of small sensors + { 4, 4, 0, 0, 0, 0 }, // ladder 19 - last column defines alignment of small sensors + { 1, 2, 4, 4, 4, 0 }, // ladder 20 - last column defines alignment of small sensors + { 4, 0, 0, 0, 0, 0 }, // ladder 21 - last column defines alignment of small sensors + { 2, 3, 4, 4, 4, 0 }, // ladder 22 - last column defines alignment of small sensors + { 2, 3, 3, 4, 4, 0 }, // ladder 23 - last column defines alignment of small sensors + + { 2, 3, 4, 4, 0, 0 }, // ladder 24 - copy of 17 with different total length + { 3, 4, 4, 0, 0, 0 }, // ladder 25 - copy of 18 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 26 - copy of 19 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 27 - copy of 19 with different total length + }; + +// Issue #405 +// Counting from the most upstream ladder, the gaps between sensors are as follows: +// 01 (most upstream): 41.3mm +// 02: 41.3mm +// 03: 42.0mm +// 04: 48.6mm +// 05: 60.8mm +// 06: 67.0mm +// 07: 79.2mm +// 08 (most downstream): 88.0mm + + Double_t gapXYZ[27][3] = { + { 0., 4.13, 0. }, // ladder 01 + { 0., 4.13, 0. }, // ladder 02 + { 0., 4.20, 0. }, // ladder 03 + { 0., 4.86, 0. }, // ladder 04 + { 0., 6.08, 0. }, // ladder 05 + { 0., 6.70, 0. }, // ladder 06 + { 0., 7.92, 0. }, // ladder 07 + { 0., 8.80, 0. }, // ladder 08 + { 0., -gkSectorOverlapY, 0. }, // ladder 09 + { 0., -gkSectorOverlapY, 0. }, // ladder 10 + { 0., -gkSectorOverlapY, 0. }, // ladder 11 + { 0., -gkSectorOverlapY, 0. }, // ladder 12 + { 0., -gkSectorOverlapY, 0. }, // ladder 13 + { 0., -gkSectorOverlapY, 0. }, // ladder 14 + { 0., -gkSectorOverlapY, 0. }, // ladder 15 + { 0., -gkSectorOverlapY, 0. }, // ladder 16 + { 0., -gkSectorOverlapY, 0. }, // ladder 17 + { 0., -gkSectorOverlapY, 0. }, // ladder 18 + { 0., -gkSectorOverlapY, 0. }, // ladder 19 + { 0., -gkSectorOverlapY, 0. }, // ladder 20 + { 0., -gkSectorOverlapY, 0. }, // ladder 21 + { 0., -gkSectorOverlapY, 0. }, // ladder 22 + { 0., -gkSectorOverlapY, 0. }, // ladder 23 + + { 0., -gkSectorOverlapY, 0. }, // ladder 24 - copy of 17 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 25 - copy of 18 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 26 - copy of 19 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 27 - copy of 19 with different total length + }; + + Double_t ladderLength[27] = { + 48.0, // ladder 01 + 48.0, // ladder 02 + 64.0, // ladder 03 + 64.0, // ladder 04 + 80.0, // ladder 05 + 80.0, // ladder 06 + 92.0, // ladder 07 + 96.0, // ladder 08 + 48.0, // ladder 09 + 48.0, // ladder 10 + 48.0, // ladder 11 + 64.0, // ladder 12 + 64.0, // ladder 13 + 64.0, // ladder 14 + 64.0, // ladder 15 + 80.0, // ladder 16 + 80.0, // ladder 17 + 80.0, // ladder 18 + 80.0, // ladder 19 + 92.0, // ladder 20 + 92.0, // ladder 21 + 96.0, // ladder 22 + 96.0, // ladder 23 + + 96.0, // ladder 24 - copy of 17 with different total length + 92.0, // ladder 25 - copy of 18 with different total length + 96.0, // ladder 26 - copy of 19 with different total length + 92.0, // ladder 27 - copy of 19 with different total length + }; +// ======================================================================== + + // calculate Z shift for ladders with and without gaps in the center + s0name = Form("Sector%02d", allSectorTypes[0][0]); + s0vol = gGeoMan->GetVolume(s0name); + shape = (TGeoBBox*) s0vol->GetShape(); + + for (Int_t iLadder = 0; iLadder < 27; iLadder++) + { + if (iLadder+1 <= 8) +// if ((iLadder+1 == 7) || (iLadder+1 == 8)) // not for ladders with gap + gapXYZ[iLadder][2] = 0; + else + gapXYZ[iLadder][2] = 2. * shape->GetDZ() + gkSectorGapZ; // set displacement in z for overlapping half ladders + } + +// ======================================================================== + + for (Int_t iLadder = 0; iLadder < 27; iLadder++) + { + cout << endl; + nSectors = 0; + for (Int_t i=0; i < 5; i++) + if (allSectorTypes[iLadder][i] != 0) + { + sectorTypes[nSectors] = allSectorTypes[iLadder][i]; + cout << "DE sectorTypes[" << nSectors << "] = " << allSectorTypes[iLadder][i] << ";" << endl; + nSectors++; + } + + if (allSectorTypes[iLadder][5] == 0) + align = 'l'; + else + align = 'r'; + hlname = Form("HalfLadder%02du", iLadder+1); + halfLadderU = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2.); // mirrored + + if (allSectorTypes[iLadder][5] == 0) + align = 'r'; + else + align = 'l'; + hlname = Form("HalfLadder%02dd", iLadder+1); + halfLadderD = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2.); // mirrored + + ConstructLadder(iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); + nLadders++; + + // v19b + ConstructLadder(100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); + } + + return nLadders; +} +/** ======================================================================= **/ + + + +// **************************************************************************** +// ***** ***** +// ***** Generic functions for the construction of STS elements ***** +// ***** ***** +// ***** module: volume (made of a sector and a cable) ***** +// ***** haf ladder: assembly (made of modules) ***** +// ***** ladder: assembly (made of two half ladders) ***** +// ***** station: volume (made of ladders) ***** +// ***** ***** +// **************************************************************************** + + + +/** =========================================================================== + ** Construct a module + ** + ** A module is a sector plus the readout cable extending from the + ** top of the sector. The cable is made from passive silicon. + ** The cable has the same x size as the sector. + ** Its thickness is given by the global variable gkCableThickness. + ** The cable length is a parameter. + ** The sensor(s) of the sector is/are placed directly in the module; + ** the sector is just auxiliary for the proper placement. + ** + ** Arguments: + ** name volume name + ** sector pointer to sector volume + ** cableLength length of cable + **/ +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength) { + + // --- Check sector volume + if ( ! sector ) Fatal("CreateModule", "Sector volume not found!"); + + // --- Get size of sector + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + + // --- Get size of cable + Double_t cableX = sectorX; + Double_t cableY = cableLength; + Double_t cableZ = gkCableThickness; + + // --- Create module volume + Double_t moduleX = TMath::Max(sectorX, cableX); + Double_t moduleY = sectorY + cableLength; + + Double_t moduleZ = TMath::Max(sectorZ, cableZ); + + TGeoVolume* module = gGeoManager->MakeBox(name, gStsMedium, + moduleX/2., + moduleY/2., + moduleZ/2.); + + // --- Position of sector in module + // --- Sector is centred in x and z and aligned to the bottom + Double_t sectorXpos = 0.; + Double_t sectorYpos = 0.5 * (sectorY - moduleY); + Double_t sectorZpos = 0.; + + + // --- Get sensor(s) from sector + Int_t nSensors = sector->GetNdaughters(); + for (Int_t iSensor = 0; iSensor < nSensors; iSensor++) { + TGeoNode* sensor = sector->GetNode(iSensor); + + // --- Calculate position of sensor in module + const Double_t* xSensTrans = sensor->GetMatrix()->GetTranslation(); + Double_t sensorXpos = 0.; + Double_t sensorYpos = sectorYpos + xSensTrans[1]; + Double_t sensorZpos = 0.; + TGeoTranslation* sensTrans = new TGeoTranslation("sensTrans", + sensorXpos, + sensorYpos, + sensorZpos); + + // --- Add sensor volume to module + TGeoVolume* sensVol = sensor->GetVolume(); + module->AddNode(sensor->GetVolume(), iSensor+1, sensTrans); + module->GetShape()->ComputeBBox(); + } + + + // --- Create cable volume, if necessary, and place it in module + // --- Cable is centred in x and z and aligned to the top + if ( gkConstructCables && cableLength > 0.0001 ) { + TString cableName = TString(name) + "_cable"; + TGeoMedium* cableMedium = gGeoMan->GetMedium("STScable"); + if ( ! cableMedium ) Fatal("CreateModule", "Medium STScable not found!"); + TGeoVolume* cable = gGeoManager->MakeBox(cableName.Data(), + cableMedium, + cableX / 2., + cableY / 2., + cableZ / 2.); + // add color to cables + cable->SetLineColor(kOrange); + cable->SetTransparency(60); + Double_t cableXpos = 0.; + Double_t cableYpos = sectorY + 0.5 * cableY - 0.5 * moduleY; + Double_t cableZpos = 0.; + TGeoTranslation* cableTrans = new TGeoTranslation("cableTrans", + cableXpos, + cableYpos, + cableZpos); + module->AddNode(cable, 1, cableTrans); + module->GetShape()->ComputeBBox(); + } + + return module; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a half ladder + ** + ** A half ladder is a virtual volume (TGeoVolumeAssembly) consisting + ** of several modules arranged on top of each other. The modules + ** have a given overlap in y and a displacement in z to allow for the + ** overlap. + ** + ** The typ of sectors / modules to be placed must be specified: + ** 1 = sensor01 + ** 2 = sensor02 + ** 3 = sensor03 + ** 4 = sensor04 + ** 5 = 2 x sensor04 (chained) + ** 6 = 3 x sensor04 (chained) + ** The cable is added automatically from the top of each sensor to + ** the top of the half ladder. + ** The alignment can be left (l) or right (r), which matters in the + ** case of different x sizes of sensors (e.g. SensorType01). + ** + ** Arguments: + ** name volume name + ** nSectors number of sectors + ** sectorTypes array with sector types + ** align horizontal alignment of sectors + * ladderLength full length of the ladder towards FEE + * offsetY gap in the beam-pipe region + **/ +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY) { + + // --- Create half ladder volume assembly + TGeoVolumeAssembly* halfLadder = new TGeoVolumeAssembly(name); + + // --- Determine size of ladder + Double_t ladderX = 0.; + Double_t ladderY = 0.; + Double_t ladderZ = 0.; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + if ( ! sector ) + Fatal("ConstructHalfLadder", Form("Volume %s not found", sectorName.Data())); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + // --- Ladder x size equals largest sector x size + ladderX = TMath::Max(ladderX, 2. * box->GetDX()); + // --- Ladder y size is sum of sector ysizes + ladderY += 2. * box->GetDY(); + // --- Ladder z size is sum of sector z sizes + ladderZ += 2. * box->GetDZ(); + } + // --- Subtract overlaps in y + ladderY -= Double_t(nSectors-1) * gkSectorOverlapY; + // --- Add gaps in z direction + ladderZ += Double_t(nSectors-1) * gkSectorGapZ; + + ladderY = TMath::Max(ladderLength - offsetY, ladderY); + + // --- Create and place modules + Double_t yPosSect = -0.5 * ladderY; + Double_t zPosMod = -0.5 * ladderZ; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + yPosSect += 0.5 * sectorY; // Position of sector in ladder + Double_t cableLength = 0.5 * ladderY - yPosSect - 0.5 * sectorY; + TString moduleName = name + "_" + Form("Module%02d", + sectorTypes[iSector]); + TGeoVolume* module = ConstructModule(moduleName.Data(), + sector, cableLength); + + TGeoBBox* shapeMod = (TGeoBBox*) module->GetShape(); + Double_t moduleX = 2. * shapeMod->GetDX(); + Double_t moduleY = 2. * shapeMod->GetDY(); + Double_t moduleZ = 2. * shapeMod->GetDZ(); + Double_t xPosMod = 0.; + if ( align == 'l' ) + xPosMod = 0.5 * (moduleX - ladderX); // left aligned + else if ( align == 'r' ) + xPosMod = 0.5 * (ladderX - moduleX); // right aligned + else + xPosMod = 0.; // centred in x + Double_t yPosMod = 0.5 * (ladderY - moduleY); // top aligned + zPosMod += 0.5 * moduleZ; + TGeoTranslation* trans = new TGeoTranslation("t", xPosMod, + yPosMod, zPosMod); + halfLadder->AddNode(module, iSector+1, trans); + halfLadder->GetShape()->ComputeBBox(); + yPosSect += 0.5 * sectorY - gkSectorOverlapY; + zPosMod += 0.5 * moduleZ + gkSectorGapZ; + } + + CheckVolume(halfLadder); + cout << endl; + + return halfLadder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Add a carbon support to a ladder + ** + ** Arguments: + ** LadderIndex ladder number + ** ladder pointer to ladder + ** xu size of halfladder + ** ladderY height of ladder along y + ** ladderZ thickness of ladder along z + **/ +void AddCarbonLadder(Int_t LadderIndex, + TGeoVolume* ladder, + Double_t xu, + Double_t ladderY, + Double_t ladderZ) { + + // --- Some variables +// v19a TString name = Form("LadderType%02d", LadderIndex); + TString name = Form("LadderType%03d", LadderIndex); + Int_t i; + Double_t j; + +// guess Int_t YnumOfFrameBoxes = (Int_t)(ladderY / gkFrameStep)+1; // calculate number of elements +// guess if (LadderIndex == 1 || LadderIndex == 2) // set even number of ladder elements for these ladders in station 1 and 2 +// guess YnumOfFrameBoxes--; +// guess// if (LadderIndex == 3 || LadderIndex == 4) // set even number of ladder elements for these ladders in station 3 and 4 +// guess// YnumOfFrameBoxes++; +// guess YnumOfFrameBoxes += YnumOfFrameBoxes % 2; // use even number of frame elements for all ladders + + Int_t YnumOfFrameBoxes = round(ladderY / gkFrameStep); + + // cout << "DEXZ: lad " << LadderIndex << " inum " << YnumOfFrameBoxes << endl; + + // DEDE + Double_t ladderDZ = (xu/2.+sqrt(2.)*gkFrameThickness/2.)/2.; + TGeoBBox* fullFrameShp = new TGeoBBox (name+"_CarbonElement_shp", xu/2., gkFrameStep/2., ladderDZ); + // TGeoBBox* fullFrameShp = new TGeoBBox (name+"_CarbonElement_shp", xu/2., gkFrameStep/2., (gkSectorGapZFrame+xu/2.+sqrt(2.)*gkFrameThickness/2.)/2.); + TGeoVolume* fullFrameBoxVol = new TGeoVolume(name+"_CarbonElement", fullFrameShp, gStsMedium); + + // cout << "DE: frame Z size " << (xu/2.+sqrt(2.)*gkFrameThickness/2.) << " cm" << endl; + + // ConstructFrameElement("FrameBox", fullFrameBoxVol, xu/2.); + ConstructFrameElement("CarbonElement", fullFrameBoxVol, xu/2.); + TGeoRotation* fullFrameRot = new TGeoRotation; + fullFrameRot->RotateY(180); + + Int_t inum = YnumOfFrameBoxes; // 6; // 9; + for (i=1; i<=inum; i++) + { + j=-(inum-1)/2.+(i-1); + // -(10-1)/2. +0 +10-1 -> -4.5 .. +4.5 -> -0.5, +0.5 (= 2) + // -(11-1)/2. +0 +11-1 -> -5.0 .. +5.0 -> -1, 0, 1 (= 3) + // cout << "DE: i " << i << " j " << j << endl; + + if (LadderIndex % 100 <= 3) // central ladders in stations 1 to 3 + { + if ((j>=-1) && (j<=1)) // keep the inner 2 (even) or 3 (odd) elements free for the cone + continue; + } + else if (LadderIndex % 100 <= 8) // central ladders in stations 4 to 8 + { + if ((j>=-2) && (j<=2)) // keep the inner 4 elements free for the cone + continue; + } + + // DEDEDF + cout << "DELZ: ladderDZ " << ladderDZ << " cm " << -ladderZ/2. - ladderDZ << " cm " << endl; + ladder->AddNode(fullFrameBoxVol, i, new TGeoCombiTrans(name+"_CarbonElement_posrot", 0., j*gkFrameStep, -ladderZ/2. - ladderDZ, fullFrameRot)); + // ladder->AddNode(fullFrameBoxVol, i, new TGeoCombiTrans(name+"_CarbonElement_posrot", 0., j*gkFrameStep, -ladderZ/2.-(gkSectorGapZFrame+xu/2.+sqrt(2.)*gkFrameThickness/2.)/2., fullFrameRot)); + } + // cout << endl; + ladder->GetShape()->ComputeBBox(); + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Construct a ladder out of two half ladders with vertical gap + ** + ** The second half ladder will be rotated by 180 degrees + ** in the x-y plane. The two half ladders will be put on top of each + ** other with a vertical gap. + ** + ** Arguments: + ** name volume name + ** halfLadderU pointer to upper half ladder + ** halfLadderD pointer to lower half ladder + ** gapY vertical gap + ** shiftZ relative displacement along the z axis + **/ + + TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ) { + + // --- Some variables + TGeoBBox* shape = NULL; + + // --- Dimensions of half ladders + shape = (TGeoBBox*) halfLadderU->GetShape(); + Double_t xu = 2. * shape->GetDX(); + Double_t yu = 2. * shape->GetDY(); + Double_t zu = 2. * shape->GetDZ(); + + shape = (TGeoBBox*) halfLadderD->GetShape(); + Double_t xd = 2. * shape->GetDX(); + Double_t yd = 2. * shape->GetDY(); + Double_t zd = 2. * shape->GetDZ(); + + // --- Create ladder volume assembly +// v19a TString name = Form("LadderType%02d", LadderIndex); + TString name = Form("LadderType%03d", LadderIndex); + TGeoVolumeAssembly* ladder = new TGeoVolumeAssembly(name); + Double_t ladderX = TMath::Max(xu, xd); + Double_t ladderY = yu + yd + gapY; + Double_t ladderZ = TMath::Max(zu, zd + shiftZ); + + // --- Place half ladders + Double_t xPosU = 0.; // centred in x + Double_t yPosU = 0.5 * ( ladderY - yu ); // top aligned + Double_t zPosU = 0.5 * ( ladderZ - zu ); // front aligned + TGeoTranslation* tu = new TGeoTranslation("tu", xPosU, yPosU, zPosU); + ladder->AddNode(halfLadderU, 1, tu); + + Double_t xPosD = 0.; // centred in x + Double_t yPosD = 0.5 * ( yd - ladderY ); // bottom aligned + Double_t zPosD = 0.5 * ( zd - ladderZ ); // back aligned + TGeoRotation* rd = new TGeoRotation(); + rd->RotateZ(180.); + TGeoCombiTrans* cd = new TGeoCombiTrans(xPosD, yPosD, zPosD, rd); + ladder->AddNode(halfLadderD, 2, cd); + ladder->GetShape()->ComputeBBox(); + + // ---------------- Create and place frame boxes ------------------------ + + if (gkConstructFrames) + AddCarbonLadder(LadderIndex, ladder, xu, ladderY, ladderZ); + + // -------------------------------------------------------------------------- + + return ladder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a unit + ** + ** The unit volume is the minimal box comprising all ladders + ** minus a tube accomodating the beam pipe. + ** + ** The ladders are arranged horizontally from left to right with + ** a given overlap in x. + ** Every second ladder is slightly displaced upstream from the centre + ** z plane and facing downstream, the others are slightly displaced + ** downstream and facing upstream (rotated around the y axis). + ** + ** Arguments: + ** name volume name + ** nLadders number of ladders + ** ladderTypes array of ladder types + **/ + + TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation) { + + Bool_t isFirstPartOfHalfUnit = kFALSE; + + // TString name = Form("Unit%02d", iUnit); // 0,1,2,3,4,5,6,7 - Unit00 missing in output + // TString name = Form("Unit%02d", iUnit+1); // 1,2,3,4,5,6,7,8 + + TGeoVolume* unit = gGeoMan->GetVolume(unitName[iUnit]); + if ( ! unit ) // if it does not yet exist, create a new one + { + unit = new TGeoVolumeAssembly(unitName[iUnit]); + isFirstPartOfHalfUnit = kTRUE; + } + + // --- Some local variables + TGeoBBox* ladderShape = NULL; + TGeoVolume* ladder = NULL; + TString ladderName; + Double_t subtractedVal; + + // --- Determine size of unit from ladders + Double_t statX = 0.; + // Double_t statY = 0.; + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { +// v19a Int_t ladderType = ladderTypes[iLadder]%100; +// Int_t ladderType = ladderTypes[iLadder]%1000; + Int_t ladderType = ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100; + if (ladderType > 0) + { +// v19a ladderName = Form("LadderType%02d", ladderType); + ladderName = Form("LadderType%03d", ladderType); + ladder = gGeoManager->GetVolume(ladderName); + if ( ! ladder ) Fatal("ConstructUnit", + Form("Volume %s not found", ladderName.Data())); + ladderShape = (TGeoBBox*) ladder->GetShape(); + statX += 2. * ladderShape->GetDX(); + // statY = TMath::Max(statY, 2. * ladderShape->GetDY()); + } + else + statX += gkSensorSizeX; // empty ladder in unit + } + statX -= Double_t(nLadders-1) * gkLadderOverlapX; + + // --- Place ladders in unit + cout << "xPos0: " << statX << endl; + Double_t xPos = -0.5 * statX; + cout << "xPos1: " << xPos << endl; + Double_t yPos = 0.; + Double_t zPos = 0.; + + Double_t maxdz = 0.; + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { // find maximum dz in this unit +// v19a Int_t ladderType = ladderTypes[iLadder]%100; +// Int_t ladderType = ladderTypes[iLadder]%1000; + Int_t ladderType = ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100; + if (ladderType > 0) + { +// v19a ladderName = Form("LadderType%02d", ladderType); + ladderName = Form("LadderType%03d", ladderType); + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + if (maxdz < ladderShape->GetDZ()) + maxdz = ladderShape->GetDZ(); + } + } + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { +// v19a Int_t ladderType = ladderTypes[iLadder]%100; +// Int_t ladderType = ladderTypes[iLadder]%1000; + Int_t ladderType = ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100; + if (ladderType > 0) + { +// v19a ladderName = Form("LadderType%02d", ladderType); + ladderName = Form("LadderType%03d", ladderType); + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + xPos += ladderShape->GetDX(); + cout << "xPos2: " << xPos << endl; + yPos = 0.; // vertically centred + TGeoRotation* rot = new TGeoRotation(); + + if (gkConstructFrames) + // DEDE + subtractedVal = sqrt(2.)*gkFrameThickness/2. + ladderShape->GetDX(); + // subtractedVal = 2*gkSectorGapZFrame + sqrt(2.)*gkFrameThickness/2. + ladderShape->GetDX(); + else + subtractedVal = 0.; + + // zPos = 0.5 * gkLadderGapZ + (ladderShape->GetDZ()-subtractedVal/2.); // non z-aligned ladders + zPos = 0.5 * gkLadderGapZ + (2*maxdz-ladderShape->GetDZ()-subtractedVal/2.); // z-aligned ladders + +// v19a cout << "DE ladder" << ladderTypes[iLadder]%100 + cout << "DE ladder" << ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100 + << " dx: " << ladderShape->GetDX() + << " dy: " << ladderShape->GetDY() + << " dz: " << ladderShape->GetDZ() + << " max dz: " << maxdz << endl; + +// v19a cout << "DE ladder" << ladderTypes[iLadder]%100 + cout << "DE ladder" << ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100 + << " fra: " << gkFrameThickness/2. + << " sub: " << subtractedVal + << " zpo: " << zPos << endl << endl; + +// v19a if (ladderTypes[iLadder]/100 == 1) // flip some of the ladders to reproduce the CAD layout + if (ladderTypes[iLadder]/1000 == 1) // flip some of the ladders to reproduce the CAD layout + rot->RotateY(180.); + else + zPos = -zPos; + + if (!isFirstPartOfHalfUnit) + // zPos += 10; + zPos += 10.5; // v19d +// zPos += 11.0; // v19e + + TGeoCombiTrans* trans = new TGeoCombiTrans(xPos, yPos, zPos, rot); +// start +// cout << "DEEE** iLadder " << iLadder << " " << nLadders/2 << " " << nLadders << endl; + + if (iSide == 0) + { + if (iLadder < nLadders/2) // right side - only half unit -x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + else + { + if (iLadder >= nLadders/2) // left side - only half unit +x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + unit->GetShape()->ComputeBBox(); +// stop + xPos += ladderShape->GetDX() - gkLadderOverlapX; + cout << "xPos3: " << xPos << endl; + } + else + xPos += gkSensorSizeX - gkLadderOverlapX; + } + + return unit; + } +/** ======================================================================= **/ + + +/** =========================================================================== + ** Import and add the passive materials to the STS volume + **/ +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile) +{ + TString passiveName = TString("sts_passive_") + geoTag; + TString basePath = gSystem->Getenv("VMCWORKDIR"); + TString relPath = "/geometry/sts/passive/" + passiveName + ".gdml"; + TString passiveFileName = basePath + relPath; + infoFile << std::endl << std::endl; + infoFile << "Importing STS passive materials from GDML file '" << relPath << "'." << std::endl; + + TGDMLParse parser; + TGeoVolume* gdmlVolume = parser.GDMLReadFile(passiveFileName); + PostProcessGdml(gdmlVolume); + gdmlVolume->SetName(passiveName); + + TGeoTranslation* passiveTrans = new TGeoTranslation(0., 0., 4.68); + infoFile << "Passive assembly is translated for Z=4.68 cm downstream with respect to parent volume" << std::endl << std::endl; + + gdmlVolume->GetShape()->ComputeBBox(); + CheckVolume(gdmlVolume, infoFile); + + infoFile << std::endl; + for (Int_t iNode = 0; iNode < gdmlVolume->GetNdaughters(); iNode++) { + CheckVolume(gdmlVolume->GetNode(iNode)->GetVolume(), infoFile, kFALSE); + } + + stsVolume->AddNode(gdmlVolume, stsVolume->GetNdaughters(), passiveTrans, ""); +} + +/** =========================================================================== + ** Assign visual properties to the imported gdml volumes + **/ +void PostProcessGdml(TGeoVolume* gdmlVolume) +{ + const UInt_t kPOBColor = kRed-6; + const UInt_t kPOBTransparency = 0;// 5; + + const UInt_t kFEBColor = kOrange-6; + const UInt_t kFEBTransparency = 0;// 5; + + const UInt_t kUnitColor = kCyan-10; + const UInt_t kUnitTransparency = 0;// 5; + + const UInt_t kCfColor = kGray+3; + const UInt_t kCfTransparency = 0;// 10; + + // name <Color, Transparency> + std::map<std::string, std::tuple<UInt_t,UInt_t> > props { + { "passive_POB", std::tuple<UInt_t,UInt_t> {kPOBColor, kPOBTransparency} }, + { "passive_FEB", std::tuple<UInt_t,UInt_t> {kFEBColor, kFEBTransparency} }, + { "passive_unit", std::tuple<UInt_t,UInt_t> {kUnitColor, kUnitTransparency} }, + { "passive_Box_Wall", std::tuple<UInt_t,UInt_t> {kCfColor, kCfTransparency} }, + { "passive_Box_Wall_Front_CF2", std::tuple<UInt_t,UInt_t> {kCfColor-3, kCfTransparency} }, + }; + + // Match volume name and apply visual properties + const TObjArray* volumes = gGeoManager->GetListOfVolumes(); + for (auto& entry : props) { + TIter next(volumes); + TGeoVolume *vol = nullptr; + while ((vol=(TGeoVolume*)next())) { + if (TString(vol->GetName()).Contains(entry.first.c_str())) { + vol->SetLineColor(std::get<0>(entry.second)); + vol->SetTransparency(std::get<1>(entry.second)); + } + } + } +} + +/** =========================================================================== + ** Volume information for debugging + **/ +void CheckVolume(TGeoVolume* volume) { + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + cout << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) cout << ", assembly"; + else { + if ( volume->GetMedium() ) + cout << ", medium " << volume->GetMedium()->GetName(); + else cout << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + cout << endl; + if ( volume->GetNdaughters() ) { + cout << "Daughters: " << endl; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) { + TGeoNode* node = volume->GetNode(iNode); + TGeoBBox* shape = (TGeoBBox*) node->GetVolume()->GetShape(); + cout << setw(15) << node->GetName() << ", size " + << fixed << setprecision(3) + << setw(6) << 2. * shape->GetDX() << " x " + << setw(6) << 2. * shape->GetDY() << " x " + << setw(6) << 2. * shape->GetDZ() << ", position ( "; + TGeoMatrix* matrix = node->GetMatrix(); + const Double_t* pos = matrix->GetTranslation(); + cout << setfill(' '); + cout << fixed << setw(8) << pos[0] << ", " + << setw(8) << pos[1] << ", " + << setw(8) << pos[2] << " )" << endl; + } + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Volume information for output to file + **/ +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren) { + if ( ! file ) return; + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + file << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) file << ", assembly"; + else { + if ( volume->GetMedium() ) + file << ", medium " << volume->GetMedium()->GetName(); + else file << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + file << endl; + if ( volume->GetNdaughters() && listChildren) { + file << "Contains: "; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) + file << volume->GetNode(iNode)->GetVolume()->GetName() << " "; + file << endl; + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Calculate beam pipe outer radius for a given z + **/ +Double_t BeamPipeRadius(Double_t z) { + if ( z < gkPipeZ2 ) return gkPipeR1; + Double_t slope = (gkPipeR3 - gkPipeR2 ) / (gkPipeZ3 - gkPipeZ2); + return gkPipeR2 + slope * (z - gkPipeZ2); +} +/** ======================================================================= **/ + + + +/** ======================================================================= **/ +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + TGeoBBox* frameVertPillarShp; + + Double_t t = gkFrameThickness/2.; + + // --- Main vertical pillars +// TGeoBBox* frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, gkFrameStep/2., t); // square crossection, along y +// TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); +// frameVertPillarVol->SetLineColor(kGreen); +// frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoTranslation(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2.)); +// frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoTranslation(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkCylindricalFrames) + // TGeoBBox* frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", 0, t, gkFrameStep/2.); // circle crossection, along z + frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", gkCylinderDiaInner/2., gkCylinderDiaOuter/2., gkFrameStep/2.); // circle crossection, along z + else + frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, t, gkFrameStep/2.); // square crossection, along z + TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); + frameVertPillarVol->SetLineColor(kGreen); + + TGeoRotation* xRot90 = new TGeoRotation; + xRot90->RotateX(90.); + frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoCombiTrans(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoCombiTrans(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + + // TGeoRotation* vertRot = new TGeoRotation(name + "_vertpillar_rot_1", 90., 45., -90.); + TGeoRotation* vertRot = new TGeoRotation; + vertRot->RotateX(90.); + vertRot->RotateY(45.); + frameBoxVol->AddNode(frameVertPillarVol, 3, new TGeoCombiTrans(name + "_vertpillar_pos_3", 0., 0., (x-sqrt(2.)*t)/2., vertRot)); + + // --- Small horizontal pillar + // TGeoBBox* frameHorPillarShp = new TGeoBBox(name + "_horpillar_shape", x-2.*t, gkThinFrameThickness/2., gkThinFrameThickness/2.); + // TGeoVolume* frameHorPillarVol = new TGeoVolume(name + "_horpillar", frameHorPillarShp, framesMaterial); + // frameHorPillarVol->SetLineColor(kCyan); + // frameBoxVol->AddNode(frameHorPillarVol, 1, new TGeoTranslation(name + "_horpillar_pos_1", 0., -gkFrameStep/2.+gkThinFrameThickness/2., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkConstructSmallFrames) { + + // --- Small sloping pillars + TGeoPara* frameSlopePillarShp = new TGeoPara(name + "_slopepillar_shape", + (x-2.*t)/TMath::Cos(31.4/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., 31.4, 0., 90.); + TGeoVolume* frameSlopePillarVol = new TGeoVolume(name + "_slopepillar", frameSlopePillarShp, framesMaterial); + frameSlopePillarVol->SetLineColor(kCyan); + TGeoRotation* slopeRot = new TGeoRotation(name + "_slopepillar_rot_1", 0., 0., 31.4); + TGeoRotation* slopeRot2 = new TGeoRotation(name + "_slopepillar_rot_2", 0., 0., -31.4); + TGeoCombiTrans* slopeTrRot = new TGeoCombiTrans(name + "_slopepillar_posrot_1", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot); + TGeoCombiTrans* slopeTrRot2 = new TGeoCombiTrans(name + "_slopepillar_posrot_2", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot2); + + frameBoxVol->AddNode(frameSlopePillarVol, 1, slopeTrRot); + frameBoxVol->AddNodeOverlap(frameSlopePillarVol, 2, slopeTrRot2); + + + Double_t angl = 23.; + // --- Small sub pillar + TGeoPara* frameSubPillarShp = new TGeoPara(name + "_subpillar_shape", + (sqrt(2)*(x/2.-t)-t/2.)/TMath::Cos(angl/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., angl, 0., 90.); + TGeoVolume* frameSubPillarVol = new TGeoVolume(name + "_subpillar", frameSubPillarShp, framesMaterial); + frameSubPillarVol->SetLineColor(kMagenta); + + Double_t posZ = t * (1. - 3. / ( 2.*sqrt(2.) )); + + // one side of X direction + TGeoRotation* subRot1 = new TGeoRotation(name + "_subpillar_rot_1", 90., 45., -90.+angl); + TGeoCombiTrans* subTrRot1 = new TGeoCombiTrans(name + "_subpillar_posrot_1", -(-x/2.+t-t/(2.*sqrt(2.))), 1., posZ, subRot1); + + TGeoRotation* subRot2 = new TGeoRotation(name + "_subpillar_rot_2", 90., -90.-45., -90.+angl); + TGeoCombiTrans* subTrRot2 = new TGeoCombiTrans(name + "_subpillar_posrot_2", -(-x/2.+t-t/(2.*sqrt(2.))), -1., posZ, subRot2); + + // other side of X direction + TGeoRotation* subRot3 = new TGeoRotation(name + "_subpillar_rot_3", 90., 90.+45., -90.+angl); + TGeoCombiTrans* subTrRot3 = new TGeoCombiTrans(name + "_subpillar_posrot_3", -x/2.+t-t/(2.*sqrt(2.)), 1., posZ, subRot3); + + TGeoRotation* subRot4 = new TGeoRotation(name + "_subpillar_rot_4", 90., -45., -90.+angl); + TGeoCombiTrans* subTrRot4 = new TGeoCombiTrans(name + "_subpillar_posrot_4", -x/2.+t-t/(2.*sqrt(2.)), -1., posZ, subRot4); + + frameBoxVol->AddNode(frameSubPillarVol, 1, subTrRot1); + frameBoxVol->AddNode(frameSubPillarVol, 2, subTrRot2); + frameBoxVol->AddNode(frameSubPillarVol, 3, subTrRot3); + frameBoxVol->AddNode(frameSubPillarVol, 4, subTrRot4); + // frameBoxVol->GetShape()->ComputeBBox(); + } + + return frameBoxVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructSmallCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 6., 7.6, 6., 6.04, 0., 180.); +// TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + Double_t radius = 3.0; + Double_t thickness = 0.04; // 0.4 mm +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 3., 3.2, 3., 3.2, 0., 180.); + TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, radius, radius+thickness, radius, radius+thickness, 0., 180.); + TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + TGeoCombiTrans* M = new TGeoCombiTrans ("M"); + M->RotateX (45.); + M->SetDy (-5.575); + M->SetDz (6.935); + M->RegisterYourself(); + + TGeoShape* coneShp = new TGeoCompositeShape ("Cone_shp", "A-B:M"); + TGeoVolume* coneVol = new TGeoVolume ("Cone", coneShp, framesMaterial); + coneVol->SetLineColor(kGreen); +// coneVol->RegisterYourself(); + +// // --- Inner cone +// Double_t thickness = 0.02; +// Double_t thickness2 = 0.022; +// // TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); +// TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 3.+thickness, 4.6-thickness2, 2.99+thickness, 3.05-thickness2, 0., 180.); +// +// TGeoCombiTrans* M2 = new TGeoCombiTrans ("M2"); +// M2->RotateX (45.); +// M2->SetDy (-5.575+thickness*sqrt(2.)); +// M2->SetDz (6.935); +// M2->RegisterYourself(); +// +// TGeoShape* coneShp2 = new TGeoCompositeShape ("Cone2_shp", "A2-B:M2"); +// TGeoVolume* coneVol2 = new TGeoVolume ("Cone2", coneShp2, gStsMedium); +// coneVol2->SetLineColor(kGreen); +//// coneVol2->RegisterYourself(); +// +// coneVol->AddNode(coneVol2, 1); + + return coneVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructBigCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone + TGeoConeSeg* bA = new TGeoConeSeg ("bA", coneDz, 6., 7.6, 6., 6.04, 0., 180.); + TGeoBBox* bB = new TGeoBBox ("bB", 8., 6., 10.); + + TGeoCombiTrans* bM = new TGeoCombiTrans ("bM"); + bM->RotateX (45.); + bM->SetDy (-5.575); + bM->SetDz (6.935); + bM->RegisterYourself(); + + TGeoShape* coneBigShp = new TGeoCompositeShape ("ConeBig_shp", "bA-bB:bM"); + TGeoVolume* coneBigVol = new TGeoVolume ("ConeBig", coneBigShp, framesMaterial); + coneBigVol->SetLineColor(kGreen); +// coneBigVol->RegisterYourself(); + + // --- Inner cone + Double_t thickness = 0.02; + Double_t thickness2 = 0.022; + TGeoConeSeg* bA2 = new TGeoConeSeg ("bA2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); + + TGeoCombiTrans* bM2 = new TGeoCombiTrans ("bM2"); + bM2->RotateX (45.); + bM2->SetDy (-5.575+thickness*sqrt(2.)); + bM2->SetDz (6.935); + bM2->RegisterYourself(); + + TGeoShape* coneBigShp2 = new TGeoCompositeShape ("ConeBig2_shp", "bA2-bB:bM2"); + TGeoVolume* coneBigVol2 = new TGeoVolume ("ConeBig2", coneBigShp2, gStsMedium); + coneBigVol2->SetLineColor(kGreen); +// coneBigVol2->RegisterYourself(); + + coneBigVol->AddNode(coneBigVol2, 1); + + return coneBigVol; +} + +/** ======================================================================= **/ diff --git a/macro/sts/geometry/create_stsgeo_v19k.C b/macro/sts/geometry/create_stsgeo_v19k.C new file mode 100644 index 0000000000000000000000000000000000000000..177bfc8962135e8e9ed2ddd6d72912f91874aa19 --- /dev/null +++ b/macro/sts/geometry/create_stsgeo_v19k.C @@ -0,0 +1,2371 @@ +/****************************************************************************** + ** Creation of STS geometry in ROOT format (TGeo). + ** + ** @file create_stsgeo_v19k.C + ** @author Volker Friese <v.friese@gsi.de> + ** @since 15 June 2012 + ** @date 09.05.2014 + ** @author Tomas Balog <T.Balog@gsi.de> + ** + ** v19k: ladders on upstream side of units get upper half ladders installed first, + ** ladders on downstream side of units get lower half ladders installed first, + ** this saves 1.5 mm space in z per station, 12 mm in total (LadderType went from 3 to 4 digits) + ** parameters : delta Z prime = 1.00 cm - delta Z pitch = 0.15 cm + ** v19j: use overlap and distance parameters from CAD model + ** v19h: put STS stations from v19d at z-positions = 260; 365; 470; 575; 680; 785; 890; 995 mm + ** v19g: place a box with services around v19e + ** v19f: place a box with services around v19d + ** v19e: increase spacing between stations by +10 mm from 100 mm + ** v19d: increase spacing between stations by + 5 mm from 100 mm + ** v19c: drop station 8 and increase spacing between remaining 7 stations from 10 cm to 12 c + ** v19b: introduce FEB orientation in ladder numbering (LadderType went from 2 to 3 digits) + ** v19a: import passive materials from gdml file + ** extend CF ladder structures and cables towards FEE plane + ** change CF ladder frame shape + ** v18d: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu (based on v18b) + ** v18c: fixed cut-out windows in cooling plates, improve the box shape/materials + ** v18b: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu + ** v18a: adds 9 cooling/holding plates and a box around the setup + ** v16g: v16g is the new standard geometry from November 2017 + ** v16g: switch from stations to units - left / right ("Unit01L", "Unit01R") + ** v16f: switch from stations to units + ** - split in upstream / downstream and left / right parts + ** - named Unit0xUR, Unit0xUL, Unit0xDR, Unit0xDL + ** v16e: switch from stations to units - upstream / downstream ("Unit01U", "Unit01D") + ** v16d: skip keeping volumes of sts and stations + ** v16c: like v16b, but senors of ladders beampipe next to beampipe + ** shifted closer to the pipe, like in the CAD model + ** v16b: like v16a, but yellow sensors removed + ** v16a: derived from v15c (no cones), but with sensor types renamed: + ** 2 -> 1, 3 -> 2, 4 -> 3, 5 -> 4, 1 -> 5 + ** + ** v15c: as v15b without cones + ** v15b: introduce modified carbon ladders from v13z + ** v15a: with flipped ladder orientation for stations 0,2,4,6 to match CAD design + ** + ** TODO: + ** + ** DONE: + ** v15b - use carbon macaroni as ladder support + ** v15b - introduce a small gap between lowest sensor and carbon ladder + ** v15b - build small cones for the first 2 stations + ** v15b - within a station the ladders of adjacent units should not touch eachother - set gkLadderGapZ to 10 mm + ** v15b - for all ladders set an even number of ladder elements + ** v15b - z offset of cones to ladders should not be 0.3 by default, but 0.26 + ** v15b - within a station the ladders should be aligned in z, defined either by the unit or the ladder with most sensors + ** v15b - get rid of cone overlap in stations 7 and 8 - done by adapting rHole size + ** + ** The geometry hierarachy is: + ** + ** 1. Sensors (see function CreateSensors) + ** The sensors are the active volumes and the lowest geometry level. + ** They are built as TGeoVolumes, shape box, material silicon. + ** x size is determined by strip pitch 58 mu and 1024 strips + ** plus guard ring of 1.3 mm at each border -> 6.1992 cm. + ** Sensor type 1 is half of that (3.0792 cm). + ** y size is determined by strip length (2.2 / 4.2 / 6.3 cm) plus + ** guard ring of 1.3 mm at top and bottom -> 2.46 / 4.46 / 6.46 cm. + ** z size is a parameter, to be set by gkSensorThickness. + ** + ** 2. Sectors (see function CreateSectors) + ** Sectors consist of several chained sensors. These are arranged + ** vertically on top of each other with a gap to be set by + ** gkChainGapY. Sectors are constructed as TGeoVolumeAssembly. + ** The sectors are auxiliary volumes used for proper placement + ** of the sensor(s) in the module. They do not show up in the + ** final geometry. + ** + ** 3. Modules (see function ConstructModule) + ** A module is a readout unit, consisting of one sensor or + ** a chain of sensors (see sector) and a cable. + ** The cable extends from the top of the sector vertically to the + ** top of the halfladder the module is placed in. The cable and module + ** volume thus depend on the vertical position of the sector in + ** the halfladder. The cables consist of silicon with a thickness to be + ** set by gkCableThickness. + ** Modules are constructed as TGeoVolume, shape box, medium gStsMedium. + ** The module construction can be switched off (gkConstructCables) + ** to reproduce older geometries. + ** + ** 4. Halfladders (see function ConstructHalfLadder) + ** A halfladder is a vertical assembly of several modules. The modules + ** are placed vertically such that their sectors overlap by + ** gkSectorOverlapY. They are displaced in z direction to allow for the + ** overlap in y by gkSectorGapZ. + ** The horizontal placement of modules in the halfladder can be choosen + ** to left aligned or right aligned, which only matters if sensors of + ** different x size are involved. + ** Halfladders are constructed as TGeoVolumeAssembly. + ** + ** 5. Ladders (see function CreateLadders and ConstructLadder) + ** A ladder is a vertical assembly of two halfladders, and is such the + ** vertical building block of a station. The second (bottom) half ladder + ** is rotated upside down. The vertical arrangement is such that the + ** inner sectors of the two halfladders have the overlap gkSectorOverlapY + ** (function CreateLadder) or that there is a vertical gap for the beam + ** hole (function CreateLadderWithGap). + ** Ladders are constructed as TGeoVolumeAssembly. + ** + ** 6. Stations (see function ConstructStation) + ** A station represents one layer of the STS geometry: one measurement + ** at (approximately) a given z position. It consist of several ladders + ** arranged horizontally to cover the acceptance. + ** The ladders are arranged such that there is a horizontal overlap + ** between neighbouring ladders (gkLadderOverLapX) and a vertical gap + ** to allow for this overlap (gkLadderGapZ). Each second ladder is + ** rotated around its y axis to face away from or into the beam. + ** Stations are constructed as TGeoVolumes, shape box minus tube (for + ** the beam hole), material gStsMedium. + ** + ** 7. STS + ** The STS is a volume hosting the entire detectors system. It consists + ** of several stations located at different z positions. + ** The STS is constructed as TGeoVolume, shape box minus cone (for the + ** beam pipe), material gStsMedium. The size of the box is computed to + ** enclose all stations. + *****************************************************************************/ + + +// Remark: With the proper steering variables, this should exactly reproduce +// the geometry version v11b of A. Kotynia's described in the ASCII format. +// The only exception is a minimal difference in the z position of the +// sectors/sensors. This is because of ladder types 2 and 4 containing the half +// sensors around the beam hole (stations 1,2 and 3). In v11b, the two ladders +// covering the beam hole cannot be transformed into each other by rotations, +// but only by a reflection. This means they are constructionally different. +// To avoid introducing another two ladder types, the difference in z position +// was accepted. + + +// Differences to v12: +// gkChainGap reduced from 1 mm to 0 +// gkCableThickness increased from 100 mum to 200 mum (2 cables per module) +// gkSectorOverlapY reduced from 3 mm to 2.4 mm +// New sensor types 05 and 06 +// New sector types 07 and 08 +// Re-definiton of ladders (17 types instead of 8) +// Re-definiton of station from new ladders + + +#include <iomanip> +#include <iostream> +#include "TGeoManager.h" + +#include "TGeoTube.h" +#include "TGeoPara.h" +#include "TGeoCone.h" +#include "TGeoTrd2.h" +#include "TGeoCompositeShape.h" +#include "TGeoXtru.h" +#include "TGeoPhysicalNode.h" + +// forward declarations +Int_t CreateSensors(); +Int_t CreateSectors(); +Int_t CreateLadders(); +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength); +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY); +TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ); +TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation); +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile); +void PostProcessGdml(TGeoVolume* gdmlTop); +void CheckVolume(TGeoVolume* volume); +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren = kTRUE); +Double_t BeamPipeRadius(Double_t z); +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x); +TGeoVolume* ConstructSmallCone(Double_t coneDz); +TGeoVolume* ConstructBigCone(Double_t coneDz); + +// ------------- Version highlight ----------------------------------- + +const std::string gVersionHighlight = R"( +Summary: + This version adds passive materials imported from GDML model to the STS geometry: + * Taken from and largely correspond to mechanical CAD drawings of the detector + * Thermal insulation box: + - made out of carbon sandwitch panel (2mm carbon fiber sheet + layer of carbon foam + 2mm carbon fiber sheet) + - front window of complex shape with interface to MVD / target chamber + - back window with large aperture (2000 x 1200 mm) square cut into carbon foam + * Structural units: + - made of 2 complex shape aluminum C-Frames, 15mm thick + - placed at 25, 35, ... ,105 cm absolute Z + - contain front-end and power distribution boxes with equivalent X_0 values + + Scripted geometry tweaks: + * Ladders and cables are extended towards the read-out planes having same lengths in respective rows + * Adjusted form and shape of carbon ladder structures from L-type to X-type + * Reduced verbosity of this file + + Sensor arrangement is the same as in version v16g + + !! Important for this version is the discrepancy from the mechanical CAD w.r.t. front wall. + The square window was replaced by a round one to avoid overlaps with present beam pipe designs, e.g. pipe_v16b_1e +)"; + +// ------------- Steering variables ----------------------------------- + +// ---> Horizontal width of sensors [cm] +const Double_t gkSensorSizeX = 6.2; // was 6.2092; // 6.2 - Oleg CAD 15/05/2020 + +// ---> Thickness of sensors [cm] +const Double_t gkSensorThickness = 0.03; + +// ---> Vertical gap between chained sensors [cm] +const Double_t gkChainGapY = 0.00; + +// ---> Thickness of cables [cm] +const Double_t gkCableThickness = 0.02; + +// ---> Horizontal overlap of neighbouring ladders [cm] +const Double_t gkLadderOverlapX = 0.25; // delta X - Oleg CAD 14/05/2020 + +// ---> Vertical overlap of neighbouring sectors in a ladder [cm] +const Double_t gkSectorOverlapY = 0.46; // delta Y - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring sectors in a ladder [cm] +const Double_t gkSectorGapZ = 0.12; // gap + thickness = pitch // delta Z pitch = 0.15 - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring ladders [cm] +const Double_t gkLadderGapZ = 1.00 - 0.15; // for asym // 1.0 for sym // delta Z prime - Oleg CAD 14/05/2020 + +// ---> Gap in z between lowest sector to carbon support structure [cm] +const Double_t gkSectorGapZFrame = 0.280 - 0.025; // Oleg CAD 05/05/2020 // there is a 2.8 mm gap between the bottom side of the sensor and the top ledge of the carbon ladder + +// ---> Switch to construct / not to construct readout cables +const Bool_t gkConstructCables = kTRUE; + +// ---> Switch to construct / not to construct frames +const Bool_t gkConstructCones = kFALSE; // kTRUE; // switch this false by default for v15c and v16x +const Bool_t gkConstructFrames = kTRUE; // kFALSE; // switch this true by default for v15c and v16x +const Bool_t gkConstructSmallFrames = kTRUE; // kFALSE; +const Bool_t gkCylindricalFrames = kTRUE; // kFALSE; + +// ---> Size of the frame +const Double_t gkFrameThickness = 0.2; +const Double_t gkThinFrameThickness = 0.05; +const Double_t gkFrameStep = 4.0; // size of frame cell along y direction + +const Double_t gkCylinderDiaInner = 0.07; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) +const Double_t gkCylinderDiaOuter = 0.15; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) + +// ---> Switch to import / not to import the Passive materials from GDML file +//const Bool_t gkImportPassive = kTRUE; +const Bool_t gkImportPassive = kFALSE; + +// ---------------------------------------------------------------------------- + + +// -------------- Parameters of beam pipe in the STS region -------------- +// ---> Needed to compute stations and STS such as to avoid overlaps +const Double_t gkPipeZ1 = 22.0; +const Double_t gkPipeR1 = 1.8; +const Double_t gkPipeZ2 = 50.0; +const Double_t gkPipeR2 = 1.8; +const Double_t gkPipeZ3 = 125.0; +const Double_t gkPipeR3 = 5.5; + +//DE const Double_t gkPipeZ1 = 27.0; +//DE const Double_t gkPipeR1 = 1.05; +//DE const Double_t gkPipeZ2 = 160.0; +//DE const Double_t gkPipeR2 = 3.25; +// ---------------------------------------------------------------------------- + +//TString unitName[16] = // names of units for v16e +// { "Unit00D", +// "Unit01U", "Unit01D", +// "Unit02U", "Unit02D", +// "Unit03U", "Unit03D", +// "Unit04U", "Unit04D", +// "Unit05U", "Unit05D", +// "Unit06U", "Unit06D", +// "Unit07U", "Unit07D", +// "Unit08U" }; + +//TString unitName[32] = // names of units for v16f +// { "Unit00DR", "Unit00DL", +// "Unit01UR", "Unit01UL", "Unit01DR", "Unit01DL", +// "Unit02UR", "Unit02UL", "Unit02DR", "Unit02DL", +// "Unit03UR", "Unit03UL", "Unit03DR", "Unit03DL", +// "Unit04UR", "Unit04UL", "Unit04DR", "Unit04DL", +// "Unit05UR", "Unit05UL", "Unit05DR", "Unit05DL", +// "Unit06UR", "Unit06UL", "Unit06DR", "Unit06DL", +// "Unit07UR", "Unit07UL", "Unit07DR", "Unit07DL", +// "Unit08UR", "Unit08UL" }; + +TString unitName[32] = // names of units for v16g - while merging D and U parts + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", "Unit01R", "Unit01L", + "Unit02R", "Unit02L", "Unit02R", "Unit02L", + "Unit03R", "Unit03L", "Unit03R", "Unit03L", + "Unit04R", "Unit04L", "Unit04R", "Unit04L", + "Unit05R", "Unit05L", "Unit05R", "Unit05L", + "Unit06R", "Unit06L", "Unit06R", "Unit06L", + "Unit07R", "Unit07L", "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +TString unitName18[18] = // names of units for v16g + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", + "Unit02R", "Unit02L", + "Unit03R", "Unit03L", + "Unit04R", "Unit04L", + "Unit05R", "Unit05L", + "Unit06R", "Unit06L", + "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +// ------------- Other global variables ----------------------------------- +// ---> STS medium (for every volume except silicon) +TGeoMedium* gStsMedium = NULL; // will be set later +// ---> TGeoManager (too lazy to write out 'Manager' all the time +TGeoManager* gGeoMan = NULL; // will be set later +// ---------------------------------------------------------------------------- + + + + +// ============================================================================ +// ====== Main function ===== +// ============================================================================ + +void create_stsgeo_v19k(const char* geoTag="v19k") +{ + + // ------- Geometry file name (output) ---------------------------------- + TString geoFileName = "sts_"; + geoFileName = geoFileName + geoTag + ".geo.root"; + // -------------------------------------------------------------------------- + + + // ------- Open info file ----------------------------------------------- + TString infoFileName = geoFileName; + infoFileName.ReplaceAll("root", "info"); + fstream infoFile; + infoFile.open(infoFileName.Data(), fstream::out); + infoFile << "STS geometry created with create_stsgeo_v19k.C" << endl; + infoFile << gVersionHighlight << endl; + infoFile << "Global variables: " << endl; + infoFile << "Sensor thickness = " << gkSensorThickness << " cm" << endl; + infoFile << "Vertical gap in sensor chain = " + << gkChainGapY << " cm" << endl; + infoFile << "Vertical overlap of sensors = " + << gkSectorOverlapY << " cm" << endl; + infoFile << "Gap in z between neighbour sensors = " + << gkSectorGapZ << " cm" << endl; + infoFile << "Horizontal overlap of sensors = " + << gkLadderOverlapX << " cm" << endl; + infoFile << "Gap in z between neighbour ladders = " + << gkLadderGapZ << " cm" << endl; + if ( gkConstructCables ) + infoFile << "Cable thickness = " << gkCableThickness << " cm" << endl; + else + infoFile << "No cables" << endl; + infoFile << endl; + infoFile << "Beam pipe: R1 = " << gkPipeR1 << " cm at z = " + << gkPipeZ1 << " cm" << endl; + infoFile << "Beam pipe: R2 = " << gkPipeR2 << " cm at z = " + << gkPipeZ2 << " cm" << endl; + infoFile << "Beam pipe: R3 = " << gkPipeR3 << " cm at z = " + << gkPipeZ3 << " cm" << endl; + // -------------------------------------------------------------------------- + + + // ------- Load media from media file ----------------------------------- + FairGeoLoader* geoLoad = new FairGeoLoader("TGeo","FairGeoLoader"); + FairGeoInterface* geoFace = geoLoad->getGeoInterface(); + TString geoPath = gSystem->Getenv("VMCWORKDIR"); + TString medFile = geoPath + "/geometry/media.geo"; + geoFace->setMediaFile(medFile); + geoFace->readMedia(); + gGeoMan = gGeoManager; + // -------------------------------------------------------------------------- + + + // ----------------- Get and create the required media ----------------- + FairGeoMedia* geoMedia = geoFace->getMedia(); + FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder(); + + // ---> air + FairGeoMedium* mAir = geoMedia->getMedium("air"); + if ( ! mAir ) Fatal("Main", "FairMedium air not found"); + geoBuild->createMedium(mAir); + TGeoMedium* air = gGeoMan->GetMedium("air"); + if ( ! air ) Fatal("Main", "Medium air not found"); + + // ---> silicon + FairGeoMedium* mSilicon = geoMedia->getMedium("silicon"); + if ( ! mSilicon ) Fatal("Main", "FairMedium silicon not found"); + geoBuild->createMedium(mSilicon); + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + if ( ! silicon ) Fatal("Main", "Medium silicon not found"); + + // ---> carbon + FairGeoMedium* mCarbon = geoMedia->getMedium("carbon"); + if ( ! mCarbon ) Fatal("Main", "FairMedium carbon not found"); + geoBuild->createMedium(mCarbon); + TGeoMedium* carbon = gGeoMan->GetMedium("carbon"); + if ( ! carbon ) Fatal("Main", "Medium carbon not found"); + + // ---> STSBoxCarbonFoam + FairGeoMedium* mSTSBoxCarbonFoam = geoMedia->getMedium("STSBoxCarbonFoam"); + if ( ! mSTSBoxCarbonFoam ) Fatal("Main", "FairMedium STSBoxCarbonFoam not found"); + geoBuild->createMedium(mSTSBoxCarbonFoam); + TGeoMedium* STSBoxCarbonFoam = gGeoMan->GetMedium("STSBoxCarbonFoam"); + if ( ! STSBoxCarbonFoam ) Fatal("Main", "Medium STSBoxCarbonFoam not found"); + + // ---> STSBoxCarbonFibre + FairGeoMedium* mSTSBoxCarbonFibre = geoMedia->getMedium("STSBoxCarbonFibre"); + if ( ! mSTSBoxCarbonFibre ) Fatal("Main", "FairMedium STSBoxCarbonFibre not found"); + geoBuild->createMedium(mSTSBoxCarbonFibre); + TGeoMedium* STSBoxCarbonFibre = gGeoMan->GetMedium("STSBoxCarbonFibre"); + if ( ! STSBoxCarbonFibre ) Fatal("Main", "Medium STSBoxCarbonFibre not found"); + + // ---> STScable + FairGeoMedium* mSTScable = geoMedia->getMedium("STScable"); + if ( ! mSTScable ) Fatal("Main", "FairMedium STScable not found"); + geoBuild->createMedium(mSTScable); + TGeoMedium* STScable = gGeoMan->GetMedium("STScable"); + if ( ! STScable ) Fatal("Main", "Medium STScable not found"); + + // ---> Aluminium + FairGeoMedium* mAluminium = geoMedia->getMedium("aluminium"); + if ( ! mAluminium ) Fatal("Main", "FairMedium aluminium not found"); + geoBuild->createMedium(mAluminium); + TGeoMedium* aluminium = gGeoMan->GetMedium("aluminium"); + if ( ! aluminium ) Fatal("Main", "Medium aluminium not found"); + + // --- + gStsMedium = air; + // -------------------------------------------------------------------------- + + + // -------------- Create geometry and top volume ------------------------- + gGeoMan = (TGeoManager*)gROOT->FindObject("FAIRGeom"); +// gGeoMan->SetName("STSgeom"); + TGeoVolume* top = new TGeoVolumeAssembly("top"); +// TGeoBBox* topbox= new TGeoBBox("", 120., 120., 120.); +// TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air")); + gGeoMan->SetTopVolume(top); + // -------------------------------------------------------------------------- + + + // -------------- Create media ------------------------------------------ + /* + cout << endl; + cout << "===> Creating media...."; + cout << CreateMedia(); + cout << " media created" << endl; + TList* media = gGeoMan->GetListOfMedia(); + for (Int_t iMedium = 0; iMedium < media->GetSize(); iMedium++ ) { + cout << "Medium " << iMedium << ": " + << ((TGeoMedium*) media->At(iMedium))->GetName() << endl; + } + gStsMedium = gGeoMan->GetMedium("air"); + if ( ! gStsMedium ) Fatal("Main", "medium sts_air not found"); + */ + // -------------------------------------------------------------------------- + + + // --------------- Create sensors --------------------------------------- + cout << endl << endl; + cout << "===> Creating sensors...." << endl << endl; + infoFile << endl << "Sensors: " << endl; + Int_t nSensors = CreateSensors(); + for (Int_t iSensor = 1; iSensor <= nSensors; iSensor++) { + TString name = Form("Sensor%02d",iSensor); + TGeoVolume* sensor = gGeoMan->GetVolume(name); + + // add color to sensors + if (iSensor == 1) + sensor->SetLineColor(kRed); + if (iSensor == 2) + sensor->SetLineColor(kGreen); + if (iSensor == 3) + sensor->SetLineColor(kBlue); + if (iSensor == 4) + sensor->SetLineColor(kAzure); + if (iSensor == 5) + sensor->SetLineColor(kYellow); + if (iSensor == 6) + sensor->SetLineColor(kYellow); + if (iSensor == 7) + sensor->SetLineColor(kYellow); + + CheckVolume(sensor); + CheckVolume(sensor, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create sectors -------------------------------------- + cout << endl << endl; + cout << "===> Creating sectors...." << endl; + // infoFile << endl << "Sectors: " << endl; + Int_t nSectors = CreateSectors(); + for (Int_t iSector = 1; iSector <= nSectors; iSector++) { + // cout << endl; + TString name = Form("Sector%02d", iSector); + TGeoVolume* sector = gGeoMan->GetVolume(name); + CheckVolume(sector); + // CheckVolume(sector, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create ladders -------------------------------------- + cout << endl << endl; + cout << "===> Creating ladders...." << endl; + infoFile << endl << "Ladders:" << endl; + + TString name = ""; + TGeoVolume* ladder; + + + Int_t nLadders = CreateLadders(); + + for (Int_t iLadder = 1; iLadder <= nLadders; iLadder++) { + cout << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType0%02d", iLadder); // v19b + name = Form("LadderType00%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF1: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType1%02d", iLadder); // v19b + name = Form("LadderType01%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF2: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType10%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF3: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType11%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF4: ladder name: " << name << endl << endl; + } + // -------------------------------------------------------------------------- + + + // ---------------- Create cones ---------------------------------------- + Double_t coneDz = 1.64; + TGeoVolume* coneSmallVolum = ConstructSmallCone(coneDz); + if (!coneSmallVolum) Fatal("ConstructSmallCone", "Volume Cone not found"); + TGeoVolume* coneBigVolum = ConstructBigCone(coneDz); + if (!coneBigVolum) Fatal("ConstructBigCone", "Volume Cone not found"); + // -------------------------------------------------------------------------- + + + // ---------------- Create stations ------------------------------------- + cout << endl << endl; + cout << "===> Creating stations...." << endl; + infoFile << endl << "Stations: " << endl; + Int_t angle = 0; + nLadders = 0; + Int_t ladderTypes[16]; // there are max 16 ladders in one layer + TGeoTranslation* statTrans = NULL; + + TGeoVolume *myunit[32]; // units + +// Int_t statPos[8] = { 30, 40, 50, 60, 70, 80, 90, 100 }; // z positions of stations +// Int_t statPos[16] = { 28, 32, 38, 42, 48, 52, 58, 62, +// 68, 72, 78, 82, 88, 92, 98,102 }; // z positions of units +// Int_t statPos[16] = { 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units +// Int_t statPos18[18] = { 30, 30, // expanded for placement of Unit00 +// 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units + // v19h + Double_t statPos[16] = { 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of units + Double_t statPos18[18] = { 26.0, 26.0, // expanded for placement of Unit00 + 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of unit + +// // v19d +// Double_t statPos[16] = { 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units +// Double_t statPos18[18] = { 30.0, 30.0, // expanded for placement of Unit00 +// 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units + +////Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.9 , 3.7 , 3.7 , 4.2 , 4.2 }; // size of cutouts in stations +// Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.43, 3.04, 3.35, 3.96, 4.2 }; // size of cutouts in stations, derived from gapXYZ[x][1]/2 + + Int_t cone_size[8] = { 0, 0, 0, 1, 1, 1, 1, 1 }; // size of cones: 0 = small, 1 = large + + Double_t cone_offset[2] = { 0.305, 0.285 }; + +// Int_t allLadderTypes[8][16]= +// { { -1, -1, -1, -1, 10, 109, 9, 101, 1, 109, 9, 110, -1, -1, -1, -1 }, // station 1 +// { -1, -1, 111, 10, 110, 9, 109, 2, 102, 9, 109, 10, 110, 11, -1, -1 }, // station 2 +// { -1, -1, 14, 113, 12, 112, 12, 103, 3, 112, 12, 112, 13, 114, -1, -1 }, // station 3 +// { -1, 15, 114, 13, 112, 12, 112, 4, 104, 12, 112, 12, 113, 14, 115, -1 }, // station 4 +// { -1, 119, 18, 117, 17, 116, 16, 105, 5, 116, 16, 117, 17, 118, 19, -1 }, // station 5 +// { -1, 19, 118, 17, 117, 16, 116, 6, 106, 16, 116, 17, 117, 18, 119, -1 }, // station 6 +// { 21, 119, 18, 120, 20, 120, 20, 107, 7, 120, 20, 120, 20, 118, 19, 121 }, // station 7 +// { 119, 17, 123, 22, 122, 22, 122, 8, 108, 22, 122, 22, 122, 23, 117, 19 } }; // station 8 + +//============================================================================================== + +// explanation: type xyzz +// where x = carbon ladder orientation +// where y = FEB box orientation +// where zz = sensor arrangement on ladder +// with FEB orientation - v19b + Int_t allUnitTypes[16][16]= + { { -1, -1, -1, -1, 10, 0, 9, 0, 101, 0, 109, 0, -1, -1, -1, -1 }, // unit00D Station01 00 + { -1, -1, -1, -1, 0, 1109, 0, 1101, 0, 1009, 0, 1010, -1, -1, -1, -1 }, // unit01U Station01 01 + + { -1, -1, 0, 10, 0, 9, 0, 2, 0, 109, 0, 110, 0, 111, -1, -1 }, // unit01D Station02 02 + { -1, -1, 1111, 0, 1110, 0, 1109, 0, 1002, 0, 1009, 0, 1010, 0, -1, -1 }, // unit02U Station02 03 + + { -1, -1, 14, 0, 12, 0, 12, 0, 103, 0, 112, 0, 113, 0, -1, -1 }, // unit02D Station03 04 + { -1, -1, 0, 1113, 0, 1112, 0, 1103, 0, 1012, 0, 1012, 0, 1014, -1, -1 }, // unit03U Station03 05 + + { -1, 15, 0, 13, 0, 12, 0, 4, 0, 112, 0, 112, 0, 114, 0, -1 }, // unit03D Station04 06 + { -1, 0, 1114, 0, 1112, 0, 1112, 0, 1004, 0, 1012, 0, 1013, 0, 1015, -1 }, // unit04U Station04 07 + + { -1, 0, 18, 0, 17, 0, 16, 0, 105, 0, 116, 0, 117, 0, 119, -1 }, // unit04D Station05 08 + { -1, 1119, 0, 1117, 0, 1116, 0, 1105, 0, 1016, 0, 1017, 0, 1018, 0, -1 }, // unit05U Station05 09 + + { -1, 19, 0, 17, 0, 16, 0, 6, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05D Station06 10 + { -1, 0, 1118, 0, 1117, 0, 1116, 0, 1006, 0, 1016, 0, 1017, 0, 1019, -1 }, // unit06U Station06 11 + + { 21, 0, 25, 0, 20, 0, 20, 0, 107, 0, 120, 0, 120, 0, 127, 0 }, // unit06D Station07 12 + { 0, 1127, 0, 1120, 0, 1120, 0, 1107, 0, 1020, 0, 1020, 0, 1025, 0, 1021 }, // unit07U Station07 13 + + { 0, 24, 0, 22, 0, 22, 0, 8, 0, 122, 0, 122, 0, 123, 0, 126 }, // unit07D Station08 14 + { 1126, 0, 1123, 0, 1122, 0, 1122, 0, 1008, 0, 1022, 0, 1022, 0, 1024, 0 } }; // unit08U Station08 15 + +//============================================================================================== + +// without FEB orientation - v19a +// v19a Int_t allUnitTypes[16][16]= +// v19a { { -1, -1, -1, -1, 10, 0, 9, 0, 1, 0, 9, 0, -1, -1, -1, -1 }, // unit00D Station01 00 +// v19a { -1, -1, -1, -1, 0, 109, 0, 101, 0, 109, 0, 110, -1, -1, -1, -1 }, // unit01U Station01 01 +// v19a { -1, -1, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, -1, -1 }, // unit01D Station02 02 +// v19a { -1, -1, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, -1, -1 }, // unit02U Station02 03 +// v19a { -1, -1, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, -1, -1 }, // unit02D Station03 04 +// v19a { -1, -1, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, -1, -1 }, // unit03U Station03 05 +// v19a { -1, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, -1 }, // unit03D Station04 06 +// v19a { -1, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, -1 }, // unit04U Station04 07 +// v19a { -1, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, -1 }, // unit04D Station05 08 +// v19a { -1, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05U Station05 09 +// v19a { -1, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, -1 }, // unit05D Station06 10 +// v19a { -1, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, -1 }, // unit06U Station06 11 +// v19a { 21, 0, 25, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 27, 0 }, // unit06D Station07 12 +// v19a { 0, 127, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 125, 0, 121 }, // unit07U Station07 13 +// v19a { 0, 24, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 26 }, // unit07D Station08 14 +// v19a { 126, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 124, 0 } }; // unit08U Station08 15 + + +// unitTypes[0] = { 0, 0, 0, 0, 10, 0, 9, 0, 1, 0, 9, 0, 0, 0, 0, 0 }; // unit 0D +// unitTypes[1] = { 0, 0, 0, 0, 0, 109, 0, 101, 0, 109, 0, 110, 0, 0, 0, 0 }; // unit 1U +// unitTypes[2] = { 0, 0, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, 0, 0 }; // unit 1D +// unitTypes[3] = { 0, 0, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, 0, 0 }; // unit 2U +// unitTypes[4] = { 0, 0, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, 0, 0 }; // unit 2D +// unitTypes[5] = { 0, 0, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, 0, 0 }; // unit 3U +// unitTypes[6] = { 0, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, 0 }; // unit 3D +// unitTypes[7] = { 0, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, 0 }; // unit 4U +// unitTypes[8] = { 0, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, 0 }; // unit 4D +// unitTypes[9] = { 0, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, 0 }; // unit 5U +// unitTypes[10] = { 0, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, 0 }; // unit 5D +// unitTypes[11] = { 0, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, 0 }; // unit 6U +// unitTypes[12] = { 21, 0, 18, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 19, 0 }; // unit 6D +// unitTypes[13] = { 0, 119, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 118, 0, 121 }; // unit 7U +// unitTypes[14] = { 0, 17, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 19 }; // unit 7D +// unitTypes[15] = { 119, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 117, 0 }; // unit 8U + + +// // generate unit +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) +// for (Int_t iLadder = 0; iLadder < 16; iLadder++) +// { +// allUnitTypes[iUnit][iLadder] = 0; +// if ((iUnit % 2 == 0) && (allLadderTypes[iUnit/2][iLadder] < 100)) // if carbon structure is oriented upstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// if ((iUnit % 2 == 1) && (allLadderTypes[iUnit/2][iLadder] >= 100)) // if carbon structure is oriented downstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// } + + + // dump unit + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << "DE unitTypes[" << iUnit << "] = { "; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + { + cout << allUnitTypes[iUnit][iLadder]; + if (iLadder < 15) + cout << ", "; + else + cout << " };"; + } + cout << endl; + } + + + // --- Units 01 - 16 + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << endl; + + nLadders = 0; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + if (allUnitTypes[iUnit][iLadder] >= 0) + { + ladderTypes[nLadders] = allUnitTypes[iUnit][iLadder]; + cout << "DE ladderTypes[" << nLadders << "] = " << allUnitTypes[iUnit][iLadder] << ";" << endl; + nLadders++; + } + myunit[iUnit*2+0] = ConstructUnit(0, iUnit*2+0, nLadders, ladderTypes, iUnit/2+1); + myunit[iUnit*2+1] = ConstructUnit(1, iUnit*2+1, nLadders, ladderTypes, iUnit/2+1); + +// if (gkConstructCones) { +// if (iUnit%2 == 0) +// angle = 90; +// else +// angle = -90; +// +// // upstream +// TGeoRotation* coneRot11 = new TGeoRotation; +// coneRot11->RotateZ(angle); +// coneRot11->RotateY(180); +// TGeoCombiTrans* conePosRot11 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-cone_offset[cone_size[iUnit]]-gkLadderGapZ/2., coneRot11); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 1, conePosRot11); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 1, conePosRot11); +// +// // downstream +// TGeoRotation* coneRot12 = new TGeoRotation; +// coneRot12->RotateZ(angle); +// TGeoCombiTrans* conePosRot12 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+cone_offset[cone_size[iUnit]]+gkLadderGapZ/2., coneRot12); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 2, conePosRot12); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 2, conePosRot12); +// +// myunit[iUnit]->GetShape()->ComputeBBox(); +// } + +// CheckVolume(myunit[iUnit]); +// CheckVolume(myunit[iUnit], infoFile); + if ((iUnit%2 == 0)||(iUnit == 15)) + { + CheckVolume(myunit[iUnit*2+0]); + CheckVolume(myunit[iUnit*2+0], infoFile); + CheckVolume(myunit[iUnit*2+1]); + CheckVolume(myunit[iUnit*2+1], infoFile); + } + infoFile << "Position z = " << statPos[iUnit] << endl; + } + // -------------------------------------------------------------------------- + + + // --------------- Create STS volume ------------------------------------ + cout << endl << endl; + cout << "===> Creating STS...." << endl; + +// // --- Determine size of STS box +// Double_t stsX = 0.; +// Double_t stsY = 0.; +// Double_t stsZ = 0.; +// Double_t stsBorder = 2*5.; // 5 cm space for carbon ladders on each side +// for (Int_t iStation = 1; iStation<=8; iStation++) { +// TString statName = Form("Station%02d", iStation); +// TGeoVolume* station = gGeoMan->GetVolume(statName); +// TGeoBBox* shape = (TGeoBBox*) station->GetShape(); +// stsX = TMath::Max(stsX, 2.* shape->GetDX() ); +// stsY = TMath::Max(stsY, 2.* shape->GetDY() ); +// cout << "Station " << iStation << ": Y " << stsY << endl; +// } +// // --- Some border around the stations +// stsX += stsBorder; +// stsY += stsBorder; +// stsZ = ( statPos[7] - statPos[0] ) + stsBorder; +// +// // --- Create box around the stations +// new TGeoBBox("stsBox", stsX/2., stsY/2., stsZ/2.); +// cout << "size of STS box: x " << stsX << " - y " << stsY << " - z " << stsZ << endl; +// +// // --- Create cone hosting the beam pipe +// // --- One straight section with constant radius followed by a cone +// Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +// Double_t z2 = gkPipeZ2; +// Double_t z3 = statPos[7] + 0.5 * stsBorder; // end of STS box +// Double_t r1 = BeamPipeRadius(z1); +// Double_t r2 = BeamPipeRadius(z2); +// Double_t r3 = BeamPipeRadius(z3); +// r1 += 0.01; // safety margin +// r2 += 0.01; // safety margin +// r3 += 0.01; // safety margin +// +// cout << endl; +// cout << z1 << " " << r1 << endl; +// cout << z2 << " " << r2 << endl; +// cout << z3 << " " << r3 << endl; +// +// cout << endl; +// cout << "station1 : " << BeamPipeRadius(statPos[0]) << endl; +// cout << "station2 : " << BeamPipeRadius(statPos[1]) << endl; +// cout << "station3 : " << BeamPipeRadius(statPos[2]) << endl; +// cout << "station4 : " << BeamPipeRadius(statPos[3]) << endl; +// cout << "station5 : " << BeamPipeRadius(statPos[4]) << endl; +// cout << "station6 : " << BeamPipeRadius(statPos[5]) << endl; +// cout << "station7 : " << BeamPipeRadius(statPos[6]) << endl; +// cout << "station8 : " << BeamPipeRadius(statPos[7]) << endl; +// +// // TGeoPcon* cutout = new TGeoPcon("stsCone", 0., 360., 3); // 2.*TMath::Pi(), 3); +// // cutout->DefineSection(0, z1, 0., r1); +// // cutout->DefineSection(1, z2, 0., r2); +// // cutout->DefineSection(2, z3, 0., r3); +// new TGeoTrd2("stsCone1", r1, r2, r1, r2, (z2-z1)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans1 = new TGeoTranslation("trans1", 0., 0., -(z3-z1)/2.+(z2-z1)/2.); +// trans1->RegisterYourself(); +// new TGeoTrd2("stsCone2", r2, r3, r2, r3, (z3-z2)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans2 = new TGeoTranslation("trans2", 0., 0., +(z3-z1)/2.-(z3-z2)/2.); +// trans2->RegisterYourself(); +// +////DE Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +////DE Double_t z2 = statPos[7] + 0.5 * stsBorder; // end of STS box +////DE Double_t slope = (gkPipeR2 - gkPipeR1) / (gkPipeZ2 - gkPipeZ1); +////DE Double_t r1 = gkPipeR1 + slope * (z1 - gkPipeZ1); // at start of STS +////DE Double_t r2 = gkPipeR1 + slope * (z2 - gkPipeZ1); // at end of STS +////DE r1 += 0.1; // safety margin +////DE r2 += 0.1; // safety margin +////DE // new TGeoCone("stsCone", stsZ/2., 0., r1, 0., r2); +////DE new TGeoTrd2("stsCone", r1, r2, r1, r2, stsZ/2.); + + + // // Create holding/cooling plates + // static std::vector< std::vector<Double_t> > plateSizes = { + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // }; + + // // 8-vertex cut-outs { minWidth, maxWidth, minHeight, maxHeight } + // static std::vector< std::vector<Double_t> > plateCutOuts = { + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 17.6, 47.6 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 49.0, 79.0 }, + // { 85.5,115.5, 51.5, 82.8 }, + // { 85.5,115.5, 59.0, 91.4 }, + // { 85.5,115.5, 68.0, 99.0 }, + // }; + + // for (Int_t iPlate = 0; iPlate < 9; iPlate++) { + // Int_t iUnit = iPlate * 2; + // TGeoBBox* outerPlate = new TGeoBBox(Form("outerPlate%02d",iPlate), + // plateSizes[iPlate][0], plateSizes[iPlate][1], plateSizes[iPlate][2]); + + // TGeoBBox* unitShapeR = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+0])->GetShape(); + // TGeoBBox* unitShapeL = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+1])->GetShape(); + + // Double_t maxDx = (unitShapeR->GetDX() + unitShapeL->GetDX()) / 2.; + // Double_t maxDy = TMath::Max(unitShapeR->GetDY(), unitShapeL->GetDY()); + // cout << maxDy << endl; + + // Double_t* cutOutX = new Double_t[8]; + // Double_t* cutOutY = new Double_t[8]; + + // cutOutX[0] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[0] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[1] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[1] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[2] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[2] = 1/2. * plateCutOuts[iPlate][2]; + // cutOutX[3] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[3] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[4] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[4] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[5] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[5] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[6] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[6] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[7] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[7] = 1/2. * plateCutOuts[iPlate][2]; + + // TGeoXtru* cutOutShape = new TGeoXtru(2); + // cutOutShape->SetName(Form("innerPlate%02d", iPlate)); + // cutOutShape->DefinePolygon(8, cutOutX, cutOutY); + // cutOutShape->DefineSection(0, -1*plateSizes[iPlate][2]-1e-7); + // cutOutShape->DefineSection(1, +1*plateSizes[iPlate][2]+1e-7); + + // TGeoShape* plateShape = new TGeoCompositeShape(Form("PlateShape%02d",iPlate), Form("outerPlate%02d-innerPlate%02d",iPlate,iPlate)); + // TGeoVolume* plate = new TGeoVolume(Form("Plate%02d", iPlate), plateShape, gGeoManager->GetMedium("aluminium")); + // plate->SetLineColor(kRed); + // plate->SetTransparency(65); + // plate->GetShape()->ComputeBBox(); + // } + + // --- Create STS volume + TString stsName = "sts_"; + stsName += geoTag; + +// TGeoShape* stsShape = new TGeoCompositeShape("stsShape", +// "stsBox-stsCone1:trans1-stsCone2:trans2"); +// TGeoVolume* sts = new TGeoVolume(stsName.Data(), stsShape, gStsMedium); + + Double_t stsBorder = 2 * 5.; + + TGeoVolume* sts = new TGeoVolumeAssembly(stsName.Data()); + + // --- Place stations in the STS + Double_t stsPosZ = 0.5 * ( statPos[15] + statPos[0] ); // todo units: update statPos[7] + // cout << "stsPosZ " << stsPosZ << " " << statPos[15] << " " << statPos[0] << "*****" << endl; + +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) { + for (Int_t iUnit = 0; iUnit < 18; iUnit++) { +// for (Int_t iUnit = 0; iUnit < 32; iUnit++) { + TGeoVolume* station = gGeoMan->GetVolume(unitName18[iUnit]); +// Double_t posZ = statPos[iUnit] - stsPosZ; + Double_t posZ = statPos18[iUnit] - stsPosZ; +// Double_t posZ = statPos[iUnit/2] - stsPosZ; + TGeoTranslation* trans = new TGeoTranslation(0., 0., posZ); + sts->AddNode(station, iUnit+1, trans); + sts->GetShape()->ComputeBBox(); + } + + // --- Import passive elements from GDML file + if (gkImportPassive) { + ImportPassive(sts, geoTag, infoFile); + } + + cout << endl; + CheckVolume(sts); + // -------------------------------------------------------------------------- + + + // --------------- Finish ----------------------------------------------- + TGeoTranslation* stsTrans = new TGeoTranslation(0., 0., stsPosZ); + top->AddNode(sts, 1, stsTrans); + top->GetShape()->ComputeBBox(); + cout << endl << endl; + + CheckVolume(top); + cout << endl << endl; + gGeoMan->CloseGeometry(); + gGeoMan->CheckOverlaps(0.0001); + gGeoMan->PrintOverlaps(); + gGeoMan->CheckOverlaps(0.0001, "s"); + gGeoMan->PrintOverlaps(); + gGeoMan->Test(); + + TFile* geoFile = new TFile(geoFileName, "RECREATE"); + top->Write(); + cout << endl; + cout << "Geometry " << top->GetName() << " written to " + << geoFileName << endl; + geoFile->Close(); + + TString geoFileName_ = "sts_"; + geoFileName_ = geoFileName_ + geoTag + "_geo.root"; + + geoFile = new TFile(geoFileName_, "RECREATE"); + gGeoMan->Write(); // use this is you want GeoManager format in the output + geoFile->Close(); + + TString geoFileName__ = "sts_"; + geoFileName_ = geoFileName__ + geoTag + "-geo.root"; + sts->Export(geoFileName_); + + geoFile = new TFile(geoFileName_, "UPDATE"); + stsTrans->Write(); + geoFile->Close(); + + // gGeoManager->FindVolumeFast("LadderType10_CarbonElement")->Draw("ogl"); + top->Draw("ogl"); + gGeoManager->SetVisLevel(8); + + infoFile.close(); + +} +// ============================================================================ +// ====== End of main function ===== +// ============================================================================ + + + + + +// **************************************************************************** +// ***** Definition of media, sensors, sectors and ladders ***** +// ***** ***** +// ***** Decoupled from main function for better readability ***** +// **************************************************************************** + + +/** =========================================================================== + ** Create media + ** + ** Currently created: air, active silicon, passive silion + ** + ** Not used for the time being + **/ +Int_t CreateMedia() { + + Int_t nMedia = 0; + Double_t density = 0.; + + // --- Material air + density = 1.205e-3; // [g/cm^3] + TGeoMixture* matAir = new TGeoMixture("sts_air", 3, density); + matAir->AddElement(14.0067, 7, 0.755); // Nitrogen + matAir->AddElement(15.999, 8, 0.231); // Oxygen + matAir->AddElement(39.948, 18, 0.014); // Argon + + // --- Material silicon + density = 2.33; // [g/cm^3] + TGeoElement* elSi = gGeoMan->GetElementTable()->GetElement(14); + TGeoMaterial* matSi = new TGeoMaterial("matSi", elSi, density); + + + // --- Air (passive) + TGeoMedium* medAir = new TGeoMedium("air", nMedia++, matAir); + medAir->SetParam(0, 0.); // is passive + medAir->SetParam(1, 1.); // is in magnetic field + medAir->SetParam(2, 20.); // max. field [kG] + medAir->SetParam(6, 0.001); // boundary crossing precision [cm] + + + // --- Active silicon for sensors + TGeoMedium* medSiAct = new TGeoMedium("silicon", + nMedia++, matSi); + medSiAct->SetParam(0, 1.); // is active + medSiAct->SetParam(1, 1.); // is in magnetic field + medSiAct->SetParam(2, 20.); // max. field [kG] + medSiAct->SetParam(6, 0.001); // boundary crossing precisison [cm] + + // --- Passive silicon for cables + TGeoMedium* medSiPas = new TGeoMedium("carbon", + nMedia++, matSi); + medSiPas->SetParam(0, 0.); // is passive + medSiPas->SetParam(1, 1.); // is in magnetic field + medSiPas->SetParam(2, 20.); // max. field [kG] + medSiPas->SetParam(6, 0.001); // boundary crossing precisison [cm] + + return nMedia; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sensors + ** + ** Sensors are created as volumes with box shape and active silicon as medium. + ** Four kinds of sensors: 3.2x2.2, 6.2x2.2, 6.2x4.2, 6.2x6.2 + **/ +Int_t CreateSensors() { + + Int_t nSensors = 0; + + Double_t xSize = 0.; + Double_t ySize = 0.; + Double_t zSize = gkSensorThickness; + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + + + // --- Sensor type 01: Small sensor (6.2 cm x 2.2 cm) + xSize = gkSensorSizeX; + ySize = 2.2; + TGeoBBox* shape_sensor01 = new TGeoBBox("sensor01", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor01", shape_sensor01, silicon); + nSensors++; + + + // --- Sensor type 02: Medium sensor (6.2 cm x 4.2 cm) + xSize = gkSensorSizeX; + ySize = 4.2; + TGeoBBox* shape_sensor02 = new TGeoBBox("sensor02", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor02", shape_sensor02, silicon); + nSensors++; + + + // --- Sensor type 03: Big sensor (6.2 cm x 6.2 cm) + xSize = gkSensorSizeX; + ySize = 6.2; + TGeoBBox* shape_sensor03 = new TGeoBBox("sensor03", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor03", shape_sensor03, silicon); + nSensors++; + + + // --- Sensor type 04: Big sensor (6.2 cm x 12.4 cm) + xSize = gkSensorSizeX; + ySize = 12.4; + TGeoBBox* shape_sensor04 = new TGeoBBox("sensor04", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor04", shape_sensor04, silicon); + nSensors++; + + + // below are extra small sensors, those are not available in the CAD model + + // --- Sensor Type 05: Half small sensor (4 cm x 2.5 cm) + xSize = 4.0; + ySize = 2.5; + TGeoBBox* shape_sensor05 = new TGeoBBox("sensor05", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor05", shape_sensor05, silicon); + nSensors++; + + + // --- Sensor type 06: Additional "in hole" sensor (3.1 cm x 4.2 cm) + xSize = 3.1; + ySize = 4.2; + TGeoBBox* shape_sensor06 = new TGeoBBox("sensor06", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor06", shape_sensor06, silicon); + nSensors++; + + + // --- Sensor type 07: Mini Medium sensor (1.5 cm x 4.2 cm) + xSize = 1.5; + ySize = 4.2; + TGeoBBox* shape_sensor07 = new TGeoBBox("sensor07", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor07", shape_sensor07, silicon); + nSensors++; + + + return nSensors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sectors + ** + ** A sector is either a single sensor or several chained sensors. + ** It is implemented as TGeoVolumeAssembly. + ** Currently available: + ** - single sensors of type 1 - 4 + ** - two chained sensors of type 4 + ** - three chained sensors of type 4 + **/ +Int_t CreateSectors() { + + Int_t nSectors = 0; + + TGeoVolume* sensor01 = gGeoMan->GetVolume("Sensor01"); + TGeoVolume* sensor02 = gGeoMan->GetVolume("Sensor02"); + TGeoVolume* sensor03 = gGeoMan->GetVolume("Sensor03"); + TGeoVolume* sensor04 = gGeoMan->GetVolume("Sensor04"); + TGeoVolume* sensor05 = gGeoMan->GetVolume("Sensor05"); + TGeoVolume* sensor06 = gGeoMan->GetVolume("Sensor06"); + TGeoVolume* sensor07 = gGeoMan->GetVolume("Sensor07"); + // TGeoBBox* box4 = (TGeoBBox*) sensor04->GetShape(); + + // --- Sector type 1: single sensor of type 1 + TGeoVolumeAssembly* sector01 = new TGeoVolumeAssembly("Sector01"); + sector01->AddNode(sensor01, 1); + sector01->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 2: single sensor of type 2 + TGeoVolumeAssembly* sector02 = new TGeoVolumeAssembly("Sector02"); + sector02->AddNode(sensor02, 1); + sector02->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 3: single sensor of type 3 + TGeoVolumeAssembly* sector03 = new TGeoVolumeAssembly("Sector03"); + sector03->AddNode(sensor03, 1); + sector03->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 4: single sensor of type 4 + TGeoVolumeAssembly* sector04 = new TGeoVolumeAssembly("Sector04"); + sector04->AddNode(sensor04, 1); + sector04->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 5: single sensor of type 5 + TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); + sector05->AddNode(sensor05, 1); + sector05->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 6: single sensor of type 6 + TGeoVolumeAssembly* sector06 = new TGeoVolumeAssembly("Sector06"); + sector06->AddNode(sensor06, 1); + sector06->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 7: single sensor of type 7 + TGeoVolumeAssembly* sector07 = new TGeoVolumeAssembly("Sector07"); + sector07->AddNode(sensor07, 1); + sector07->GetShape()->ComputeBBox(); + nSectors++; + +// // --- Sector type 5: two sensors of type 4 +// TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); +// Double_t shift5 = 0.5 * gkChainGapY + box4->GetDY(); +// TGeoTranslation* transD5 = +// new TGeoTranslation("td", 0., -1. * shift5, 0.); +// TGeoTranslation* transU5 = +// new TGeoTranslation("tu", 0., shift5, 0.); +// sector05->AddNode(sensor04, 1, transD5); +// sector05->AddNode(sensor04, 2, transU5); +// sector05->GetShape()->ComputeBBox(); +// nSectors++; + + return nSectors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create ladders + ** + ** Ladders are the building blocks of the stations. They contain + ** several modules placed one after the other along the z axis + ** such that the sectors are arranged vertically (with overlap). + ** + ** A ladder is constructed out of two half ladders, the second of which + ** is rotated in the x-y plane by 180 degrees and displaced + ** in z direction. + **/ +Int_t CreateLadders() { + + Int_t nLadders = 0; + + // --- Some variables + Int_t nSectors = 0; + Int_t sectorTypes[10]; + TGeoBBox* shape = NULL; + TString s0name; + TString hlname; + char align; + TGeoVolume* s0vol = NULL; + TGeoVolume* halfLadderU = NULL; + TGeoVolume* halfLadderD = NULL; + + // --- Ladders 01-23 + Int_t allSectorTypes[27][6] = { { 1, 2, 3, 3, 0, -1 }, // ladder 01 - 5 - last column defines alignment of small sensors + { 1, 2, 3, 3, 0, 0 }, // ladder 02 - 5 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, -1 }, // ladder 03 - 6 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 04 - 6 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, -1 }, // ladder 05 - 7 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 06 - 7 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 07 - last column defines alignment of small sensors + { 3, 4, 4, 4, 0, 0 }, // ladder 08 - last column defines alignment of small sensors + + { 1, 1, 2, 3, 3, 0 }, // ladder 09 - last column defines alignment of small sensors + { 1, 1, 2, 2, 3, 0 }, // ladder 10 - last column defines alignment of small sensors + { 2, 2, 0, 0, 0, 0 }, // ladder 11 - last column defines alignment of small sensors + { 2, 2, 2, 3, 4, 0 }, // ladder 12 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 13 - last column defines alignment of small sensors + + { 2, 3, 4, 0, 0, 0 }, // ladder 14 - last column defines alignment of small sensors + { 3, 3, 0, 0, 0, 0 }, // ladder 15 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 16 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 17 - last column defines alignment of small sensors + { 3, 4, 4, 0, 0, 0 }, // ladder 18 - last column defines alignment of small sensors + + { 4, 4, 0, 0, 0, 0 }, // ladder 19 - last column defines alignment of small sensors + { 1, 2, 4, 4, 4, 0 }, // ladder 20 - last column defines alignment of small sensors + { 4, 0, 0, 0, 0, 0 }, // ladder 21 - last column defines alignment of small sensors + { 2, 3, 4, 4, 4, 0 }, // ladder 22 - last column defines alignment of small sensors + { 2, 3, 3, 4, 4, 0 }, // ladder 23 - last column defines alignment of small sensors + + { 2, 3, 4, 4, 0, 0 }, // ladder 24 - copy of 17 with different total length + { 3, 4, 4, 0, 0, 0 }, // ladder 25 - copy of 18 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 26 - copy of 19 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 27 - copy of 19 with different total length + }; + +// Issue #405 +// Counting from the most upstream ladder, the gaps between sensors are as follows: +// 01 (most upstream): 41.3mm +// 02: 41.3mm +// 03: 42.0mm +// 04: 48.6mm +// 05: 60.8mm +// 06: 67.0mm +// 07: 79.2mm +// 08 (most downstream): 88.0mm + + Double_t gapXYZ[27][3] = { + { 0., 4.13, 0. }, // ladder 01 + { 0., 4.13, 0. }, // ladder 02 + { 0., 4.20, 0. }, // ladder 03 + { 0., 4.86, 0. }, // ladder 04 + { 0., 6.08, 0. }, // ladder 05 + { 0., 6.70, 0. }, // ladder 06 + { 0., 7.92, 0. }, // ladder 07 + { 0., 8.80, 0. }, // ladder 08 + { 0., -gkSectorOverlapY, 0. }, // ladder 09 + { 0., -gkSectorOverlapY, 0. }, // ladder 10 + { 0., -gkSectorOverlapY, 0. }, // ladder 11 + { 0., -gkSectorOverlapY, 0. }, // ladder 12 + { 0., -gkSectorOverlapY, 0. }, // ladder 13 + { 0., -gkSectorOverlapY, 0. }, // ladder 14 + { 0., -gkSectorOverlapY, 0. }, // ladder 15 + { 0., -gkSectorOverlapY, 0. }, // ladder 16 + { 0., -gkSectorOverlapY, 0. }, // ladder 17 + { 0., -gkSectorOverlapY, 0. }, // ladder 18 + { 0., -gkSectorOverlapY, 0. }, // ladder 19 + { 0., -gkSectorOverlapY, 0. }, // ladder 20 + { 0., -gkSectorOverlapY, 0. }, // ladder 21 + { 0., -gkSectorOverlapY, 0. }, // ladder 22 + { 0., -gkSectorOverlapY, 0. }, // ladder 23 + + { 0., -gkSectorOverlapY, 0. }, // ladder 24 - copy of 17 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 25 - copy of 18 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 26 - copy of 19 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 27 - copy of 19 with different total length + }; + + Double_t ladderLength[27] = { + 48.0, // ladder 01 + 48.0, // ladder 02 + 64.0, // ladder 03 + 64.0, // ladder 04 + 80.0, // ladder 05 + 80.0, // ladder 06 + 92.0, // ladder 07 + 96.0, // ladder 08 + 48.0, // ladder 09 + 48.0, // ladder 10 + 48.0, // ladder 11 + 64.0, // ladder 12 + 64.0, // ladder 13 + 64.0, // ladder 14 + 64.0, // ladder 15 + 80.0, // ladder 16 + 80.0, // ladder 17 + 80.0, // ladder 18 + 80.0, // ladder 19 + 92.0, // ladder 20 + 92.0, // ladder 21 + 96.0, // ladder 22 + 96.0, // ladder 23 + + 96.0, // ladder 24 - copy of 17 with different total length + 92.0, // ladder 25 - copy of 18 with different total length + 96.0, // ladder 26 - copy of 19 with different total length + 92.0, // ladder 27 - copy of 19 with different total length + }; +// ======================================================================== + + // calculate Z shift for ladders with and without gaps in the center + s0name = Form("Sector%02d", allSectorTypes[0][0]); + s0vol = gGeoMan->GetVolume(s0name); + shape = (TGeoBBox*) s0vol->GetShape(); + + for (Int_t iLadder = 0; iLadder < 27; iLadder++) + { + if (iLadder+1 <= 8) // for the 2 inner ladders of each station with gap for beampipe + gapXYZ[iLadder][2] = 0; // there is no offset in z for halfladders on ladders with a beampipe hole + else + gapXYZ[iLadder][2] = 2. * shape->GetDZ() + gkSectorGapZ; // set displacement in z for overlapping half ladders + } + +// ======================================================================== + + for (Int_t iLadder = 0; iLadder < 27; iLadder++) + { + cout << endl; + nSectors = 0; + for (Int_t i=0; i < 5; i++) + if (allSectorTypes[iLadder][i] != 0) + { + sectorTypes[nSectors] = allSectorTypes[iLadder][i]; // copy sectors for this ladder + cout << "DE iLadder " << iLadder+1 << " sectorTypes[" << nSectors << "] = " << allSectorTypes[iLadder][i] << ";" << endl; + nSectors++; // count how many sectors are in this ladder + } + + if (allSectorTypes[iLadder][5] == 0) + align = 'l'; + else + align = 'r'; + hlname = Form("HalfLadder%02du", iLadder+1); + // build upper half ladder + halfLadderU = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2.); // mirrored + + if (allSectorTypes[iLadder][5] == 0) + align = 'r'; + else + align = 'l'; + hlname = Form("HalfLadder%02dd", iLadder+1); + // build lower half ladder + halfLadderD = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2.); // mirrored + + // at this point half ladders are constructed + + // build all 4 possible ladders types for this sensor arrangement + ConstructLadder( iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19a + ConstructLadder( 100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19b + + ConstructLadder(1000+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19k + ConstructLadder(1100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19k + + nLadders++; + } + + return nLadders; +} +/** ======================================================================= **/ + + + +// **************************************************************************** +// ***** ***** +// ***** Generic functions for the construction of STS elements ***** +// ***** ***** +// ***** module: volume (made of a sector and a cable) ***** +// ***** haf ladder: assembly (made of modules) ***** +// ***** ladder: assembly (made of two half ladders) ***** +// ***** station: volume (made of ladders) ***** +// ***** ***** +// **************************************************************************** + + + +/** =========================================================================== + ** Construct a module + ** + ** A module is a sector plus the readout cable extending from the + ** top of the sector. The cable is made from passive silicon. + ** The cable has the same x size as the sector. + ** Its thickness is given by the global variable gkCableThickness. + ** The cable length is a parameter. + ** The sensor(s) of the sector is/are placed directly in the module; + ** the sector is just auxiliary for the proper placement. + ** + ** Arguments: + ** name volume name + ** sector pointer to sector volume + ** cableLength length of cable + **/ +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength) { + + // --- Check sector volume + if ( ! sector ) Fatal("CreateModule", "Sector volume not found!"); + + // --- Get size of sector + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + + // --- Get size of cable + Double_t cableX = sectorX; + Double_t cableY = cableLength; + Double_t cableZ = gkCableThickness; + + // --- Create module volume + Double_t moduleX = TMath::Max(sectorX, cableX); + Double_t moduleY = sectorY + cableLength; + + Double_t moduleZ = TMath::Max(sectorZ, cableZ); + + TGeoVolume* module = gGeoManager->MakeBox(name, gStsMedium, + moduleX/2., + moduleY/2., + moduleZ/2.); + + // --- Position of sector in module + // --- Sector is centred in x and z and aligned to the bottom + Double_t sectorXpos = 0.; + Double_t sectorYpos = 0.5 * (sectorY - moduleY); + Double_t sectorZpos = 0.; + + + // --- Get sensor(s) from sector + Int_t nSensors = sector->GetNdaughters(); + for (Int_t iSensor = 0; iSensor < nSensors; iSensor++) { + TGeoNode* sensor = sector->GetNode(iSensor); + + // --- Calculate position of sensor in module + const Double_t* xSensTrans = sensor->GetMatrix()->GetTranslation(); + Double_t sensorXpos = 0.; + Double_t sensorYpos = sectorYpos + xSensTrans[1]; + Double_t sensorZpos = 0.; + TGeoTranslation* sensTrans = new TGeoTranslation("sensTrans", + sensorXpos, + sensorYpos, + sensorZpos); + + // --- Add sensor volume to module + TGeoVolume* sensVol = sensor->GetVolume(); + module->AddNode(sensor->GetVolume(), iSensor+1, sensTrans); + module->GetShape()->ComputeBBox(); + } + + + // --- Create cable volume, if necessary, and place it in module + // --- Cable is centred in x and z and aligned to the top + if ( gkConstructCables && cableLength > 0.0001 ) { + TString cableName = TString(name) + "_cable"; + TGeoMedium* cableMedium = gGeoMan->GetMedium("STScable"); + if ( ! cableMedium ) Fatal("CreateModule", "Medium STScable not found!"); + TGeoVolume* cable = gGeoManager->MakeBox(cableName.Data(), + cableMedium, + cableX / 2., + cableY / 2., + cableZ / 2.); + // add color to cables + cable->SetLineColor(kOrange); + cable->SetTransparency(60); + Double_t cableXpos = 0.; + Double_t cableYpos = sectorY + 0.5 * cableY - 0.5 * moduleY; + Double_t cableZpos = 0.; + TGeoTranslation* cableTrans = new TGeoTranslation("cableTrans", + cableXpos, + cableYpos, + cableZpos); + module->AddNode(cable, 1, cableTrans); + module->GetShape()->ComputeBBox(); + } + + return module; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a half ladder + ** + ** A half ladder is a virtual volume (TGeoVolumeAssembly) consisting + ** of several modules arranged on top of each other. The modules + ** have a given overlap in y and a displacement in z to allow for the + ** overlap. + ** + ** The typ of sectors / modules to be placed must be specified: + ** 1 = sensor01 + ** 2 = sensor02 + ** 3 = sensor03 + ** 4 = sensor04 + ** 5 = 2 x sensor04 (chained) + ** 6 = 3 x sensor04 (chained) + ** The cable is added automatically from the top of each sensor to + ** the top of the half ladder. + ** The alignment can be left (l) or right (r), which matters in the + ** case of different x sizes of sensors (e.g. SensorType01). + ** + ** Arguments: + ** name volume name + ** nSectors number of sectors + ** sectorTypes array with sector types + ** align horizontal alignment of sectors + * ladderLength full length of the ladder towards FEE + * offsetY gap in the beam-pipe region + **/ +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY) { + + // --- Create half ladder volume assembly + TGeoVolumeAssembly* halfLadder = new TGeoVolumeAssembly(name); + + // --- Determine size of ladder + Double_t ladderX = 0.; + Double_t ladderY = 0.; + Double_t ladderZ = 0.; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + if ( ! sector ) + Fatal("ConstructHalfLadder", Form("Volume %s not found", sectorName.Data())); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + // --- Ladder x size equals largest sector x size + ladderX = TMath::Max(ladderX, 2. * box->GetDX()); + // --- Ladder y size is sum of sector ysizes + ladderY += 2. * box->GetDY(); + // --- Ladder z size is sum of sector z sizes + ladderZ += 2. * box->GetDZ(); + } + // --- Subtract overlaps in y + ladderY -= Double_t(nSectors-1) * gkSectorOverlapY; + // --- Add gaps in z direction + ladderZ += Double_t(nSectors-1) * gkSectorGapZ; + + ladderY = TMath::Max(ladderLength - offsetY, ladderY); + + // --- Create and place modules + Double_t yPosSect = -0.5 * ladderY; + Double_t zPosMod = -0.5 * ladderZ; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + yPosSect += 0.5 * sectorY; // Position of sector in ladder + Double_t cableLength = 0.5 * ladderY - yPosSect - 0.5 * sectorY; + TString moduleName = name + "_" + Form("Module%02d", + sectorTypes[iSector]); + TGeoVolume* module = ConstructModule(moduleName.Data(), + sector, cableLength); + + TGeoBBox* shapeMod = (TGeoBBox*) module->GetShape(); + Double_t moduleX = 2. * shapeMod->GetDX(); + Double_t moduleY = 2. * shapeMod->GetDY(); + Double_t moduleZ = 2. * shapeMod->GetDZ(); + Double_t xPosMod = 0.; + if ( align == 'l' ) + xPosMod = 0.5 * (moduleX - ladderX); // left aligned + else if ( align == 'r' ) + xPosMod = 0.5 * (ladderX - moduleX); // right aligned + else + xPosMod = 0.; // centred in x + Double_t yPosMod = 0.5 * (ladderY - moduleY); // top aligned + zPosMod += 0.5 * moduleZ; + TGeoTranslation* trans = new TGeoTranslation("t", xPosMod, + yPosMod, zPosMod); + halfLadder->AddNode(module, iSector+1, trans); + halfLadder->GetShape()->ComputeBBox(); + yPosSect += 0.5 * sectorY - gkSectorOverlapY; + zPosMod += 0.5 * moduleZ + gkSectorGapZ; + } + + CheckVolume(halfLadder); + cout << endl; + + return halfLadder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Add a carbon support to a ladder + ** + ** Arguments: + ** LadderIndex ladder number + ** ladder pointer to ladder + ** xu size of halfladder + ** ladderY height of ladder along y + ** ladderZ thickness of ladder along z + **/ +void AddCarbonLadder(Int_t LadderIndex, + TGeoVolume* ladder, + Double_t xu, + Double_t ladderY, + Double_t ladderZ) { + + // --- Some variables + TString name = Form("LadderType%04d", LadderIndex); // v19k + Int_t i; + Double_t j; + + Int_t YnumOfFrameBoxes = round(ladderY / gkFrameStep); + + // cout << "DEXZ: lad " << LadderIndex << " inum " << YnumOfFrameBoxes << endl; + + Double_t ladderDZ = (xu/2. + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2)/2.; + cout << "DEFR: frame Z size " << 2 * ladderDZ << " cm" << endl; + + TGeoBBox* fullFrameShp = new TGeoBBox (name+"_CarbonElement_shp", xu/2., gkFrameStep/2., ladderDZ); + TGeoVolume* fullFrameBoxVol = new TGeoVolume(name+"_CarbonElement", fullFrameShp, gStsMedium); + + ConstructFrameElement("CarbonElement", fullFrameBoxVol, xu/2.); + TGeoRotation* fullFrameRot = new TGeoRotation; + fullFrameRot->RotateY(180); + + Int_t inum = YnumOfFrameBoxes; + for (i=1; i<=inum; i++) + { + j=-(inum-1)/2.+(i-1); + // -(10-1)/2. +0 +10-1 -> -4.5 .. +4.5 -> -0.5, +0.5 (= 2) + // -(11-1)/2. +0 +11-1 -> -5.0 .. +5.0 -> -1, 0, 1 (= 3) + // cout << "DE: i " << i << " j " << j << endl; + + if (LadderIndex % 100 <= 3) // central ladders in stations 1 to 3 + { + if ((j>=-1) && (j<=1)) // keep the inner 2 (even) or 3 (odd) elements free for the cone + continue; + } + else if (LadderIndex % 100 <= 8) // central ladders in stations 4 to 8 + { + if ((j>=-2) && (j<=2)) // keep the inner 4 elements free for the cone + continue; + } + + cout << "DELZ: ladderDZ " << ladderDZ << " cm " << -ladderZ/2. - ladderDZ << " cm " << endl; + ladder->AddNode(fullFrameBoxVol, i, new TGeoCombiTrans(name+"_CarbonElement_posrot", 0., j*gkFrameStep, -(ladderZ/2.+ladderDZ), fullFrameRot)); + } + + ladder->GetShape()->ComputeBBox(); + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Construct a ladder out of two half ladders with vertical gap + ** + ** The second half ladder will be rotated by 180 degrees + ** in the x-y plane. The two half ladders will be put on top of each + ** other with a vertical gap. + ** + ** Arguments: + ** name volume name + ** halfLadderU pointer to upper half ladder + ** halfLadderD pointer to lower half ladder + ** gapY vertical gap + ** shiftZ relative displacement along the z axis + **/ + + TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ) { + + // --- Some variables + TGeoBBox* shape = NULL; + + // --- Dimensions of half ladders + shape = (TGeoBBox*) halfLadderU->GetShape(); + Double_t xu = 2. * shape->GetDX(); + Double_t yu = 2. * shape->GetDY(); + Double_t zu = 2. * shape->GetDZ(); + + shape = (TGeoBBox*) halfLadderD->GetShape(); + Double_t xd = 2. * shape->GetDX(); + Double_t yd = 2. * shape->GetDY(); + Double_t zd = 2. * shape->GetDZ(); + + + // --- Create ladder volume assembly + +// TString name = Form("LadderType%02d", LadderIndex); // v19a +// TString name = Form("LadderType%03d", LadderIndex); // v19b + TString name = Form("LadderType%04d", LadderIndex); // v19k + TGeoVolumeAssembly* ladder = new TGeoVolumeAssembly(name); + Double_t ladderX = TMath::Max(xu, xd); + Double_t ladderY = yu + yd + gapY; + Double_t ladderZ = TMath::Max(zu, zd + shiftZ); + + // --- Place half ladders + Double_t xPosU = 0.; // centred in x + Double_t yPosU = 0.5 * ( ladderY - yu ); // top aligned + Double_t zPosU = 0.5 * ( ladderZ - zu ); // front aligned // mount upper half ladder last + if (LadderIndex >= 1000) zPosU = -zPosU; // back aligned // mount upper half ladder first + + TGeoTranslation* tu = new TGeoTranslation("tu", xPosU, yPosU, zPosU); + ladder->AddNode(halfLadderU, 1, tu); + + Double_t xPosD = 0.; // centred in x + Double_t yPosD = 0.5 * ( yd - ladderY ); // bottom aligned + Double_t zPosD = 0.5 * ( zd - ladderZ ); // back aligned // mount lower half ladder first + if (LadderIndex >= 1000) zPosD = -zPosD; // front aligned // mount lower half ladder last + + TGeoRotation* rd = new TGeoRotation(); + rd->RotateZ(180.); + TGeoCombiTrans* cd = new TGeoCombiTrans(xPosD, yPosD, zPosD, rd); + ladder->AddNode(halfLadderD, 2, cd); + + ladder->GetShape()->ComputeBBox(); + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD0ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + cout << "DDDD ladder" << LadderIndex << endl; + cout << "DDDD1ladder" << LadderIndex << " ladderX " << ladderX << " ladderY " << ladderY << " ladderZ " << ladderZ << endl; + + // ---------------- Create and place frame boxes ------------------------ + + if (gkConstructFrames) + AddCarbonLadder(LadderIndex, ladder, ladderX, ladderY, ladderZ); + + // -------------------------------------------------------------------------- + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD2ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + return ladder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a unit + ** + ** The unit volume is the minimal box comprising all ladders + ** minus a tube accomodating the beam pipe. + ** + ** The ladders are arranged horizontally from left to right with + ** a given overlap in x. + ** Every second ladder is slightly displaced upstream from the centre + ** z plane and facing downstream, the others are slightly displaced + ** downstream and facing upstream (rotated around the y axis). + ** + ** Arguments: + ** name volume name + ** nLadders number of ladders + ** ladderTypes array of ladder types + **/ + + TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation) { + + Bool_t isFirstPartOfHalfUnit = kFALSE; + + // TString name = Form("Unit%02d", iUnit); // 0,1,2,3,4,5,6,7 - Unit00 missing in output + // TString name = Form("Unit%02d", iUnit+1); // 1,2,3,4,5,6,7,8 + + TGeoVolume* unit = gGeoMan->GetVolume(unitName[iUnit]); + if ( ! unit ) // if it does not yet exist, create a new one + { + unit = new TGeoVolumeAssembly(unitName[iUnit]); + isFirstPartOfHalfUnit = kTRUE; + } + + // --- Some local variables + TGeoBBox* ladderShape = NULL; + TGeoVolume* ladder = NULL; + TString ladderName; + Double_t subtractedVal; + + // --- Determine size of unit from ladders + Double_t statX = 0.; + // Double_t statY = 0.; + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { +// Int_t ladderType = ladderTypes[iLadder]%100; // v19a +// Int_t ladderType = ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100; // v19b + Int_t ladderType = ladderTypes[iLadder]; // v19k + +// if (iSide == 0) cout << "DWER " << ladderTypes[iLadder] << " " << ladderType << endl; + + if (ladderType > 0) + { +// ladderName = Form("LadderType%02d", ladderType); // v19a +// ladderName = Form("LadderType%03d", ladderType); // v19b + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + if ( ! ladder ) Fatal("ConstructUnit", + Form("Volume %s not found", ladderName.Data())); + ladderShape = (TGeoBBox*) ladder->GetShape(); + statX += 2. * ladderShape->GetDX(); + // statY = TMath::Max(statY, 2. * ladderShape->GetDY()); + } + else + statX += gkSensorSizeX; // empty ladder in unit + } + statX -= Double_t(nLadders-1) * gkLadderOverlapX; + +// if (iSide == 0) cout << "DWER -" << endl; + + // --- Place ladders in unit + cout << "xPos0: " << statX << endl; + Double_t xPos = -0.5 * statX; + cout << "xPos1: " << xPos << endl; + Double_t yPos = 0.; + Double_t zPos = 0.; + + Double_t maxdz = 0.; + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { // find maximum dz in this unit +// Int_t ladderType = ladderTypes[iLadder]%100; // v19a +// Int_t ladderType = ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100; // v19b + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { +// ladderName = Form("LadderType%02d", ladderType); // v19a +// ladderName = Form("LadderType%03d", ladderType); // v19b + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + if (maxdz < ladderShape->GetDZ()) + maxdz = ladderShape->GetDZ(); + } + } + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { +// Int_t ladderType = ladderTypes[iLadder]%100; // v19a +// Int_t ladderType = ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100; // v19b + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { +// ladderName = Form("LadderType%02d", ladderType); // v19a +// ladderName = Form("LadderType%03d", ladderType); // v19b + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + xPos += ladderShape->GetDX(); + cout << "xPos2: " << xPos << endl; + yPos = 0.; // vertically centred + TGeoRotation* rot = new TGeoRotation(); + + if (gkConstructFrames) + subtractedVal = ladderShape->GetDX() + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2; + else + subtractedVal = 0.; + + zPos = 0.5 * gkLadderGapZ + (2*maxdz-ladderShape->GetDZ()-subtractedVal/2.); // z-aligned ladders + +// v19a cout << "DE ladder" << ladderTypes[iLadder]%100 +// v19b cout << "DE ladder" << ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100 +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " dx: " << ladderShape->GetDX() + << " dy: " << ladderShape->GetDY() + << " dz: " << ladderShape->GetDZ() + << " max dz: " << maxdz << endl; + +// v19a cout << "DE ladder" << ladderTypes[iLadder]%100 +// v19b cout << "DE ladder" << ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100 +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " fra: " << gkFrameThickness/2. + << " sub: " << subtractedVal + << " zpo: " << zPos << endl << endl; + +// v19a if (ladderTypes[iLadder]/100 == 1) // flip some of the ladders to reproduce the CAD layout + if (ladderTypes[iLadder]/1000 == 1) // flip some of the ladders to reproduce the CAD layout + rot->RotateY(180.); + else + zPos = -zPos; + + if (!isFirstPartOfHalfUnit) + // zPos += 10; + zPos += 10.5; // v19d +// zPos += 11.0; // v19e + + TGeoCombiTrans* trans = new TGeoCombiTrans(xPos, yPos, zPos, rot); +// start +// cout << "DEEE** iLadder " << iLadder << " " << nLadders/2 << " " << nLadders << endl; + + if (iSide == 0) + { + if (iLadder < nLadders/2) // right side - only half unit -x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + else + { + if (iLadder >= nLadders/2) // left side - only half unit +x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + unit->GetShape()->ComputeBBox(); +// stop + xPos += ladderShape->GetDX() - gkLadderOverlapX; + cout << "xPos3: " << xPos << endl; + } + else + xPos += gkSensorSizeX - gkLadderOverlapX; + } + + return unit; + } +/** ======================================================================= **/ + + +/** =========================================================================== + ** Import and add the passive materials to the STS volume + **/ +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile) +{ + TString passiveName = TString("sts_passive_") + geoTag; + TString basePath = gSystem->Getenv("VMCWORKDIR"); + TString relPath = "/geometry/sts/passive/" + passiveName + ".gdml"; + TString passiveFileName = basePath + relPath; + infoFile << std::endl << std::endl; + infoFile << "Importing STS passive materials from GDML file '" << relPath << "'." << std::endl; + + TGDMLParse parser; + TGeoVolume* gdmlVolume = parser.GDMLReadFile(passiveFileName); + PostProcessGdml(gdmlVolume); + gdmlVolume->SetName(passiveName); + + TGeoTranslation* passiveTrans = new TGeoTranslation(0., 0., 4.68); + infoFile << "Passive assembly is translated for Z=4.68 cm downstream with respect to parent volume" << std::endl << std::endl; + + gdmlVolume->GetShape()->ComputeBBox(); + CheckVolume(gdmlVolume, infoFile); + + infoFile << std::endl; + for (Int_t iNode = 0; iNode < gdmlVolume->GetNdaughters(); iNode++) { + CheckVolume(gdmlVolume->GetNode(iNode)->GetVolume(), infoFile, kFALSE); + } + + stsVolume->AddNode(gdmlVolume, stsVolume->GetNdaughters(), passiveTrans, ""); +} + +/** =========================================================================== + ** Assign visual properties to the imported gdml volumes + **/ +void PostProcessGdml(TGeoVolume* gdmlVolume) +{ + const UInt_t kPOBColor = kRed-6; + const UInt_t kPOBTransparency = 0;// 5; + + const UInt_t kFEBColor = kOrange-6; + const UInt_t kFEBTransparency = 0;// 5; + + const UInt_t kUnitColor = kCyan-10; + const UInt_t kUnitTransparency = 0;// 5; + + const UInt_t kCfColor = kGray+3; + const UInt_t kCfTransparency = 0;// 10; + + // name <Color, Transparency> + std::map<std::string, std::tuple<UInt_t,UInt_t> > props { + { "passive_POB", std::tuple<UInt_t,UInt_t> {kPOBColor, kPOBTransparency} }, + { "passive_FEB", std::tuple<UInt_t,UInt_t> {kFEBColor, kFEBTransparency} }, + { "passive_unit", std::tuple<UInt_t,UInt_t> {kUnitColor, kUnitTransparency} }, + { "passive_Box_Wall", std::tuple<UInt_t,UInt_t> {kCfColor, kCfTransparency} }, + { "passive_Box_Wall_Front_CF2", std::tuple<UInt_t,UInt_t> {kCfColor-3, kCfTransparency} }, + }; + + // Match volume name and apply visual properties + const TObjArray* volumes = gGeoManager->GetListOfVolumes(); + for (auto& entry : props) { + TIter next(volumes); + TGeoVolume *vol = nullptr; + while ((vol=(TGeoVolume*)next())) { + if (TString(vol->GetName()).Contains(entry.first.c_str())) { + vol->SetLineColor(std::get<0>(entry.second)); + vol->SetTransparency(std::get<1>(entry.second)); + } + } + } +} + +/** =========================================================================== + ** Volume information for debugging + **/ +void CheckVolume(TGeoVolume* volume) { + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + cout << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) cout << ", assembly"; + else { + if ( volume->GetMedium() ) + cout << ", medium " << volume->GetMedium()->GetName(); + else cout << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + cout << endl; + if ( volume->GetNdaughters() ) { + cout << "Daughters: " << endl; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) { + TGeoNode* node = volume->GetNode(iNode); + TGeoBBox* shape = (TGeoBBox*) node->GetVolume()->GetShape(); + cout << setw(15) << node->GetName() << ", size " + << fixed << setprecision(3) + << setw(6) << 2. * shape->GetDX() << " x " + << setw(6) << 2. * shape->GetDY() << " x " + << setw(6) << 2. * shape->GetDZ() << ", position ( "; + TGeoMatrix* matrix = node->GetMatrix(); + const Double_t* pos = matrix->GetTranslation(); + cout << setfill(' '); + cout << fixed << setw(8) << pos[0] << ", " + << setw(8) << pos[1] << ", " + << setw(8) << pos[2] << " )" << endl; + } + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Volume information for output to file + **/ +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren) { + if ( ! file ) return; + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + file << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) file << ", assembly"; + else { + if ( volume->GetMedium() ) + file << ", medium " << volume->GetMedium()->GetName(); + else file << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + file << endl; + if ( volume->GetNdaughters() && listChildren) { + file << "Contains: "; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) + file << volume->GetNode(iNode)->GetVolume()->GetName() << " "; + file << endl; + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Calculate beam pipe outer radius for a given z + **/ +Double_t BeamPipeRadius(Double_t z) { + if ( z < gkPipeZ2 ) return gkPipeR1; + Double_t slope = (gkPipeR3 - gkPipeR2 ) / (gkPipeZ3 - gkPipeZ2); + return gkPipeR2 + slope * (z - gkPipeZ2); +} +/** ======================================================================= **/ + + + +/** ======================================================================= **/ +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + TGeoBBox* frameVertPillarShp; + + Double_t t = gkFrameThickness/2.; + + // --- Main vertical pillars +// TGeoBBox* frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, gkFrameStep/2., t); // square crossection, along y +// TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); +// frameVertPillarVol->SetLineColor(kGreen); +// frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoTranslation(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2.)); +// frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoTranslation(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkCylindricalFrames) + // TGeoBBox* frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", 0, t, gkFrameStep/2.); // circle crossection, along z + frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", gkCylinderDiaInner/2., gkCylinderDiaOuter/2., gkFrameStep/2.); // circle crossection, along z + else + frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, t, gkFrameStep/2.); // square crossection, along z + TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); + frameVertPillarVol->SetLineColor(kGreen); + + TGeoRotation* xRot90 = new TGeoRotation; + xRot90->RotateX(90.); + frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoCombiTrans(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoCombiTrans(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + + // TGeoRotation* vertRot = new TGeoRotation(name + "_vertpillar_rot_1", 90., 45., -90.); + TGeoRotation* vertRot = new TGeoRotation; + vertRot->RotateX(90.); + vertRot->RotateY(45.); + frameBoxVol->AddNode(frameVertPillarVol, 3, new TGeoCombiTrans(name + "_vertpillar_pos_3", 0., 0., (x-sqrt(2.)*t)/2., vertRot)); + + // --- Small horizontal pillar + // TGeoBBox* frameHorPillarShp = new TGeoBBox(name + "_horpillar_shape", x-2.*t, gkThinFrameThickness/2., gkThinFrameThickness/2.); + // TGeoVolume* frameHorPillarVol = new TGeoVolume(name + "_horpillar", frameHorPillarShp, framesMaterial); + // frameHorPillarVol->SetLineColor(kCyan); + // frameBoxVol->AddNode(frameHorPillarVol, 1, new TGeoTranslation(name + "_horpillar_pos_1", 0., -gkFrameStep/2.+gkThinFrameThickness/2., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkConstructSmallFrames) { + + // --- Small sloping pillars + TGeoPara* frameSlopePillarShp = new TGeoPara(name + "_slopepillar_shape", + (x-2.*t)/TMath::Cos(31.4/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., 31.4, 0., 90.); + TGeoVolume* frameSlopePillarVol = new TGeoVolume(name + "_slopepillar", frameSlopePillarShp, framesMaterial); + frameSlopePillarVol->SetLineColor(kCyan); + TGeoRotation* slopeRot = new TGeoRotation(name + "_slopepillar_rot_1", 0., 0., 31.4); + TGeoRotation* slopeRot2 = new TGeoRotation(name + "_slopepillar_rot_2", 0., 0., -31.4); + TGeoCombiTrans* slopeTrRot = new TGeoCombiTrans(name + "_slopepillar_posrot_1", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot); + TGeoCombiTrans* slopeTrRot2 = new TGeoCombiTrans(name + "_slopepillar_posrot_2", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot2); + + frameBoxVol->AddNode(frameSlopePillarVol, 1, slopeTrRot); + frameBoxVol->AddNodeOverlap(frameSlopePillarVol, 2, slopeTrRot2); + + + Double_t angl = 23.; + // --- Small sub pillar + TGeoPara* frameSubPillarShp = new TGeoPara(name + "_subpillar_shape", + (sqrt(2)*(x/2.-t)-t/2.)/TMath::Cos(angl/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., angl, 0., 90.); + TGeoVolume* frameSubPillarVol = new TGeoVolume(name + "_subpillar", frameSubPillarShp, framesMaterial); + frameSubPillarVol->SetLineColor(kMagenta); + + Double_t posZ = t * (1. - 3. / ( 2.*sqrt(2.) )); + + // one side of X direction + TGeoRotation* subRot1 = new TGeoRotation(name + "_subpillar_rot_1", 90., 45., -90.+angl); + TGeoCombiTrans* subTrRot1 = new TGeoCombiTrans(name + "_subpillar_posrot_1", -(-x/2.+t-t/(2.*sqrt(2.))), 1., posZ, subRot1); + + TGeoRotation* subRot2 = new TGeoRotation(name + "_subpillar_rot_2", 90., -90.-45., -90.+angl); + TGeoCombiTrans* subTrRot2 = new TGeoCombiTrans(name + "_subpillar_posrot_2", -(-x/2.+t-t/(2.*sqrt(2.))), -1., posZ, subRot2); + + // other side of X direction + TGeoRotation* subRot3 = new TGeoRotation(name + "_subpillar_rot_3", 90., 90.+45., -90.+angl); + TGeoCombiTrans* subTrRot3 = new TGeoCombiTrans(name + "_subpillar_posrot_3", -x/2.+t-t/(2.*sqrt(2.)), 1., posZ, subRot3); + + TGeoRotation* subRot4 = new TGeoRotation(name + "_subpillar_rot_4", 90., -45., -90.+angl); + TGeoCombiTrans* subTrRot4 = new TGeoCombiTrans(name + "_subpillar_posrot_4", -x/2.+t-t/(2.*sqrt(2.)), -1., posZ, subRot4); + + frameBoxVol->AddNode(frameSubPillarVol, 1, subTrRot1); + frameBoxVol->AddNode(frameSubPillarVol, 2, subTrRot2); + frameBoxVol->AddNode(frameSubPillarVol, 3, subTrRot3); + frameBoxVol->AddNode(frameSubPillarVol, 4, subTrRot4); + // frameBoxVol->GetShape()->ComputeBBox(); + } + + return frameBoxVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructSmallCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 6., 7.6, 6., 6.04, 0., 180.); +// TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + Double_t radius = 3.0; + Double_t thickness = 0.04; // 0.4 mm +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 3., 3.2, 3., 3.2, 0., 180.); + TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, radius, radius+thickness, radius, radius+thickness, 0., 180.); + TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + TGeoCombiTrans* M = new TGeoCombiTrans ("M"); + M->RotateX (45.); + M->SetDy (-5.575); + M->SetDz (6.935); + M->RegisterYourself(); + + TGeoShape* coneShp = new TGeoCompositeShape ("Cone_shp", "A-B:M"); + TGeoVolume* coneVol = new TGeoVolume ("Cone", coneShp, framesMaterial); + coneVol->SetLineColor(kGreen); +// coneVol->RegisterYourself(); + +// // --- Inner cone +// Double_t thickness = 0.02; +// Double_t thickness2 = 0.022; +// // TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); +// TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 3.+thickness, 4.6-thickness2, 2.99+thickness, 3.05-thickness2, 0., 180.); +// +// TGeoCombiTrans* M2 = new TGeoCombiTrans ("M2"); +// M2->RotateX (45.); +// M2->SetDy (-5.575+thickness*sqrt(2.)); +// M2->SetDz (6.935); +// M2->RegisterYourself(); +// +// TGeoShape* coneShp2 = new TGeoCompositeShape ("Cone2_shp", "A2-B:M2"); +// TGeoVolume* coneVol2 = new TGeoVolume ("Cone2", coneShp2, gStsMedium); +// coneVol2->SetLineColor(kGreen); +//// coneVol2->RegisterYourself(); +// +// coneVol->AddNode(coneVol2, 1); + + return coneVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructBigCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone + TGeoConeSeg* bA = new TGeoConeSeg ("bA", coneDz, 6., 7.6, 6., 6.04, 0., 180.); + TGeoBBox* bB = new TGeoBBox ("bB", 8., 6., 10.); + + TGeoCombiTrans* bM = new TGeoCombiTrans ("bM"); + bM->RotateX (45.); + bM->SetDy (-5.575); + bM->SetDz (6.935); + bM->RegisterYourself(); + + TGeoShape* coneBigShp = new TGeoCompositeShape ("ConeBig_shp", "bA-bB:bM"); + TGeoVolume* coneBigVol = new TGeoVolume ("ConeBig", coneBigShp, framesMaterial); + coneBigVol->SetLineColor(kGreen); +// coneBigVol->RegisterYourself(); + + // --- Inner cone + Double_t thickness = 0.02; + Double_t thickness2 = 0.022; + TGeoConeSeg* bA2 = new TGeoConeSeg ("bA2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); + + TGeoCombiTrans* bM2 = new TGeoCombiTrans ("bM2"); + bM2->RotateX (45.); + bM2->SetDy (-5.575+thickness*sqrt(2.)); + bM2->SetDz (6.935); + bM2->RegisterYourself(); + + TGeoShape* coneBigShp2 = new TGeoCompositeShape ("ConeBig2_shp", "bA2-bB:bM2"); + TGeoVolume* coneBigVol2 = new TGeoVolume ("ConeBig2", coneBigShp2, gStsMedium); + coneBigVol2->SetLineColor(kGreen); +// coneBigVol2->RegisterYourself(); + + coneBigVol->AddNode(coneBigVol2, 1); + + return coneBigVol; +} + +/** ======================================================================= **/ diff --git a/macro/sts/geometry/create_stsgeo_v19l.C b/macro/sts/geometry/create_stsgeo_v19l.C new file mode 100644 index 0000000000000000000000000000000000000000..ad39a53d7628973302a5aacc83e89aebd6cbd130 --- /dev/null +++ b/macro/sts/geometry/create_stsgeo_v19l.C @@ -0,0 +1,2372 @@ +/****************************************************************************** + ** Creation of STS geometry in ROOT format (TGeo). + ** + ** @file create_stsgeo_v19l.C + ** @author Volker Friese <v.friese@gsi.de> + ** @since 15 June 2012 + ** @date 09.05.2014 + ** @author Tomas Balog <T.Balog@gsi.de> + ** + ** v19l: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.15 cm + ** v19k: ladders on upstream side of units get upper half ladders installed first, + ** ladders on downstream side of units get lower half ladders installed first, + ** this saves 1.5 mm space in z per station, 12 mm in total (LadderType went from 3 to 4 digits) + ** parameters : delta Z prime = 1.00 cm - delta Z pitch = 0.15 cm + ** v19j: use overlap and distance parameters from CAD model + ** v19h: put STS stations from v19d at z-positions = 260; 365; 470; 575; 680; 785; 890; 995 mm + ** v19g: place a box with services around v19e + ** v19f: place a box with services around v19d + ** v19e: increase spacing between stations by +10 mm from 100 mm + ** v19d: increase spacing between stations by + 5 mm from 100 mm + ** v19c: drop station 8 and increase spacing between remaining 7 stations from 10 cm to 12 c + ** v19b: introduce FEB orientation in ladder numbering (LadderType went from 2 to 3 digits) + ** v19a: import passive materials from gdml file + ** extend CF ladder structures and cables towards FEE plane + ** change CF ladder frame shape + ** v18d: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu (based on v18b) + ** v18c: fixed cut-out windows in cooling plates, improve the box shape/materials + ** v18b: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu + ** v18a: adds 9 cooling/holding plates and a box around the setup + ** v16g: v16g is the new standard geometry from November 2017 + ** v16g: switch from stations to units - left / right ("Unit01L", "Unit01R") + ** v16f: switch from stations to units + ** - split in upstream / downstream and left / right parts + ** - named Unit0xUR, Unit0xUL, Unit0xDR, Unit0xDL + ** v16e: switch from stations to units - upstream / downstream ("Unit01U", "Unit01D") + ** v16d: skip keeping volumes of sts and stations + ** v16c: like v16b, but senors of ladders beampipe next to beampipe + ** shifted closer to the pipe, like in the CAD model + ** v16b: like v16a, but yellow sensors removed + ** v16a: derived from v15c (no cones), but with sensor types renamed: + ** 2 -> 1, 3 -> 2, 4 -> 3, 5 -> 4, 1 -> 5 + ** + ** v15c: as v15b without cones + ** v15b: introduce modified carbon ladders from v13z + ** v15a: with flipped ladder orientation for stations 0,2,4,6 to match CAD design + ** + ** TODO: + ** + ** DONE: + ** v15b - use carbon macaroni as ladder support + ** v15b - introduce a small gap between lowest sensor and carbon ladder + ** v15b - build small cones for the first 2 stations + ** v15b - within a station the ladders of adjacent units should not touch eachother - set gkLadderGapZ to 10 mm + ** v15b - for all ladders set an even number of ladder elements + ** v15b - z offset of cones to ladders should not be 0.3 by default, but 0.26 + ** v15b - within a station the ladders should be aligned in z, defined either by the unit or the ladder with most sensors + ** v15b - get rid of cone overlap in stations 7 and 8 - done by adapting rHole size + ** + ** The geometry hierarachy is: + ** + ** 1. Sensors (see function CreateSensors) + ** The sensors are the active volumes and the lowest geometry level. + ** They are built as TGeoVolumes, shape box, material silicon. + ** x size is determined by strip pitch 58 mu and 1024 strips + ** plus guard ring of 1.3 mm at each border -> 6.1992 cm. + ** Sensor type 1 is half of that (3.0792 cm). + ** y size is determined by strip length (2.2 / 4.2 / 6.3 cm) plus + ** guard ring of 1.3 mm at top and bottom -> 2.46 / 4.46 / 6.46 cm. + ** z size is a parameter, to be set by gkSensorThickness. + ** + ** 2. Sectors (see function CreateSectors) + ** Sectors consist of several chained sensors. These are arranged + ** vertically on top of each other with a gap to be set by + ** gkChainGapY. Sectors are constructed as TGeoVolumeAssembly. + ** The sectors are auxiliary volumes used for proper placement + ** of the sensor(s) in the module. They do not show up in the + ** final geometry. + ** + ** 3. Modules (see function ConstructModule) + ** A module is a readout unit, consisting of one sensor or + ** a chain of sensors (see sector) and a cable. + ** The cable extends from the top of the sector vertically to the + ** top of the halfladder the module is placed in. The cable and module + ** volume thus depend on the vertical position of the sector in + ** the halfladder. The cables consist of silicon with a thickness to be + ** set by gkCableThickness. + ** Modules are constructed as TGeoVolume, shape box, medium gStsMedium. + ** The module construction can be switched off (gkConstructCables) + ** to reproduce older geometries. + ** + ** 4. Halfladders (see function ConstructHalfLadder) + ** A halfladder is a vertical assembly of several modules. The modules + ** are placed vertically such that their sectors overlap by + ** gkSectorOverlapY. They are displaced in z direction to allow for the + ** overlap in y by gkSectorGapZ. + ** The horizontal placement of modules in the halfladder can be choosen + ** to left aligned or right aligned, which only matters if sensors of + ** different x size are involved. + ** Halfladders are constructed as TGeoVolumeAssembly. + ** + ** 5. Ladders (see function CreateLadders and ConstructLadder) + ** A ladder is a vertical assembly of two halfladders, and is such the + ** vertical building block of a station. The second (bottom) half ladder + ** is rotated upside down. The vertical arrangement is such that the + ** inner sectors of the two halfladders have the overlap gkSectorOverlapY + ** (function CreateLadder) or that there is a vertical gap for the beam + ** hole (function CreateLadderWithGap). + ** Ladders are constructed as TGeoVolumeAssembly. + ** + ** 6. Stations (see function ConstructStation) + ** A station represents one layer of the STS geometry: one measurement + ** at (approximately) a given z position. It consist of several ladders + ** arranged horizontally to cover the acceptance. + ** The ladders are arranged such that there is a horizontal overlap + ** between neighbouring ladders (gkLadderOverLapX) and a vertical gap + ** to allow for this overlap (gkLadderGapZ). Each second ladder is + ** rotated around its y axis to face away from or into the beam. + ** Stations are constructed as TGeoVolumes, shape box minus tube (for + ** the beam hole), material gStsMedium. + ** + ** 7. STS + ** The STS is a volume hosting the entire detectors system. It consists + ** of several stations located at different z positions. + ** The STS is constructed as TGeoVolume, shape box minus cone (for the + ** beam pipe), material gStsMedium. The size of the box is computed to + ** enclose all stations. + *****************************************************************************/ + + +// Remark: With the proper steering variables, this should exactly reproduce +// the geometry version v11b of A. Kotynia's described in the ASCII format. +// The only exception is a minimal difference in the z position of the +// sectors/sensors. This is because of ladder types 2 and 4 containing the half +// sensors around the beam hole (stations 1,2 and 3). In v11b, the two ladders +// covering the beam hole cannot be transformed into each other by rotations, +// but only by a reflection. This means they are constructionally different. +// To avoid introducing another two ladder types, the difference in z position +// was accepted. + + +// Differences to v12: +// gkChainGap reduced from 1 mm to 0 +// gkCableThickness increased from 100 mum to 200 mum (2 cables per module) +// gkSectorOverlapY reduced from 3 mm to 2.4 mm +// New sensor types 05 and 06 +// New sector types 07 and 08 +// Re-definiton of ladders (17 types instead of 8) +// Re-definiton of station from new ladders + + +#include <iomanip> +#include <iostream> +#include "TGeoManager.h" + +#include "TGeoTube.h" +#include "TGeoPara.h" +#include "TGeoCone.h" +#include "TGeoTrd2.h" +#include "TGeoCompositeShape.h" +#include "TGeoXtru.h" +#include "TGeoPhysicalNode.h" + +// forward declarations +Int_t CreateSensors(); +Int_t CreateSectors(); +Int_t CreateLadders(); +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength); +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY); +TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ); +TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation); +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile); +void PostProcessGdml(TGeoVolume* gdmlTop); +void CheckVolume(TGeoVolume* volume); +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren = kTRUE); +Double_t BeamPipeRadius(Double_t z); +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x); +TGeoVolume* ConstructSmallCone(Double_t coneDz); +TGeoVolume* ConstructBigCone(Double_t coneDz); + +// ------------- Version highlight ----------------------------------- + +const std::string gVersionHighlight = R"( +Summary: + This version adds passive materials imported from GDML model to the STS geometry: + * Taken from and largely correspond to mechanical CAD drawings of the detector + * Thermal insulation box: + - made out of carbon sandwitch panel (2mm carbon fiber sheet + layer of carbon foam + 2mm carbon fiber sheet) + - front window of complex shape with interface to MVD / target chamber + - back window with large aperture (2000 x 1200 mm) square cut into carbon foam + * Structural units: + - made of 2 complex shape aluminum C-Frames, 15mm thick + - placed at 25, 35, ... ,105 cm absolute Z + - contain front-end and power distribution boxes with equivalent X_0 values + + Scripted geometry tweaks: + * Ladders and cables are extended towards the read-out planes having same lengths in respective rows + * Adjusted form and shape of carbon ladder structures from L-type to X-type + * Reduced verbosity of this file + + Sensor arrangement is the same as in version v16g + + !! Important for this version is the discrepancy from the mechanical CAD w.r.t. front wall. + The square window was replaced by a round one to avoid overlaps with present beam pipe designs, e.g. pipe_v16b_1e +)"; + +// ------------- Steering variables ----------------------------------- + +// ---> Horizontal width of sensors [cm] +const Double_t gkSensorSizeX = 6.2; // was 6.2092; // 6.2 - Oleg CAD 15/05/2020 + +// ---> Thickness of sensors [cm] +const Double_t gkSensorThickness = 0.03; + +// ---> Vertical gap between chained sensors [cm] +const Double_t gkChainGapY = 0.00; + +// ---> Thickness of cables [cm] +const Double_t gkCableThickness = 0.02; + +// ---> Horizontal overlap of neighbouring ladders [cm] +const Double_t gkLadderOverlapX = 0.25; // delta X - Oleg CAD 14/05/2020 + +// ---> Vertical overlap of neighbouring sectors in a ladder [cm] +const Double_t gkSectorOverlapY = 0.46; // delta Y - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring sectors in a ladder [cm] +const Double_t gkSectorGapZ = 0.12; // gap + thickness = pitch // delta Z pitch = 0.15 - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring ladders [cm] +const Double_t gkLadderGapZ = 0.50 - 0.15; // for asym // 0.5 for sym // delta Z prime + +// ---> Gap in z between lowest sector to carbon support structure [cm] +const Double_t gkSectorGapZFrame = 0.280 - 0.025; // Oleg CAD 05/05/2020 // there is a 2.8 mm gap between the bottom side of the sensor and the top ledge of the carbon ladder + +// ---> Switch to construct / not to construct readout cables +const Bool_t gkConstructCables = kTRUE; + +// ---> Switch to construct / not to construct frames +const Bool_t gkConstructCones = kFALSE; // kTRUE; // switch this false by default for v15c and v16x +const Bool_t gkConstructFrames = kTRUE; // kFALSE; // switch this true by default for v15c and v16x +const Bool_t gkConstructSmallFrames = kTRUE; // kFALSE; +const Bool_t gkCylindricalFrames = kTRUE; // kFALSE; + +// ---> Size of the frame +const Double_t gkFrameThickness = 0.2; +const Double_t gkThinFrameThickness = 0.05; +const Double_t gkFrameStep = 4.0; // size of frame cell along y direction + +const Double_t gkCylinderDiaInner = 0.07; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) +const Double_t gkCylinderDiaOuter = 0.15; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) + +// ---> Switch to import / not to import the Passive materials from GDML file +const Bool_t gkImportPassive = kTRUE; +//const Bool_t gkImportPassive = kFALSE; + +// ---------------------------------------------------------------------------- + + +// -------------- Parameters of beam pipe in the STS region -------------- +// ---> Needed to compute stations and STS such as to avoid overlaps +const Double_t gkPipeZ1 = 22.0; +const Double_t gkPipeR1 = 1.8; +const Double_t gkPipeZ2 = 50.0; +const Double_t gkPipeR2 = 1.8; +const Double_t gkPipeZ3 = 125.0; +const Double_t gkPipeR3 = 5.5; + +//DE const Double_t gkPipeZ1 = 27.0; +//DE const Double_t gkPipeR1 = 1.05; +//DE const Double_t gkPipeZ2 = 160.0; +//DE const Double_t gkPipeR2 = 3.25; +// ---------------------------------------------------------------------------- + +//TString unitName[16] = // names of units for v16e +// { "Unit00D", +// "Unit01U", "Unit01D", +// "Unit02U", "Unit02D", +// "Unit03U", "Unit03D", +// "Unit04U", "Unit04D", +// "Unit05U", "Unit05D", +// "Unit06U", "Unit06D", +// "Unit07U", "Unit07D", +// "Unit08U" }; + +//TString unitName[32] = // names of units for v16f +// { "Unit00DR", "Unit00DL", +// "Unit01UR", "Unit01UL", "Unit01DR", "Unit01DL", +// "Unit02UR", "Unit02UL", "Unit02DR", "Unit02DL", +// "Unit03UR", "Unit03UL", "Unit03DR", "Unit03DL", +// "Unit04UR", "Unit04UL", "Unit04DR", "Unit04DL", +// "Unit05UR", "Unit05UL", "Unit05DR", "Unit05DL", +// "Unit06UR", "Unit06UL", "Unit06DR", "Unit06DL", +// "Unit07UR", "Unit07UL", "Unit07DR", "Unit07DL", +// "Unit08UR", "Unit08UL" }; + +TString unitName[32] = // names of units for v16g - while merging D and U parts + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", "Unit01R", "Unit01L", + "Unit02R", "Unit02L", "Unit02R", "Unit02L", + "Unit03R", "Unit03L", "Unit03R", "Unit03L", + "Unit04R", "Unit04L", "Unit04R", "Unit04L", + "Unit05R", "Unit05L", "Unit05R", "Unit05L", + "Unit06R", "Unit06L", "Unit06R", "Unit06L", + "Unit07R", "Unit07L", "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +TString unitName18[18] = // names of units for v16g + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", + "Unit02R", "Unit02L", + "Unit03R", "Unit03L", + "Unit04R", "Unit04L", + "Unit05R", "Unit05L", + "Unit06R", "Unit06L", + "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +// ------------- Other global variables ----------------------------------- +// ---> STS medium (for every volume except silicon) +TGeoMedium* gStsMedium = NULL; // will be set later +// ---> TGeoManager (too lazy to write out 'Manager' all the time +TGeoManager* gGeoMan = NULL; // will be set later +// ---------------------------------------------------------------------------- + + + + +// ============================================================================ +// ====== Main function ===== +// ============================================================================ + +void create_stsgeo_v19l(const char* geoTag="v19l") +{ + + // ------- Geometry file name (output) ---------------------------------- + TString geoFileName = "sts_"; + geoFileName = geoFileName + geoTag + ".geo.root"; + // -------------------------------------------------------------------------- + + + // ------- Open info file ----------------------------------------------- + TString infoFileName = geoFileName; + infoFileName.ReplaceAll("root", "info"); + fstream infoFile; + infoFile.open(infoFileName.Data(), fstream::out); + infoFile << "STS geometry created with create_stsgeo_v19l.C" << endl; + infoFile << gVersionHighlight << endl; + infoFile << "Global variables: " << endl; + infoFile << "Sensor thickness = " << gkSensorThickness << " cm" << endl; + infoFile << "Vertical gap in sensor chain = " + << gkChainGapY << " cm" << endl; + infoFile << "Vertical overlap of sensors = " + << gkSectorOverlapY << " cm" << endl; + infoFile << "Gap in z between neighbour sensors = " + << gkSectorGapZ << " cm" << endl; + infoFile << "Horizontal overlap of sensors = " + << gkLadderOverlapX << " cm" << endl; + infoFile << "Gap in z between neighbour ladders = " + << gkLadderGapZ << " cm" << endl; + if ( gkConstructCables ) + infoFile << "Cable thickness = " << gkCableThickness << " cm" << endl; + else + infoFile << "No cables" << endl; + infoFile << endl; + infoFile << "Beam pipe: R1 = " << gkPipeR1 << " cm at z = " + << gkPipeZ1 << " cm" << endl; + infoFile << "Beam pipe: R2 = " << gkPipeR2 << " cm at z = " + << gkPipeZ2 << " cm" << endl; + infoFile << "Beam pipe: R3 = " << gkPipeR3 << " cm at z = " + << gkPipeZ3 << " cm" << endl; + // -------------------------------------------------------------------------- + + + // ------- Load media from media file ----------------------------------- + FairGeoLoader* geoLoad = new FairGeoLoader("TGeo","FairGeoLoader"); + FairGeoInterface* geoFace = geoLoad->getGeoInterface(); + TString geoPath = gSystem->Getenv("VMCWORKDIR"); + TString medFile = geoPath + "/geometry/media.geo"; + geoFace->setMediaFile(medFile); + geoFace->readMedia(); + gGeoMan = gGeoManager; + // -------------------------------------------------------------------------- + + + // ----------------- Get and create the required media ----------------- + FairGeoMedia* geoMedia = geoFace->getMedia(); + FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder(); + + // ---> air + FairGeoMedium* mAir = geoMedia->getMedium("air"); + if ( ! mAir ) Fatal("Main", "FairMedium air not found"); + geoBuild->createMedium(mAir); + TGeoMedium* air = gGeoMan->GetMedium("air"); + if ( ! air ) Fatal("Main", "Medium air not found"); + + // ---> silicon + FairGeoMedium* mSilicon = geoMedia->getMedium("silicon"); + if ( ! mSilicon ) Fatal("Main", "FairMedium silicon not found"); + geoBuild->createMedium(mSilicon); + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + if ( ! silicon ) Fatal("Main", "Medium silicon not found"); + + // ---> carbon + FairGeoMedium* mCarbon = geoMedia->getMedium("carbon"); + if ( ! mCarbon ) Fatal("Main", "FairMedium carbon not found"); + geoBuild->createMedium(mCarbon); + TGeoMedium* carbon = gGeoMan->GetMedium("carbon"); + if ( ! carbon ) Fatal("Main", "Medium carbon not found"); + + // ---> STSBoxCarbonFoam + FairGeoMedium* mSTSBoxCarbonFoam = geoMedia->getMedium("STSBoxCarbonFoam"); + if ( ! mSTSBoxCarbonFoam ) Fatal("Main", "FairMedium STSBoxCarbonFoam not found"); + geoBuild->createMedium(mSTSBoxCarbonFoam); + TGeoMedium* STSBoxCarbonFoam = gGeoMan->GetMedium("STSBoxCarbonFoam"); + if ( ! STSBoxCarbonFoam ) Fatal("Main", "Medium STSBoxCarbonFoam not found"); + + // ---> STSBoxCarbonFibre + FairGeoMedium* mSTSBoxCarbonFibre = geoMedia->getMedium("STSBoxCarbonFibre"); + if ( ! mSTSBoxCarbonFibre ) Fatal("Main", "FairMedium STSBoxCarbonFibre not found"); + geoBuild->createMedium(mSTSBoxCarbonFibre); + TGeoMedium* STSBoxCarbonFibre = gGeoMan->GetMedium("STSBoxCarbonFibre"); + if ( ! STSBoxCarbonFibre ) Fatal("Main", "Medium STSBoxCarbonFibre not found"); + + // ---> STScable + FairGeoMedium* mSTScable = geoMedia->getMedium("STScable"); + if ( ! mSTScable ) Fatal("Main", "FairMedium STScable not found"); + geoBuild->createMedium(mSTScable); + TGeoMedium* STScable = gGeoMan->GetMedium("STScable"); + if ( ! STScable ) Fatal("Main", "Medium STScable not found"); + + // ---> Aluminium + FairGeoMedium* mAluminium = geoMedia->getMedium("aluminium"); + if ( ! mAluminium ) Fatal("Main", "FairMedium aluminium not found"); + geoBuild->createMedium(mAluminium); + TGeoMedium* aluminium = gGeoMan->GetMedium("aluminium"); + if ( ! aluminium ) Fatal("Main", "Medium aluminium not found"); + + // --- + gStsMedium = air; + // -------------------------------------------------------------------------- + + + // -------------- Create geometry and top volume ------------------------- + gGeoMan = (TGeoManager*)gROOT->FindObject("FAIRGeom"); +// gGeoMan->SetName("STSgeom"); + TGeoVolume* top = new TGeoVolumeAssembly("top"); +// TGeoBBox* topbox= new TGeoBBox("", 120., 120., 120.); +// TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air")); + gGeoMan->SetTopVolume(top); + // -------------------------------------------------------------------------- + + + // -------------- Create media ------------------------------------------ + /* + cout << endl; + cout << "===> Creating media...."; + cout << CreateMedia(); + cout << " media created" << endl; + TList* media = gGeoMan->GetListOfMedia(); + for (Int_t iMedium = 0; iMedium < media->GetSize(); iMedium++ ) { + cout << "Medium " << iMedium << ": " + << ((TGeoMedium*) media->At(iMedium))->GetName() << endl; + } + gStsMedium = gGeoMan->GetMedium("air"); + if ( ! gStsMedium ) Fatal("Main", "medium sts_air not found"); + */ + // -------------------------------------------------------------------------- + + + // --------------- Create sensors --------------------------------------- + cout << endl << endl; + cout << "===> Creating sensors...." << endl << endl; + infoFile << endl << "Sensors: " << endl; + Int_t nSensors = CreateSensors(); + for (Int_t iSensor = 1; iSensor <= nSensors; iSensor++) { + TString name = Form("Sensor%02d",iSensor); + TGeoVolume* sensor = gGeoMan->GetVolume(name); + + // add color to sensors + if (iSensor == 1) + sensor->SetLineColor(kRed); + if (iSensor == 2) + sensor->SetLineColor(kGreen); + if (iSensor == 3) + sensor->SetLineColor(kBlue); + if (iSensor == 4) + sensor->SetLineColor(kAzure); + if (iSensor == 5) + sensor->SetLineColor(kYellow); + if (iSensor == 6) + sensor->SetLineColor(kYellow); + if (iSensor == 7) + sensor->SetLineColor(kYellow); + + CheckVolume(sensor); + CheckVolume(sensor, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create sectors -------------------------------------- + cout << endl << endl; + cout << "===> Creating sectors...." << endl; + // infoFile << endl << "Sectors: " << endl; + Int_t nSectors = CreateSectors(); + for (Int_t iSector = 1; iSector <= nSectors; iSector++) { + // cout << endl; + TString name = Form("Sector%02d", iSector); + TGeoVolume* sector = gGeoMan->GetVolume(name); + CheckVolume(sector); + // CheckVolume(sector, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create ladders -------------------------------------- + cout << endl << endl; + cout << "===> Creating ladders...." << endl; + infoFile << endl << "Ladders:" << endl; + + TString name = ""; + TGeoVolume* ladder; + + + Int_t nLadders = CreateLadders(); + + for (Int_t iLadder = 1; iLadder <= nLadders; iLadder++) { + cout << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType0%02d", iLadder); // v19b + name = Form("LadderType00%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF1: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType1%02d", iLadder); // v19b + name = Form("LadderType01%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF2: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType10%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF3: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType11%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF4: ladder name: " << name << endl << endl; + } + // -------------------------------------------------------------------------- + + + // ---------------- Create cones ---------------------------------------- + Double_t coneDz = 1.64; + TGeoVolume* coneSmallVolum = ConstructSmallCone(coneDz); + if (!coneSmallVolum) Fatal("ConstructSmallCone", "Volume Cone not found"); + TGeoVolume* coneBigVolum = ConstructBigCone(coneDz); + if (!coneBigVolum) Fatal("ConstructBigCone", "Volume Cone not found"); + // -------------------------------------------------------------------------- + + + // ---------------- Create stations ------------------------------------- + cout << endl << endl; + cout << "===> Creating stations...." << endl; + infoFile << endl << "Stations: " << endl; + Int_t angle = 0; + nLadders = 0; + Int_t ladderTypes[16]; // there are max 16 ladders in one layer + TGeoTranslation* statTrans = NULL; + + TGeoVolume *myunit[32]; // units + +// Int_t statPos[8] = { 30, 40, 50, 60, 70, 80, 90, 100 }; // z positions of stations +// Int_t statPos[16] = { 28, 32, 38, 42, 48, 52, 58, 62, +// 68, 72, 78, 82, 88, 92, 98,102 }; // z positions of units +// Int_t statPos[16] = { 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units +// Int_t statPos18[18] = { 30, 30, // expanded for placement of Unit00 +// 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units + // v19h + Double_t statPos[16] = { 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of units + Double_t statPos18[18] = { 26.0, 26.0, // expanded for placement of Unit00 + 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of unit + +// // v19d +// Double_t statPos[16] = { 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units +// Double_t statPos18[18] = { 30.0, 30.0, // expanded for placement of Unit00 +// 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units + +////Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.9 , 3.7 , 3.7 , 4.2 , 4.2 }; // size of cutouts in stations +// Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.43, 3.04, 3.35, 3.96, 4.2 }; // size of cutouts in stations, derived from gapXYZ[x][1]/2 + + Int_t cone_size[8] = { 0, 0, 0, 1, 1, 1, 1, 1 }; // size of cones: 0 = small, 1 = large + + Double_t cone_offset[2] = { 0.305, 0.285 }; + +// Int_t allLadderTypes[8][16]= +// { { -1, -1, -1, -1, 10, 109, 9, 101, 1, 109, 9, 110, -1, -1, -1, -1 }, // station 1 +// { -1, -1, 111, 10, 110, 9, 109, 2, 102, 9, 109, 10, 110, 11, -1, -1 }, // station 2 +// { -1, -1, 14, 113, 12, 112, 12, 103, 3, 112, 12, 112, 13, 114, -1, -1 }, // station 3 +// { -1, 15, 114, 13, 112, 12, 112, 4, 104, 12, 112, 12, 113, 14, 115, -1 }, // station 4 +// { -1, 119, 18, 117, 17, 116, 16, 105, 5, 116, 16, 117, 17, 118, 19, -1 }, // station 5 +// { -1, 19, 118, 17, 117, 16, 116, 6, 106, 16, 116, 17, 117, 18, 119, -1 }, // station 6 +// { 21, 119, 18, 120, 20, 120, 20, 107, 7, 120, 20, 120, 20, 118, 19, 121 }, // station 7 +// { 119, 17, 123, 22, 122, 22, 122, 8, 108, 22, 122, 22, 122, 23, 117, 19 } }; // station 8 + +//============================================================================================== + +// explanation: type xyzz +// where x = carbon ladder orientation +// where y = FEB box orientation +// where zz = sensor arrangement on ladder +// with FEB orientation - v19b + Int_t allUnitTypes[16][16]= + { { -1, -1, -1, -1, 10, 0, 9, 0, 101, 0, 109, 0, -1, -1, -1, -1 }, // unit00D Station01 00 + { -1, -1, -1, -1, 0, 1109, 0, 1101, 0, 1009, 0, 1010, -1, -1, -1, -1 }, // unit01U Station01 01 + + { -1, -1, 0, 10, 0, 9, 0, 2, 0, 109, 0, 110, 0, 111, -1, -1 }, // unit01D Station02 02 + { -1, -1, 1111, 0, 1110, 0, 1109, 0, 1002, 0, 1009, 0, 1010, 0, -1, -1 }, // unit02U Station02 03 + + { -1, -1, 14, 0, 12, 0, 12, 0, 103, 0, 112, 0, 113, 0, -1, -1 }, // unit02D Station03 04 + { -1, -1, 0, 1113, 0, 1112, 0, 1103, 0, 1012, 0, 1012, 0, 1014, -1, -1 }, // unit03U Station03 05 + + { -1, 15, 0, 13, 0, 12, 0, 4, 0, 112, 0, 112, 0, 114, 0, -1 }, // unit03D Station04 06 + { -1, 0, 1114, 0, 1112, 0, 1112, 0, 1004, 0, 1012, 0, 1013, 0, 1015, -1 }, // unit04U Station04 07 + + { -1, 0, 18, 0, 17, 0, 16, 0, 105, 0, 116, 0, 117, 0, 119, -1 }, // unit04D Station05 08 + { -1, 1119, 0, 1117, 0, 1116, 0, 1105, 0, 1016, 0, 1017, 0, 1018, 0, -1 }, // unit05U Station05 09 + + { -1, 19, 0, 17, 0, 16, 0, 6, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05D Station06 10 + { -1, 0, 1118, 0, 1117, 0, 1116, 0, 1006, 0, 1016, 0, 1017, 0, 1019, -1 }, // unit06U Station06 11 + + { 21, 0, 25, 0, 20, 0, 20, 0, 107, 0, 120, 0, 120, 0, 127, 0 }, // unit06D Station07 12 + { 0, 1127, 0, 1120, 0, 1120, 0, 1107, 0, 1020, 0, 1020, 0, 1025, 0, 1021 }, // unit07U Station07 13 + + { 0, 24, 0, 22, 0, 22, 0, 8, 0, 122, 0, 122, 0, 123, 0, 126 }, // unit07D Station08 14 + { 1126, 0, 1123, 0, 1122, 0, 1122, 0, 1008, 0, 1022, 0, 1022, 0, 1024, 0 } }; // unit08U Station08 15 + +//============================================================================================== + +// without FEB orientation - v19a +// v19a Int_t allUnitTypes[16][16]= +// v19a { { -1, -1, -1, -1, 10, 0, 9, 0, 1, 0, 9, 0, -1, -1, -1, -1 }, // unit00D Station01 00 +// v19a { -1, -1, -1, -1, 0, 109, 0, 101, 0, 109, 0, 110, -1, -1, -1, -1 }, // unit01U Station01 01 +// v19a { -1, -1, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, -1, -1 }, // unit01D Station02 02 +// v19a { -1, -1, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, -1, -1 }, // unit02U Station02 03 +// v19a { -1, -1, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, -1, -1 }, // unit02D Station03 04 +// v19a { -1, -1, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, -1, -1 }, // unit03U Station03 05 +// v19a { -1, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, -1 }, // unit03D Station04 06 +// v19a { -1, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, -1 }, // unit04U Station04 07 +// v19a { -1, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, -1 }, // unit04D Station05 08 +// v19a { -1, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05U Station05 09 +// v19a { -1, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, -1 }, // unit05D Station06 10 +// v19a { -1, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, -1 }, // unit06U Station06 11 +// v19a { 21, 0, 25, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 27, 0 }, // unit06D Station07 12 +// v19a { 0, 127, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 125, 0, 121 }, // unit07U Station07 13 +// v19a { 0, 24, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 26 }, // unit07D Station08 14 +// v19a { 126, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 124, 0 } }; // unit08U Station08 15 + + +// unitTypes[0] = { 0, 0, 0, 0, 10, 0, 9, 0, 1, 0, 9, 0, 0, 0, 0, 0 }; // unit 0D +// unitTypes[1] = { 0, 0, 0, 0, 0, 109, 0, 101, 0, 109, 0, 110, 0, 0, 0, 0 }; // unit 1U +// unitTypes[2] = { 0, 0, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, 0, 0 }; // unit 1D +// unitTypes[3] = { 0, 0, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, 0, 0 }; // unit 2U +// unitTypes[4] = { 0, 0, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, 0, 0 }; // unit 2D +// unitTypes[5] = { 0, 0, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, 0, 0 }; // unit 3U +// unitTypes[6] = { 0, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, 0 }; // unit 3D +// unitTypes[7] = { 0, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, 0 }; // unit 4U +// unitTypes[8] = { 0, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, 0 }; // unit 4D +// unitTypes[9] = { 0, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, 0 }; // unit 5U +// unitTypes[10] = { 0, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, 0 }; // unit 5D +// unitTypes[11] = { 0, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, 0 }; // unit 6U +// unitTypes[12] = { 21, 0, 18, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 19, 0 }; // unit 6D +// unitTypes[13] = { 0, 119, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 118, 0, 121 }; // unit 7U +// unitTypes[14] = { 0, 17, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 19 }; // unit 7D +// unitTypes[15] = { 119, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 117, 0 }; // unit 8U + + +// // generate unit +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) +// for (Int_t iLadder = 0; iLadder < 16; iLadder++) +// { +// allUnitTypes[iUnit][iLadder] = 0; +// if ((iUnit % 2 == 0) && (allLadderTypes[iUnit/2][iLadder] < 100)) // if carbon structure is oriented upstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// if ((iUnit % 2 == 1) && (allLadderTypes[iUnit/2][iLadder] >= 100)) // if carbon structure is oriented downstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// } + + + // dump unit + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << "DE unitTypes[" << iUnit << "] = { "; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + { + cout << allUnitTypes[iUnit][iLadder]; + if (iLadder < 15) + cout << ", "; + else + cout << " };"; + } + cout << endl; + } + + + // --- Units 01 - 16 + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << endl; + + nLadders = 0; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + if (allUnitTypes[iUnit][iLadder] >= 0) + { + ladderTypes[nLadders] = allUnitTypes[iUnit][iLadder]; + cout << "DE ladderTypes[" << nLadders << "] = " << allUnitTypes[iUnit][iLadder] << ";" << endl; + nLadders++; + } + myunit[iUnit*2+0] = ConstructUnit(0, iUnit*2+0, nLadders, ladderTypes, iUnit/2+1); + myunit[iUnit*2+1] = ConstructUnit(1, iUnit*2+1, nLadders, ladderTypes, iUnit/2+1); + +// if (gkConstructCones) { +// if (iUnit%2 == 0) +// angle = 90; +// else +// angle = -90; +// +// // upstream +// TGeoRotation* coneRot11 = new TGeoRotation; +// coneRot11->RotateZ(angle); +// coneRot11->RotateY(180); +// TGeoCombiTrans* conePosRot11 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-cone_offset[cone_size[iUnit]]-gkLadderGapZ/2., coneRot11); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 1, conePosRot11); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 1, conePosRot11); +// +// // downstream +// TGeoRotation* coneRot12 = new TGeoRotation; +// coneRot12->RotateZ(angle); +// TGeoCombiTrans* conePosRot12 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+cone_offset[cone_size[iUnit]]+gkLadderGapZ/2., coneRot12); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 2, conePosRot12); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 2, conePosRot12); +// +// myunit[iUnit]->GetShape()->ComputeBBox(); +// } + +// CheckVolume(myunit[iUnit]); +// CheckVolume(myunit[iUnit], infoFile); + if ((iUnit%2 == 0)||(iUnit == 15)) + { + CheckVolume(myunit[iUnit*2+0]); + CheckVolume(myunit[iUnit*2+0], infoFile); + CheckVolume(myunit[iUnit*2+1]); + CheckVolume(myunit[iUnit*2+1], infoFile); + } + infoFile << "Position z = " << statPos[iUnit] << endl; + } + // -------------------------------------------------------------------------- + + + // --------------- Create STS volume ------------------------------------ + cout << endl << endl; + cout << "===> Creating STS...." << endl; + +// // --- Determine size of STS box +// Double_t stsX = 0.; +// Double_t stsY = 0.; +// Double_t stsZ = 0.; +// Double_t stsBorder = 2*5.; // 5 cm space for carbon ladders on each side +// for (Int_t iStation = 1; iStation<=8; iStation++) { +// TString statName = Form("Station%02d", iStation); +// TGeoVolume* station = gGeoMan->GetVolume(statName); +// TGeoBBox* shape = (TGeoBBox*) station->GetShape(); +// stsX = TMath::Max(stsX, 2.* shape->GetDX() ); +// stsY = TMath::Max(stsY, 2.* shape->GetDY() ); +// cout << "Station " << iStation << ": Y " << stsY << endl; +// } +// // --- Some border around the stations +// stsX += stsBorder; +// stsY += stsBorder; +// stsZ = ( statPos[7] - statPos[0] ) + stsBorder; +// +// // --- Create box around the stations +// new TGeoBBox("stsBox", stsX/2., stsY/2., stsZ/2.); +// cout << "size of STS box: x " << stsX << " - y " << stsY << " - z " << stsZ << endl; +// +// // --- Create cone hosting the beam pipe +// // --- One straight section with constant radius followed by a cone +// Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +// Double_t z2 = gkPipeZ2; +// Double_t z3 = statPos[7] + 0.5 * stsBorder; // end of STS box +// Double_t r1 = BeamPipeRadius(z1); +// Double_t r2 = BeamPipeRadius(z2); +// Double_t r3 = BeamPipeRadius(z3); +// r1 += 0.01; // safety margin +// r2 += 0.01; // safety margin +// r3 += 0.01; // safety margin +// +// cout << endl; +// cout << z1 << " " << r1 << endl; +// cout << z2 << " " << r2 << endl; +// cout << z3 << " " << r3 << endl; +// +// cout << endl; +// cout << "station1 : " << BeamPipeRadius(statPos[0]) << endl; +// cout << "station2 : " << BeamPipeRadius(statPos[1]) << endl; +// cout << "station3 : " << BeamPipeRadius(statPos[2]) << endl; +// cout << "station4 : " << BeamPipeRadius(statPos[3]) << endl; +// cout << "station5 : " << BeamPipeRadius(statPos[4]) << endl; +// cout << "station6 : " << BeamPipeRadius(statPos[5]) << endl; +// cout << "station7 : " << BeamPipeRadius(statPos[6]) << endl; +// cout << "station8 : " << BeamPipeRadius(statPos[7]) << endl; +// +// // TGeoPcon* cutout = new TGeoPcon("stsCone", 0., 360., 3); // 2.*TMath::Pi(), 3); +// // cutout->DefineSection(0, z1, 0., r1); +// // cutout->DefineSection(1, z2, 0., r2); +// // cutout->DefineSection(2, z3, 0., r3); +// new TGeoTrd2("stsCone1", r1, r2, r1, r2, (z2-z1)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans1 = new TGeoTranslation("trans1", 0., 0., -(z3-z1)/2.+(z2-z1)/2.); +// trans1->RegisterYourself(); +// new TGeoTrd2("stsCone2", r2, r3, r2, r3, (z3-z2)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans2 = new TGeoTranslation("trans2", 0., 0., +(z3-z1)/2.-(z3-z2)/2.); +// trans2->RegisterYourself(); +// +////DE Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +////DE Double_t z2 = statPos[7] + 0.5 * stsBorder; // end of STS box +////DE Double_t slope = (gkPipeR2 - gkPipeR1) / (gkPipeZ2 - gkPipeZ1); +////DE Double_t r1 = gkPipeR1 + slope * (z1 - gkPipeZ1); // at start of STS +////DE Double_t r2 = gkPipeR1 + slope * (z2 - gkPipeZ1); // at end of STS +////DE r1 += 0.1; // safety margin +////DE r2 += 0.1; // safety margin +////DE // new TGeoCone("stsCone", stsZ/2., 0., r1, 0., r2); +////DE new TGeoTrd2("stsCone", r1, r2, r1, r2, stsZ/2.); + + + // // Create holding/cooling plates + // static std::vector< std::vector<Double_t> > plateSizes = { + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // }; + + // // 8-vertex cut-outs { minWidth, maxWidth, minHeight, maxHeight } + // static std::vector< std::vector<Double_t> > plateCutOuts = { + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 17.6, 47.6 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 49.0, 79.0 }, + // { 85.5,115.5, 51.5, 82.8 }, + // { 85.5,115.5, 59.0, 91.4 }, + // { 85.5,115.5, 68.0, 99.0 }, + // }; + + // for (Int_t iPlate = 0; iPlate < 9; iPlate++) { + // Int_t iUnit = iPlate * 2; + // TGeoBBox* outerPlate = new TGeoBBox(Form("outerPlate%02d",iPlate), + // plateSizes[iPlate][0], plateSizes[iPlate][1], plateSizes[iPlate][2]); + + // TGeoBBox* unitShapeR = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+0])->GetShape(); + // TGeoBBox* unitShapeL = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+1])->GetShape(); + + // Double_t maxDx = (unitShapeR->GetDX() + unitShapeL->GetDX()) / 2.; + // Double_t maxDy = TMath::Max(unitShapeR->GetDY(), unitShapeL->GetDY()); + // cout << maxDy << endl; + + // Double_t* cutOutX = new Double_t[8]; + // Double_t* cutOutY = new Double_t[8]; + + // cutOutX[0] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[0] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[1] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[1] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[2] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[2] = 1/2. * plateCutOuts[iPlate][2]; + // cutOutX[3] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[3] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[4] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[4] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[5] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[5] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[6] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[6] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[7] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[7] = 1/2. * plateCutOuts[iPlate][2]; + + // TGeoXtru* cutOutShape = new TGeoXtru(2); + // cutOutShape->SetName(Form("innerPlate%02d", iPlate)); + // cutOutShape->DefinePolygon(8, cutOutX, cutOutY); + // cutOutShape->DefineSection(0, -1*plateSizes[iPlate][2]-1e-7); + // cutOutShape->DefineSection(1, +1*plateSizes[iPlate][2]+1e-7); + + // TGeoShape* plateShape = new TGeoCompositeShape(Form("PlateShape%02d",iPlate), Form("outerPlate%02d-innerPlate%02d",iPlate,iPlate)); + // TGeoVolume* plate = new TGeoVolume(Form("Plate%02d", iPlate), plateShape, gGeoManager->GetMedium("aluminium")); + // plate->SetLineColor(kRed); + // plate->SetTransparency(65); + // plate->GetShape()->ComputeBBox(); + // } + + // --- Create STS volume + TString stsName = "sts_"; + stsName += geoTag; + +// TGeoShape* stsShape = new TGeoCompositeShape("stsShape", +// "stsBox-stsCone1:trans1-stsCone2:trans2"); +// TGeoVolume* sts = new TGeoVolume(stsName.Data(), stsShape, gStsMedium); + + Double_t stsBorder = 2 * 5.; + + TGeoVolume* sts = new TGeoVolumeAssembly(stsName.Data()); + + // --- Place stations in the STS + Double_t stsPosZ = 0.5 * ( statPos[15] + statPos[0] ); // todo units: update statPos[7] + // cout << "stsPosZ " << stsPosZ << " " << statPos[15] << " " << statPos[0] << "*****" << endl; + +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) { + for (Int_t iUnit = 0; iUnit < 18; iUnit++) { +// for (Int_t iUnit = 0; iUnit < 32; iUnit++) { + TGeoVolume* station = gGeoMan->GetVolume(unitName18[iUnit]); +// Double_t posZ = statPos[iUnit] - stsPosZ; + Double_t posZ = statPos18[iUnit] - stsPosZ; +// Double_t posZ = statPos[iUnit/2] - stsPosZ; + TGeoTranslation* trans = new TGeoTranslation(0., 0., posZ); + sts->AddNode(station, iUnit+1, trans); + sts->GetShape()->ComputeBBox(); + } + + // --- Import passive elements from GDML file + if (gkImportPassive) { + ImportPassive(sts, geoTag, infoFile); + } + + cout << endl; + CheckVolume(sts); + // -------------------------------------------------------------------------- + + + // --------------- Finish ----------------------------------------------- + TGeoTranslation* stsTrans = new TGeoTranslation(0., 0., stsPosZ); + top->AddNode(sts, 1, stsTrans); + top->GetShape()->ComputeBBox(); + cout << endl << endl; + + CheckVolume(top); + cout << endl << endl; + gGeoMan->CloseGeometry(); + gGeoMan->CheckOverlaps(0.0001); + gGeoMan->PrintOverlaps(); + gGeoMan->CheckOverlaps(0.0001, "s"); + gGeoMan->PrintOverlaps(); + gGeoMan->Test(); + + TFile* geoFile = new TFile(geoFileName, "RECREATE"); + top->Write(); + cout << endl; + cout << "Geometry " << top->GetName() << " written to " + << geoFileName << endl; + geoFile->Close(); + + TString geoFileName_ = "sts_"; + geoFileName_ = geoFileName_ + geoTag + "_geo.root"; + + geoFile = new TFile(geoFileName_, "RECREATE"); + gGeoMan->Write(); // use this is you want GeoManager format in the output + geoFile->Close(); + + TString geoFileName__ = "sts_"; + geoFileName_ = geoFileName__ + geoTag + "-geo.root"; + sts->Export(geoFileName_); + + geoFile = new TFile(geoFileName_, "UPDATE"); + stsTrans->Write(); + geoFile->Close(); + + // gGeoManager->FindVolumeFast("LadderType10_CarbonElement")->Draw("ogl"); + top->Draw("ogl"); + gGeoManager->SetVisLevel(8); + + infoFile.close(); + +} +// ============================================================================ +// ====== End of main function ===== +// ============================================================================ + + + + + +// **************************************************************************** +// ***** Definition of media, sensors, sectors and ladders ***** +// ***** ***** +// ***** Decoupled from main function for better readability ***** +// **************************************************************************** + + +/** =========================================================================== + ** Create media + ** + ** Currently created: air, active silicon, passive silion + ** + ** Not used for the time being + **/ +Int_t CreateMedia() { + + Int_t nMedia = 0; + Double_t density = 0.; + + // --- Material air + density = 1.205e-3; // [g/cm^3] + TGeoMixture* matAir = new TGeoMixture("sts_air", 3, density); + matAir->AddElement(14.0067, 7, 0.755); // Nitrogen + matAir->AddElement(15.999, 8, 0.231); // Oxygen + matAir->AddElement(39.948, 18, 0.014); // Argon + + // --- Material silicon + density = 2.33; // [g/cm^3] + TGeoElement* elSi = gGeoMan->GetElementTable()->GetElement(14); + TGeoMaterial* matSi = new TGeoMaterial("matSi", elSi, density); + + + // --- Air (passive) + TGeoMedium* medAir = new TGeoMedium("air", nMedia++, matAir); + medAir->SetParam(0, 0.); // is passive + medAir->SetParam(1, 1.); // is in magnetic field + medAir->SetParam(2, 20.); // max. field [kG] + medAir->SetParam(6, 0.001); // boundary crossing precision [cm] + + + // --- Active silicon for sensors + TGeoMedium* medSiAct = new TGeoMedium("silicon", + nMedia++, matSi); + medSiAct->SetParam(0, 1.); // is active + medSiAct->SetParam(1, 1.); // is in magnetic field + medSiAct->SetParam(2, 20.); // max. field [kG] + medSiAct->SetParam(6, 0.001); // boundary crossing precisison [cm] + + // --- Passive silicon for cables + TGeoMedium* medSiPas = new TGeoMedium("carbon", + nMedia++, matSi); + medSiPas->SetParam(0, 0.); // is passive + medSiPas->SetParam(1, 1.); // is in magnetic field + medSiPas->SetParam(2, 20.); // max. field [kG] + medSiPas->SetParam(6, 0.001); // boundary crossing precisison [cm] + + return nMedia; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sensors + ** + ** Sensors are created as volumes with box shape and active silicon as medium. + ** Four kinds of sensors: 3.2x2.2, 6.2x2.2, 6.2x4.2, 6.2x6.2 + **/ +Int_t CreateSensors() { + + Int_t nSensors = 0; + + Double_t xSize = 0.; + Double_t ySize = 0.; + Double_t zSize = gkSensorThickness; + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + + + // --- Sensor type 01: Small sensor (6.2 cm x 2.2 cm) + xSize = gkSensorSizeX; + ySize = 2.2; + TGeoBBox* shape_sensor01 = new TGeoBBox("sensor01", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor01", shape_sensor01, silicon); + nSensors++; + + + // --- Sensor type 02: Medium sensor (6.2 cm x 4.2 cm) + xSize = gkSensorSizeX; + ySize = 4.2; + TGeoBBox* shape_sensor02 = new TGeoBBox("sensor02", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor02", shape_sensor02, silicon); + nSensors++; + + + // --- Sensor type 03: Big sensor (6.2 cm x 6.2 cm) + xSize = gkSensorSizeX; + ySize = 6.2; + TGeoBBox* shape_sensor03 = new TGeoBBox("sensor03", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor03", shape_sensor03, silicon); + nSensors++; + + + // --- Sensor type 04: Big sensor (6.2 cm x 12.4 cm) + xSize = gkSensorSizeX; + ySize = 12.4; + TGeoBBox* shape_sensor04 = new TGeoBBox("sensor04", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor04", shape_sensor04, silicon); + nSensors++; + + + // below are extra small sensors, those are not available in the CAD model + + // --- Sensor Type 05: Half small sensor (4 cm x 2.5 cm) + xSize = 4.0; + ySize = 2.5; + TGeoBBox* shape_sensor05 = new TGeoBBox("sensor05", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor05", shape_sensor05, silicon); + nSensors++; + + + // --- Sensor type 06: Additional "in hole" sensor (3.1 cm x 4.2 cm) + xSize = 3.1; + ySize = 4.2; + TGeoBBox* shape_sensor06 = new TGeoBBox("sensor06", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor06", shape_sensor06, silicon); + nSensors++; + + + // --- Sensor type 07: Mini Medium sensor (1.5 cm x 4.2 cm) + xSize = 1.5; + ySize = 4.2; + TGeoBBox* shape_sensor07 = new TGeoBBox("sensor07", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor07", shape_sensor07, silicon); + nSensors++; + + + return nSensors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sectors + ** + ** A sector is either a single sensor or several chained sensors. + ** It is implemented as TGeoVolumeAssembly. + ** Currently available: + ** - single sensors of type 1 - 4 + ** - two chained sensors of type 4 + ** - three chained sensors of type 4 + **/ +Int_t CreateSectors() { + + Int_t nSectors = 0; + + TGeoVolume* sensor01 = gGeoMan->GetVolume("Sensor01"); + TGeoVolume* sensor02 = gGeoMan->GetVolume("Sensor02"); + TGeoVolume* sensor03 = gGeoMan->GetVolume("Sensor03"); + TGeoVolume* sensor04 = gGeoMan->GetVolume("Sensor04"); + TGeoVolume* sensor05 = gGeoMan->GetVolume("Sensor05"); + TGeoVolume* sensor06 = gGeoMan->GetVolume("Sensor06"); + TGeoVolume* sensor07 = gGeoMan->GetVolume("Sensor07"); + // TGeoBBox* box4 = (TGeoBBox*) sensor04->GetShape(); + + // --- Sector type 1: single sensor of type 1 + TGeoVolumeAssembly* sector01 = new TGeoVolumeAssembly("Sector01"); + sector01->AddNode(sensor01, 1); + sector01->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 2: single sensor of type 2 + TGeoVolumeAssembly* sector02 = new TGeoVolumeAssembly("Sector02"); + sector02->AddNode(sensor02, 1); + sector02->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 3: single sensor of type 3 + TGeoVolumeAssembly* sector03 = new TGeoVolumeAssembly("Sector03"); + sector03->AddNode(sensor03, 1); + sector03->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 4: single sensor of type 4 + TGeoVolumeAssembly* sector04 = new TGeoVolumeAssembly("Sector04"); + sector04->AddNode(sensor04, 1); + sector04->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 5: single sensor of type 5 + TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); + sector05->AddNode(sensor05, 1); + sector05->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 6: single sensor of type 6 + TGeoVolumeAssembly* sector06 = new TGeoVolumeAssembly("Sector06"); + sector06->AddNode(sensor06, 1); + sector06->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 7: single sensor of type 7 + TGeoVolumeAssembly* sector07 = new TGeoVolumeAssembly("Sector07"); + sector07->AddNode(sensor07, 1); + sector07->GetShape()->ComputeBBox(); + nSectors++; + +// // --- Sector type 5: two sensors of type 4 +// TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); +// Double_t shift5 = 0.5 * gkChainGapY + box4->GetDY(); +// TGeoTranslation* transD5 = +// new TGeoTranslation("td", 0., -1. * shift5, 0.); +// TGeoTranslation* transU5 = +// new TGeoTranslation("tu", 0., shift5, 0.); +// sector05->AddNode(sensor04, 1, transD5); +// sector05->AddNode(sensor04, 2, transU5); +// sector05->GetShape()->ComputeBBox(); +// nSectors++; + + return nSectors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create ladders + ** + ** Ladders are the building blocks of the stations. They contain + ** several modules placed one after the other along the z axis + ** such that the sectors are arranged vertically (with overlap). + ** + ** A ladder is constructed out of two half ladders, the second of which + ** is rotated in the x-y plane by 180 degrees and displaced + ** in z direction. + **/ +Int_t CreateLadders() { + + Int_t nLadders = 0; + + // --- Some variables + Int_t nSectors = 0; + Int_t sectorTypes[10]; + TGeoBBox* shape = NULL; + TString s0name; + TString hlname; + char align; + TGeoVolume* s0vol = NULL; + TGeoVolume* halfLadderU = NULL; + TGeoVolume* halfLadderD = NULL; + + // --- Ladders 01-23 + Int_t allSectorTypes[27][6] = { { 1, 2, 3, 3, 0, -1 }, // ladder 01 - 5 - last column defines alignment of small sensors + { 1, 2, 3, 3, 0, 0 }, // ladder 02 - 5 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, -1 }, // ladder 03 - 6 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 04 - 6 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, -1 }, // ladder 05 - 7 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 06 - 7 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 07 - last column defines alignment of small sensors + { 3, 4, 4, 4, 0, 0 }, // ladder 08 - last column defines alignment of small sensors + + { 1, 1, 2, 3, 3, 0 }, // ladder 09 - last column defines alignment of small sensors + { 1, 1, 2, 2, 3, 0 }, // ladder 10 - last column defines alignment of small sensors + { 2, 2, 0, 0, 0, 0 }, // ladder 11 - last column defines alignment of small sensors + { 2, 2, 2, 3, 4, 0 }, // ladder 12 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 13 - last column defines alignment of small sensors + + { 2, 3, 4, 0, 0, 0 }, // ladder 14 - last column defines alignment of small sensors + { 3, 3, 0, 0, 0, 0 }, // ladder 15 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 16 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 17 - last column defines alignment of small sensors + { 3, 4, 4, 0, 0, 0 }, // ladder 18 - last column defines alignment of small sensors + + { 4, 4, 0, 0, 0, 0 }, // ladder 19 - last column defines alignment of small sensors + { 1, 2, 4, 4, 4, 0 }, // ladder 20 - last column defines alignment of small sensors + { 4, 0, 0, 0, 0, 0 }, // ladder 21 - last column defines alignment of small sensors + { 2, 3, 4, 4, 4, 0 }, // ladder 22 - last column defines alignment of small sensors + { 2, 3, 3, 4, 4, 0 }, // ladder 23 - last column defines alignment of small sensors + + { 2, 3, 4, 4, 0, 0 }, // ladder 24 - copy of 17 with different total length + { 3, 4, 4, 0, 0, 0 }, // ladder 25 - copy of 18 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 26 - copy of 19 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 27 - copy of 19 with different total length + }; + +// Issue #405 +// Counting from the most upstream ladder, the gaps between sensors are as follows: +// 01 (most upstream): 41.3mm +// 02: 41.3mm +// 03: 42.0mm +// 04: 48.6mm +// 05: 60.8mm +// 06: 67.0mm +// 07: 79.2mm +// 08 (most downstream): 88.0mm + + Double_t gapXYZ[27][3] = { + { 0., 4.13, 0. }, // ladder 01 + { 0., 4.13, 0. }, // ladder 02 + { 0., 4.20, 0. }, // ladder 03 + { 0., 4.86, 0. }, // ladder 04 + { 0., 6.08, 0. }, // ladder 05 + { 0., 6.70, 0. }, // ladder 06 + { 0., 7.92, 0. }, // ladder 07 + { 0., 8.80, 0. }, // ladder 08 + { 0., -gkSectorOverlapY, 0. }, // ladder 09 + { 0., -gkSectorOverlapY, 0. }, // ladder 10 + { 0., -gkSectorOverlapY, 0. }, // ladder 11 + { 0., -gkSectorOverlapY, 0. }, // ladder 12 + { 0., -gkSectorOverlapY, 0. }, // ladder 13 + { 0., -gkSectorOverlapY, 0. }, // ladder 14 + { 0., -gkSectorOverlapY, 0. }, // ladder 15 + { 0., -gkSectorOverlapY, 0. }, // ladder 16 + { 0., -gkSectorOverlapY, 0. }, // ladder 17 + { 0., -gkSectorOverlapY, 0. }, // ladder 18 + { 0., -gkSectorOverlapY, 0. }, // ladder 19 + { 0., -gkSectorOverlapY, 0. }, // ladder 20 + { 0., -gkSectorOverlapY, 0. }, // ladder 21 + { 0., -gkSectorOverlapY, 0. }, // ladder 22 + { 0., -gkSectorOverlapY, 0. }, // ladder 23 + + { 0., -gkSectorOverlapY, 0. }, // ladder 24 - copy of 17 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 25 - copy of 18 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 26 - copy of 19 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 27 - copy of 19 with different total length + }; + + Double_t ladderLength[27] = { + 48.0, // ladder 01 + 48.0, // ladder 02 + 64.0, // ladder 03 + 64.0, // ladder 04 + 80.0, // ladder 05 + 80.0, // ladder 06 + 92.0, // ladder 07 + 96.0, // ladder 08 + 48.0, // ladder 09 + 48.0, // ladder 10 + 48.0, // ladder 11 + 64.0, // ladder 12 + 64.0, // ladder 13 + 64.0, // ladder 14 + 64.0, // ladder 15 + 80.0, // ladder 16 + 80.0, // ladder 17 + 80.0, // ladder 18 + 80.0, // ladder 19 + 92.0, // ladder 20 + 92.0, // ladder 21 + 96.0, // ladder 22 + 96.0, // ladder 23 + + 96.0, // ladder 24 - copy of 17 with different total length + 92.0, // ladder 25 - copy of 18 with different total length + 96.0, // ladder 26 - copy of 19 with different total length + 92.0, // ladder 27 - copy of 19 with different total length + }; +// ======================================================================== + + // calculate Z shift for ladders with and without gaps in the center + s0name = Form("Sector%02d", allSectorTypes[0][0]); + s0vol = gGeoMan->GetVolume(s0name); + shape = (TGeoBBox*) s0vol->GetShape(); + + for (Int_t iLadder = 0; iLadder < 27; iLadder++) + { + if (iLadder+1 <= 8) // for the 2 inner ladders of each station with gap for beampipe + gapXYZ[iLadder][2] = 0; // there is no offset in z for halfladders on ladders with a beampipe hole + else + gapXYZ[iLadder][2] = 2. * shape->GetDZ() + gkSectorGapZ; // set displacement in z for overlapping half ladders + } + +// ======================================================================== + + for (Int_t iLadder = 0; iLadder < 27; iLadder++) + { + cout << endl; + nSectors = 0; + for (Int_t i=0; i < 5; i++) + if (allSectorTypes[iLadder][i] != 0) + { + sectorTypes[nSectors] = allSectorTypes[iLadder][i]; // copy sectors for this ladder + cout << "DE iLadder " << iLadder+1 << " sectorTypes[" << nSectors << "] = " << allSectorTypes[iLadder][i] << ";" << endl; + nSectors++; // count how many sectors are in this ladder + } + + if (allSectorTypes[iLadder][5] == 0) + align = 'l'; + else + align = 'r'; + hlname = Form("HalfLadder%02du", iLadder+1); + // build upper half ladder + halfLadderU = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2.); // mirrored + + if (allSectorTypes[iLadder][5] == 0) + align = 'r'; + else + align = 'l'; + hlname = Form("HalfLadder%02dd", iLadder+1); + // build lower half ladder + halfLadderD = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2.); // mirrored + + // at this point half ladders are constructed + + // build all 4 possible ladders types for this sensor arrangement + ConstructLadder( iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19a + ConstructLadder( 100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19b + + ConstructLadder(1000+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19k + ConstructLadder(1100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19k + + nLadders++; + } + + return nLadders; +} +/** ======================================================================= **/ + + + +// **************************************************************************** +// ***** ***** +// ***** Generic functions for the construction of STS elements ***** +// ***** ***** +// ***** module: volume (made of a sector and a cable) ***** +// ***** haf ladder: assembly (made of modules) ***** +// ***** ladder: assembly (made of two half ladders) ***** +// ***** station: volume (made of ladders) ***** +// ***** ***** +// **************************************************************************** + + + +/** =========================================================================== + ** Construct a module + ** + ** A module is a sector plus the readout cable extending from the + ** top of the sector. The cable is made from passive silicon. + ** The cable has the same x size as the sector. + ** Its thickness is given by the global variable gkCableThickness. + ** The cable length is a parameter. + ** The sensor(s) of the sector is/are placed directly in the module; + ** the sector is just auxiliary for the proper placement. + ** + ** Arguments: + ** name volume name + ** sector pointer to sector volume + ** cableLength length of cable + **/ +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength) { + + // --- Check sector volume + if ( ! sector ) Fatal("CreateModule", "Sector volume not found!"); + + // --- Get size of sector + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + + // --- Get size of cable + Double_t cableX = sectorX; + Double_t cableY = cableLength; + Double_t cableZ = gkCableThickness; + + // --- Create module volume + Double_t moduleX = TMath::Max(sectorX, cableX); + Double_t moduleY = sectorY + cableLength; + + Double_t moduleZ = TMath::Max(sectorZ, cableZ); + + TGeoVolume* module = gGeoManager->MakeBox(name, gStsMedium, + moduleX/2., + moduleY/2., + moduleZ/2.); + + // --- Position of sector in module + // --- Sector is centred in x and z and aligned to the bottom + Double_t sectorXpos = 0.; + Double_t sectorYpos = 0.5 * (sectorY - moduleY); + Double_t sectorZpos = 0.; + + + // --- Get sensor(s) from sector + Int_t nSensors = sector->GetNdaughters(); + for (Int_t iSensor = 0; iSensor < nSensors; iSensor++) { + TGeoNode* sensor = sector->GetNode(iSensor); + + // --- Calculate position of sensor in module + const Double_t* xSensTrans = sensor->GetMatrix()->GetTranslation(); + Double_t sensorXpos = 0.; + Double_t sensorYpos = sectorYpos + xSensTrans[1]; + Double_t sensorZpos = 0.; + TGeoTranslation* sensTrans = new TGeoTranslation("sensTrans", + sensorXpos, + sensorYpos, + sensorZpos); + + // --- Add sensor volume to module + TGeoVolume* sensVol = sensor->GetVolume(); + module->AddNode(sensor->GetVolume(), iSensor+1, sensTrans); + module->GetShape()->ComputeBBox(); + } + + + // --- Create cable volume, if necessary, and place it in module + // --- Cable is centred in x and z and aligned to the top + if ( gkConstructCables && cableLength > 0.0001 ) { + TString cableName = TString(name) + "_cable"; + TGeoMedium* cableMedium = gGeoMan->GetMedium("STScable"); + if ( ! cableMedium ) Fatal("CreateModule", "Medium STScable not found!"); + TGeoVolume* cable = gGeoManager->MakeBox(cableName.Data(), + cableMedium, + cableX / 2., + cableY / 2., + cableZ / 2.); + // add color to cables + cable->SetLineColor(kOrange); + cable->SetTransparency(60); + Double_t cableXpos = 0.; + Double_t cableYpos = sectorY + 0.5 * cableY - 0.5 * moduleY; + Double_t cableZpos = 0.; + TGeoTranslation* cableTrans = new TGeoTranslation("cableTrans", + cableXpos, + cableYpos, + cableZpos); + module->AddNode(cable, 1, cableTrans); + module->GetShape()->ComputeBBox(); + } + + return module; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a half ladder + ** + ** A half ladder is a virtual volume (TGeoVolumeAssembly) consisting + ** of several modules arranged on top of each other. The modules + ** have a given overlap in y and a displacement in z to allow for the + ** overlap. + ** + ** The typ of sectors / modules to be placed must be specified: + ** 1 = sensor01 + ** 2 = sensor02 + ** 3 = sensor03 + ** 4 = sensor04 + ** 5 = 2 x sensor04 (chained) + ** 6 = 3 x sensor04 (chained) + ** The cable is added automatically from the top of each sensor to + ** the top of the half ladder. + ** The alignment can be left (l) or right (r), which matters in the + ** case of different x sizes of sensors (e.g. SensorType01). + ** + ** Arguments: + ** name volume name + ** nSectors number of sectors + ** sectorTypes array with sector types + ** align horizontal alignment of sectors + * ladderLength full length of the ladder towards FEE + * offsetY gap in the beam-pipe region + **/ +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY) { + + // --- Create half ladder volume assembly + TGeoVolumeAssembly* halfLadder = new TGeoVolumeAssembly(name); + + // --- Determine size of ladder + Double_t ladderX = 0.; + Double_t ladderY = 0.; + Double_t ladderZ = 0.; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + if ( ! sector ) + Fatal("ConstructHalfLadder", Form("Volume %s not found", sectorName.Data())); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + // --- Ladder x size equals largest sector x size + ladderX = TMath::Max(ladderX, 2. * box->GetDX()); + // --- Ladder y size is sum of sector ysizes + ladderY += 2. * box->GetDY(); + // --- Ladder z size is sum of sector z sizes + ladderZ += 2. * box->GetDZ(); + } + // --- Subtract overlaps in y + ladderY -= Double_t(nSectors-1) * gkSectorOverlapY; + // --- Add gaps in z direction + ladderZ += Double_t(nSectors-1) * gkSectorGapZ; + + ladderY = TMath::Max(ladderLength - offsetY, ladderY); + + // --- Create and place modules + Double_t yPosSect = -0.5 * ladderY; + Double_t zPosMod = -0.5 * ladderZ; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + yPosSect += 0.5 * sectorY; // Position of sector in ladder + Double_t cableLength = 0.5 * ladderY - yPosSect - 0.5 * sectorY; + TString moduleName = name + "_" + Form("Module%02d", + sectorTypes[iSector]); + TGeoVolume* module = ConstructModule(moduleName.Data(), + sector, cableLength); + + TGeoBBox* shapeMod = (TGeoBBox*) module->GetShape(); + Double_t moduleX = 2. * shapeMod->GetDX(); + Double_t moduleY = 2. * shapeMod->GetDY(); + Double_t moduleZ = 2. * shapeMod->GetDZ(); + Double_t xPosMod = 0.; + if ( align == 'l' ) + xPosMod = 0.5 * (moduleX - ladderX); // left aligned + else if ( align == 'r' ) + xPosMod = 0.5 * (ladderX - moduleX); // right aligned + else + xPosMod = 0.; // centred in x + Double_t yPosMod = 0.5 * (ladderY - moduleY); // top aligned + zPosMod += 0.5 * moduleZ; + TGeoTranslation* trans = new TGeoTranslation("t", xPosMod, + yPosMod, zPosMod); + halfLadder->AddNode(module, iSector+1, trans); + halfLadder->GetShape()->ComputeBBox(); + yPosSect += 0.5 * sectorY - gkSectorOverlapY; + zPosMod += 0.5 * moduleZ + gkSectorGapZ; + } + + CheckVolume(halfLadder); + cout << endl; + + return halfLadder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Add a carbon support to a ladder + ** + ** Arguments: + ** LadderIndex ladder number + ** ladder pointer to ladder + ** xu size of halfladder + ** ladderY height of ladder along y + ** ladderZ thickness of ladder along z + **/ +void AddCarbonLadder(Int_t LadderIndex, + TGeoVolume* ladder, + Double_t xu, + Double_t ladderY, + Double_t ladderZ) { + + // --- Some variables + TString name = Form("LadderType%04d", LadderIndex); // v19k + Int_t i; + Double_t j; + + Int_t YnumOfFrameBoxes = round(ladderY / gkFrameStep); + + // cout << "DEXZ: lad " << LadderIndex << " inum " << YnumOfFrameBoxes << endl; + + Double_t ladderDZ = (xu/2. + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2)/2.; + cout << "DEFR: frame Z size " << 2 * ladderDZ << " cm" << endl; + + TGeoBBox* fullFrameShp = new TGeoBBox (name+"_CarbonElement_shp", xu/2., gkFrameStep/2., ladderDZ); + TGeoVolume* fullFrameBoxVol = new TGeoVolume(name+"_CarbonElement", fullFrameShp, gStsMedium); + + ConstructFrameElement("CarbonElement", fullFrameBoxVol, xu/2.); + TGeoRotation* fullFrameRot = new TGeoRotation; + fullFrameRot->RotateY(180); + + Int_t inum = YnumOfFrameBoxes; + for (i=1; i<=inum; i++) + { + j=-(inum-1)/2.+(i-1); + // -(10-1)/2. +0 +10-1 -> -4.5 .. +4.5 -> -0.5, +0.5 (= 2) + // -(11-1)/2. +0 +11-1 -> -5.0 .. +5.0 -> -1, 0, 1 (= 3) + // cout << "DE: i " << i << " j " << j << endl; + + if (LadderIndex % 100 <= 3) // central ladders in stations 1 to 3 + { + if ((j>=-1) && (j<=1)) // keep the inner 2 (even) or 3 (odd) elements free for the cone + continue; + } + else if (LadderIndex % 100 <= 8) // central ladders in stations 4 to 8 + { + if ((j>=-2) && (j<=2)) // keep the inner 4 elements free for the cone + continue; + } + + cout << "DELZ: ladderDZ " << ladderDZ << " cm " << -ladderZ/2. - ladderDZ << " cm " << endl; + ladder->AddNode(fullFrameBoxVol, i, new TGeoCombiTrans(name+"_CarbonElement_posrot", 0., j*gkFrameStep, -(ladderZ/2.+ladderDZ), fullFrameRot)); + } + + ladder->GetShape()->ComputeBBox(); + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Construct a ladder out of two half ladders with vertical gap + ** + ** The second half ladder will be rotated by 180 degrees + ** in the x-y plane. The two half ladders will be put on top of each + ** other with a vertical gap. + ** + ** Arguments: + ** name volume name + ** halfLadderU pointer to upper half ladder + ** halfLadderD pointer to lower half ladder + ** gapY vertical gap + ** shiftZ relative displacement along the z axis + **/ + + TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ) { + + // --- Some variables + TGeoBBox* shape = NULL; + + // --- Dimensions of half ladders + shape = (TGeoBBox*) halfLadderU->GetShape(); + Double_t xu = 2. * shape->GetDX(); + Double_t yu = 2. * shape->GetDY(); + Double_t zu = 2. * shape->GetDZ(); + + shape = (TGeoBBox*) halfLadderD->GetShape(); + Double_t xd = 2. * shape->GetDX(); + Double_t yd = 2. * shape->GetDY(); + Double_t zd = 2. * shape->GetDZ(); + + + // --- Create ladder volume assembly + +// TString name = Form("LadderType%02d", LadderIndex); // v19a +// TString name = Form("LadderType%03d", LadderIndex); // v19b + TString name = Form("LadderType%04d", LadderIndex); // v19k + TGeoVolumeAssembly* ladder = new TGeoVolumeAssembly(name); + Double_t ladderX = TMath::Max(xu, xd); + Double_t ladderY = yu + yd + gapY; + Double_t ladderZ = TMath::Max(zu, zd + shiftZ); + + // --- Place half ladders + Double_t xPosU = 0.; // centred in x + Double_t yPosU = 0.5 * ( ladderY - yu ); // top aligned + Double_t zPosU = 0.5 * ( ladderZ - zu ); // front aligned // mount upper half ladder last + if (LadderIndex >= 1000) zPosU = -zPosU; // back aligned // mount upper half ladder first + + TGeoTranslation* tu = new TGeoTranslation("tu", xPosU, yPosU, zPosU); + ladder->AddNode(halfLadderU, 1, tu); + + Double_t xPosD = 0.; // centred in x + Double_t yPosD = 0.5 * ( yd - ladderY ); // bottom aligned + Double_t zPosD = 0.5 * ( zd - ladderZ ); // back aligned // mount lower half ladder first + if (LadderIndex >= 1000) zPosD = -zPosD; // front aligned // mount lower half ladder last + + TGeoRotation* rd = new TGeoRotation(); + rd->RotateZ(180.); + TGeoCombiTrans* cd = new TGeoCombiTrans(xPosD, yPosD, zPosD, rd); + ladder->AddNode(halfLadderD, 2, cd); + + ladder->GetShape()->ComputeBBox(); + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD0ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + cout << "DDDD ladder" << LadderIndex << endl; + cout << "DDDD1ladder" << LadderIndex << " ladderX " << ladderX << " ladderY " << ladderY << " ladderZ " << ladderZ << endl; + + // ---------------- Create and place frame boxes ------------------------ + + if (gkConstructFrames) + AddCarbonLadder(LadderIndex, ladder, ladderX, ladderY, ladderZ); + + // -------------------------------------------------------------------------- + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD2ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + return ladder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a unit + ** + ** The unit volume is the minimal box comprising all ladders + ** minus a tube accomodating the beam pipe. + ** + ** The ladders are arranged horizontally from left to right with + ** a given overlap in x. + ** Every second ladder is slightly displaced upstream from the centre + ** z plane and facing downstream, the others are slightly displaced + ** downstream and facing upstream (rotated around the y axis). + ** + ** Arguments: + ** name volume name + ** nLadders number of ladders + ** ladderTypes array of ladder types + **/ + + TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation) { + + Bool_t isFirstPartOfHalfUnit = kFALSE; + + // TString name = Form("Unit%02d", iUnit); // 0,1,2,3,4,5,6,7 - Unit00 missing in output + // TString name = Form("Unit%02d", iUnit+1); // 1,2,3,4,5,6,7,8 + + TGeoVolume* unit = gGeoMan->GetVolume(unitName[iUnit]); + if ( ! unit ) // if it does not yet exist, create a new one + { + unit = new TGeoVolumeAssembly(unitName[iUnit]); + isFirstPartOfHalfUnit = kTRUE; + } + + // --- Some local variables + TGeoBBox* ladderShape = NULL; + TGeoVolume* ladder = NULL; + TString ladderName; + Double_t subtractedVal; + + // --- Determine size of unit from ladders + Double_t statX = 0.; + // Double_t statY = 0.; + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { +// Int_t ladderType = ladderTypes[iLadder]%100; // v19a +// Int_t ladderType = ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100; // v19b + Int_t ladderType = ladderTypes[iLadder]; // v19k + +// if (iSide == 0) cout << "DWER " << ladderTypes[iLadder] << " " << ladderType << endl; + + if (ladderType > 0) + { +// ladderName = Form("LadderType%02d", ladderType); // v19a +// ladderName = Form("LadderType%03d", ladderType); // v19b + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + if ( ! ladder ) Fatal("ConstructUnit", + Form("Volume %s not found", ladderName.Data())); + ladderShape = (TGeoBBox*) ladder->GetShape(); + statX += 2. * ladderShape->GetDX(); + // statY = TMath::Max(statY, 2. * ladderShape->GetDY()); + } + else + statX += gkSensorSizeX; // empty ladder in unit + } + statX -= Double_t(nLadders-1) * gkLadderOverlapX; + +// if (iSide == 0) cout << "DWER -" << endl; + + // --- Place ladders in unit + cout << "xPos0: " << statX << endl; + Double_t xPos = -0.5 * statX; + cout << "xPos1: " << xPos << endl; + Double_t yPos = 0.; + Double_t zPos = 0.; + + Double_t maxdz = 0.; + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { // find maximum dz in this unit +// Int_t ladderType = ladderTypes[iLadder]%100; // v19a +// Int_t ladderType = ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100; // v19b + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { +// ladderName = Form("LadderType%02d", ladderType); // v19a +// ladderName = Form("LadderType%03d", ladderType); // v19b + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + if (maxdz < ladderShape->GetDZ()) + maxdz = ladderShape->GetDZ(); + } + } + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { +// Int_t ladderType = ladderTypes[iLadder]%100; // v19a +// Int_t ladderType = ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100; // v19b + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { +// ladderName = Form("LadderType%02d", ladderType); // v19a +// ladderName = Form("LadderType%03d", ladderType); // v19b + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + xPos += ladderShape->GetDX(); + cout << "xPos2: " << xPos << endl; + yPos = 0.; // vertically centred + TGeoRotation* rot = new TGeoRotation(); + + if (gkConstructFrames) + subtractedVal = ladderShape->GetDX() + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2; + else + subtractedVal = 0.; + + zPos = 0.5 * gkLadderGapZ + (2*maxdz-ladderShape->GetDZ()-subtractedVal/2.); // z-aligned ladders + +// v19a cout << "DE ladder" << ladderTypes[iLadder]%100 +// v19b cout << "DE ladder" << ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100 +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " dx: " << ladderShape->GetDX() + << " dy: " << ladderShape->GetDY() + << " dz: " << ladderShape->GetDZ() + << " max dz: " << maxdz << endl; + +// v19a cout << "DE ladder" << ladderTypes[iLadder]%100 +// v19b cout << "DE ladder" << ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100 +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " fra: " << gkFrameThickness/2. + << " sub: " << subtractedVal + << " zpo: " << zPos << endl << endl; + +// v19a if (ladderTypes[iLadder]/100 == 1) // flip some of the ladders to reproduce the CAD layout + if (ladderTypes[iLadder]/1000 == 1) // flip some of the ladders to reproduce the CAD layout + rot->RotateY(180.); + else + zPos = -zPos; + + if (!isFirstPartOfHalfUnit) + // zPos += 10; + zPos += 10.5; // v19d +// zPos += 11.0; // v19e + + TGeoCombiTrans* trans = new TGeoCombiTrans(xPos, yPos, zPos, rot); +// start +// cout << "DEEE** iLadder " << iLadder << " " << nLadders/2 << " " << nLadders << endl; + + if (iSide == 0) + { + if (iLadder < nLadders/2) // right side - only half unit -x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + else + { + if (iLadder >= nLadders/2) // left side - only half unit +x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + unit->GetShape()->ComputeBBox(); +// stop + xPos += ladderShape->GetDX() - gkLadderOverlapX; + cout << "xPos3: " << xPos << endl; + } + else + xPos += gkSensorSizeX - gkLadderOverlapX; + } + + return unit; + } +/** ======================================================================= **/ + + +/** =========================================================================== + ** Import and add the passive materials to the STS volume + **/ +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile) +{ + TString passiveName = TString("sts_passive_") + geoTag; + TString basePath = gSystem->Getenv("VMCWORKDIR"); + TString relPath = "/geometry/sts/passive/" + passiveName + ".gdml"; + TString passiveFileName = basePath + relPath; + infoFile << std::endl << std::endl; + infoFile << "Importing STS passive materials from GDML file '" << relPath << "'." << std::endl; + + TGDMLParse parser; + TGeoVolume* gdmlVolume = parser.GDMLReadFile(passiveFileName); + PostProcessGdml(gdmlVolume); + gdmlVolume->SetName(passiveName); + + TGeoTranslation* passiveTrans = new TGeoTranslation(0., 0., 4.68 - 2.); + infoFile << "Passive assembly is translated for Z=2.68 cm downstream with respect to parent volume" << std::endl << std::endl; + + gdmlVolume->GetShape()->ComputeBBox(); + CheckVolume(gdmlVolume, infoFile); + + infoFile << std::endl; + for (Int_t iNode = 0; iNode < gdmlVolume->GetNdaughters(); iNode++) { + CheckVolume(gdmlVolume->GetNode(iNode)->GetVolume(), infoFile, kFALSE); + } + + stsVolume->AddNode(gdmlVolume, stsVolume->GetNdaughters(), passiveTrans, ""); +} + +/** =========================================================================== + ** Assign visual properties to the imported gdml volumes + **/ +void PostProcessGdml(TGeoVolume* gdmlVolume) +{ + const UInt_t kPOBColor = kRed-6; + const UInt_t kPOBTransparency = 0;// 5; + + const UInt_t kFEBColor = kOrange-6; + const UInt_t kFEBTransparency = 0;// 5; + + const UInt_t kUnitColor = kCyan-10; + const UInt_t kUnitTransparency = 0;// 5; + + const UInt_t kCfColor = kGray+3; + const UInt_t kCfTransparency = 0;// 10; + + // name <Color, Transparency> + std::map<std::string, std::tuple<UInt_t,UInt_t> > props { + { "passive_POB", std::tuple<UInt_t,UInt_t> {kPOBColor, kPOBTransparency} }, + { "passive_FEB", std::tuple<UInt_t,UInt_t> {kFEBColor, kFEBTransparency} }, + { "passive_unit", std::tuple<UInt_t,UInt_t> {kUnitColor, kUnitTransparency} }, + { "passive_Box_Wall", std::tuple<UInt_t,UInt_t> {kCfColor, kCfTransparency} }, + { "passive_Box_Wall_Front_CF2", std::tuple<UInt_t,UInt_t> {kCfColor-3, kCfTransparency} }, + }; + + // Match volume name and apply visual properties + const TObjArray* volumes = gGeoManager->GetListOfVolumes(); + for (auto& entry : props) { + TIter next(volumes); + TGeoVolume *vol = nullptr; + while ((vol=(TGeoVolume*)next())) { + if (TString(vol->GetName()).Contains(entry.first.c_str())) { + vol->SetLineColor(std::get<0>(entry.second)); + vol->SetTransparency(std::get<1>(entry.second)); + } + } + } +} + +/** =========================================================================== + ** Volume information for debugging + **/ +void CheckVolume(TGeoVolume* volume) { + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + cout << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) cout << ", assembly"; + else { + if ( volume->GetMedium() ) + cout << ", medium " << volume->GetMedium()->GetName(); + else cout << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + cout << endl; + if ( volume->GetNdaughters() ) { + cout << "Daughters: " << endl; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) { + TGeoNode* node = volume->GetNode(iNode); + TGeoBBox* shape = (TGeoBBox*) node->GetVolume()->GetShape(); + cout << setw(15) << node->GetName() << ", size " + << fixed << setprecision(3) + << setw(6) << 2. * shape->GetDX() << " x " + << setw(6) << 2. * shape->GetDY() << " x " + << setw(6) << 2. * shape->GetDZ() << ", position ( "; + TGeoMatrix* matrix = node->GetMatrix(); + const Double_t* pos = matrix->GetTranslation(); + cout << setfill(' '); + cout << fixed << setw(8) << pos[0] << ", " + << setw(8) << pos[1] << ", " + << setw(8) << pos[2] << " )" << endl; + } + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Volume information for output to file + **/ +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren) { + if ( ! file ) return; + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + file << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) file << ", assembly"; + else { + if ( volume->GetMedium() ) + file << ", medium " << volume->GetMedium()->GetName(); + else file << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + file << endl; + if ( volume->GetNdaughters() && listChildren) { + file << "Contains: "; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) + file << volume->GetNode(iNode)->GetVolume()->GetName() << " "; + file << endl; + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Calculate beam pipe outer radius for a given z + **/ +Double_t BeamPipeRadius(Double_t z) { + if ( z < gkPipeZ2 ) return gkPipeR1; + Double_t slope = (gkPipeR3 - gkPipeR2 ) / (gkPipeZ3 - gkPipeZ2); + return gkPipeR2 + slope * (z - gkPipeZ2); +} +/** ======================================================================= **/ + + + +/** ======================================================================= **/ +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + TGeoBBox* frameVertPillarShp; + + Double_t t = gkFrameThickness/2.; + + // --- Main vertical pillars +// TGeoBBox* frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, gkFrameStep/2., t); // square crossection, along y +// TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); +// frameVertPillarVol->SetLineColor(kGreen); +// frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoTranslation(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2.)); +// frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoTranslation(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkCylindricalFrames) + // TGeoBBox* frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", 0, t, gkFrameStep/2.); // circle crossection, along z + frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", gkCylinderDiaInner/2., gkCylinderDiaOuter/2., gkFrameStep/2.); // circle crossection, along z + else + frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, t, gkFrameStep/2.); // square crossection, along z + TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); + frameVertPillarVol->SetLineColor(kGreen); + + TGeoRotation* xRot90 = new TGeoRotation; + xRot90->RotateX(90.); + frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoCombiTrans(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoCombiTrans(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + + // TGeoRotation* vertRot = new TGeoRotation(name + "_vertpillar_rot_1", 90., 45., -90.); + TGeoRotation* vertRot = new TGeoRotation; + vertRot->RotateX(90.); + vertRot->RotateY(45.); + frameBoxVol->AddNode(frameVertPillarVol, 3, new TGeoCombiTrans(name + "_vertpillar_pos_3", 0., 0., (x-sqrt(2.)*t)/2., vertRot)); + + // --- Small horizontal pillar + // TGeoBBox* frameHorPillarShp = new TGeoBBox(name + "_horpillar_shape", x-2.*t, gkThinFrameThickness/2., gkThinFrameThickness/2.); + // TGeoVolume* frameHorPillarVol = new TGeoVolume(name + "_horpillar", frameHorPillarShp, framesMaterial); + // frameHorPillarVol->SetLineColor(kCyan); + // frameBoxVol->AddNode(frameHorPillarVol, 1, new TGeoTranslation(name + "_horpillar_pos_1", 0., -gkFrameStep/2.+gkThinFrameThickness/2., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkConstructSmallFrames) { + + // --- Small sloping pillars + TGeoPara* frameSlopePillarShp = new TGeoPara(name + "_slopepillar_shape", + (x-2.*t)/TMath::Cos(31.4/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., 31.4, 0., 90.); + TGeoVolume* frameSlopePillarVol = new TGeoVolume(name + "_slopepillar", frameSlopePillarShp, framesMaterial); + frameSlopePillarVol->SetLineColor(kCyan); + TGeoRotation* slopeRot = new TGeoRotation(name + "_slopepillar_rot_1", 0., 0., 31.4); + TGeoRotation* slopeRot2 = new TGeoRotation(name + "_slopepillar_rot_2", 0., 0., -31.4); + TGeoCombiTrans* slopeTrRot = new TGeoCombiTrans(name + "_slopepillar_posrot_1", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot); + TGeoCombiTrans* slopeTrRot2 = new TGeoCombiTrans(name + "_slopepillar_posrot_2", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot2); + + frameBoxVol->AddNode(frameSlopePillarVol, 1, slopeTrRot); + frameBoxVol->AddNodeOverlap(frameSlopePillarVol, 2, slopeTrRot2); + + + Double_t angl = 23.; + // --- Small sub pillar + TGeoPara* frameSubPillarShp = new TGeoPara(name + "_subpillar_shape", + (sqrt(2)*(x/2.-t)-t/2.)/TMath::Cos(angl/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., angl, 0., 90.); + TGeoVolume* frameSubPillarVol = new TGeoVolume(name + "_subpillar", frameSubPillarShp, framesMaterial); + frameSubPillarVol->SetLineColor(kMagenta); + + Double_t posZ = t * (1. - 3. / ( 2.*sqrt(2.) )); + + // one side of X direction + TGeoRotation* subRot1 = new TGeoRotation(name + "_subpillar_rot_1", 90., 45., -90.+angl); + TGeoCombiTrans* subTrRot1 = new TGeoCombiTrans(name + "_subpillar_posrot_1", -(-x/2.+t-t/(2.*sqrt(2.))), 1., posZ, subRot1); + + TGeoRotation* subRot2 = new TGeoRotation(name + "_subpillar_rot_2", 90., -90.-45., -90.+angl); + TGeoCombiTrans* subTrRot2 = new TGeoCombiTrans(name + "_subpillar_posrot_2", -(-x/2.+t-t/(2.*sqrt(2.))), -1., posZ, subRot2); + + // other side of X direction + TGeoRotation* subRot3 = new TGeoRotation(name + "_subpillar_rot_3", 90., 90.+45., -90.+angl); + TGeoCombiTrans* subTrRot3 = new TGeoCombiTrans(name + "_subpillar_posrot_3", -x/2.+t-t/(2.*sqrt(2.)), 1., posZ, subRot3); + + TGeoRotation* subRot4 = new TGeoRotation(name + "_subpillar_rot_4", 90., -45., -90.+angl); + TGeoCombiTrans* subTrRot4 = new TGeoCombiTrans(name + "_subpillar_posrot_4", -x/2.+t-t/(2.*sqrt(2.)), -1., posZ, subRot4); + + frameBoxVol->AddNode(frameSubPillarVol, 1, subTrRot1); + frameBoxVol->AddNode(frameSubPillarVol, 2, subTrRot2); + frameBoxVol->AddNode(frameSubPillarVol, 3, subTrRot3); + frameBoxVol->AddNode(frameSubPillarVol, 4, subTrRot4); + // frameBoxVol->GetShape()->ComputeBBox(); + } + + return frameBoxVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructSmallCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 6., 7.6, 6., 6.04, 0., 180.); +// TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + Double_t radius = 3.0; + Double_t thickness = 0.04; // 0.4 mm +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 3., 3.2, 3., 3.2, 0., 180.); + TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, radius, radius+thickness, radius, radius+thickness, 0., 180.); + TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + TGeoCombiTrans* M = new TGeoCombiTrans ("M"); + M->RotateX (45.); + M->SetDy (-5.575); + M->SetDz (6.935); + M->RegisterYourself(); + + TGeoShape* coneShp = new TGeoCompositeShape ("Cone_shp", "A-B:M"); + TGeoVolume* coneVol = new TGeoVolume ("Cone", coneShp, framesMaterial); + coneVol->SetLineColor(kGreen); +// coneVol->RegisterYourself(); + +// // --- Inner cone +// Double_t thickness = 0.02; +// Double_t thickness2 = 0.022; +// // TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); +// TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 3.+thickness, 4.6-thickness2, 2.99+thickness, 3.05-thickness2, 0., 180.); +// +// TGeoCombiTrans* M2 = new TGeoCombiTrans ("M2"); +// M2->RotateX (45.); +// M2->SetDy (-5.575+thickness*sqrt(2.)); +// M2->SetDz (6.935); +// M2->RegisterYourself(); +// +// TGeoShape* coneShp2 = new TGeoCompositeShape ("Cone2_shp", "A2-B:M2"); +// TGeoVolume* coneVol2 = new TGeoVolume ("Cone2", coneShp2, gStsMedium); +// coneVol2->SetLineColor(kGreen); +//// coneVol2->RegisterYourself(); +// +// coneVol->AddNode(coneVol2, 1); + + return coneVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructBigCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone + TGeoConeSeg* bA = new TGeoConeSeg ("bA", coneDz, 6., 7.6, 6., 6.04, 0., 180.); + TGeoBBox* bB = new TGeoBBox ("bB", 8., 6., 10.); + + TGeoCombiTrans* bM = new TGeoCombiTrans ("bM"); + bM->RotateX (45.); + bM->SetDy (-5.575); + bM->SetDz (6.935); + bM->RegisterYourself(); + + TGeoShape* coneBigShp = new TGeoCompositeShape ("ConeBig_shp", "bA-bB:bM"); + TGeoVolume* coneBigVol = new TGeoVolume ("ConeBig", coneBigShp, framesMaterial); + coneBigVol->SetLineColor(kGreen); +// coneBigVol->RegisterYourself(); + + // --- Inner cone + Double_t thickness = 0.02; + Double_t thickness2 = 0.022; + TGeoConeSeg* bA2 = new TGeoConeSeg ("bA2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); + + TGeoCombiTrans* bM2 = new TGeoCombiTrans ("bM2"); + bM2->RotateX (45.); + bM2->SetDy (-5.575+thickness*sqrt(2.)); + bM2->SetDz (6.935); + bM2->RegisterYourself(); + + TGeoShape* coneBigShp2 = new TGeoCompositeShape ("ConeBig2_shp", "bA2-bB:bM2"); + TGeoVolume* coneBigVol2 = new TGeoVolume ("ConeBig2", coneBigShp2, gStsMedium); + coneBigVol2->SetLineColor(kGreen); +// coneBigVol2->RegisterYourself(); + + coneBigVol->AddNode(coneBigVol2, 1); + + return coneBigVol; +} + +/** ======================================================================= **/ diff --git a/macro/sts/geometry/create_stsgeo_v19m.C b/macro/sts/geometry/create_stsgeo_v19m.C new file mode 100644 index 0000000000000000000000000000000000000000..de49950f4378255cb486db4cc3755f8668ea49d0 --- /dev/null +++ b/macro/sts/geometry/create_stsgeo_v19m.C @@ -0,0 +1,2373 @@ +/****************************************************************************** + ** Creation of STS geometry in ROOT format (TGeo). + ** + ** @file create_stsgeo_v19m.C + ** @author Volker Friese <v.friese@gsi.de> + ** @since 15 June 2012 + ** @date 09.05.2014 + ** @author Tomas Balog <T.Balog@gsi.de> + ** + ** v19m: based on v19k - parameters : delta Z prime = 0.55 cm - delta Z pitch = 0.20 cm (bug) + ** v19l: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.15 cm + ** v19k: ladders on upstream side of units get upper half ladders installed first, + ** ladders on downstream side of units get lower half ladders installed first, + ** this saves 1.5 mm space in z per station, 12 mm in total (LadderType went from 3 to 4 digits) + ** parameters : delta Z prime = 1.00 cm - delta Z pitch = 0.15 cm + ** v19j: use overlap and distance parameters from CAD model + ** v19h: put STS stations from v19d at z-positions = 260; 365; 470; 575; 680; 785; 890; 995 mm + ** v19g: place a box with services around v19e + ** v19f: place a box with services around v19d + ** v19e: increase spacing between stations by +10 mm from 100 mm + ** v19d: increase spacing between stations by + 5 mm from 100 mm + ** v19c: drop station 8 and increase spacing between remaining 7 stations from 10 cm to 12 c + ** v19b: introduce FEB orientation in ladder numbering (LadderType went from 2 to 3 digits) + ** v19a: import passive materials from gdml file + ** extend CF ladder structures and cables towards FEE plane + ** change CF ladder frame shape + ** v18d: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu (based on v18b) + ** v18c: fixed cut-out windows in cooling plates, improve the box shape/materials + ** v18b: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu + ** v18a: adds 9 cooling/holding plates and a box around the setup + ** v16g: v16g is the new standard geometry from November 2017 + ** v16g: switch from stations to units - left / right ("Unit01L", "Unit01R") + ** v16f: switch from stations to units + ** - split in upstream / downstream and left / right parts + ** - named Unit0xUR, Unit0xUL, Unit0xDR, Unit0xDL + ** v16e: switch from stations to units - upstream / downstream ("Unit01U", "Unit01D") + ** v16d: skip keeping volumes of sts and stations + ** v16c: like v16b, but senors of ladders beampipe next to beampipe + ** shifted closer to the pipe, like in the CAD model + ** v16b: like v16a, but yellow sensors removed + ** v16a: derived from v15c (no cones), but with sensor types renamed: + ** 2 -> 1, 3 -> 2, 4 -> 3, 5 -> 4, 1 -> 5 + ** + ** v15c: as v15b without cones + ** v15b: introduce modified carbon ladders from v13z + ** v15a: with flipped ladder orientation for stations 0,2,4,6 to match CAD design + ** + ** TODO: + ** + ** DONE: + ** v15b - use carbon macaroni as ladder support + ** v15b - introduce a small gap between lowest sensor and carbon ladder + ** v15b - build small cones for the first 2 stations + ** v15b - within a station the ladders of adjacent units should not touch eachother - set gkLadderGapZ to 10 mm + ** v15b - for all ladders set an even number of ladder elements + ** v15b - z offset of cones to ladders should not be 0.3 by default, but 0.26 + ** v15b - within a station the ladders should be aligned in z, defined either by the unit or the ladder with most sensors + ** v15b - get rid of cone overlap in stations 7 and 8 - done by adapting rHole size + ** + ** The geometry hierarachy is: + ** + ** 1. Sensors (see function CreateSensors) + ** The sensors are the active volumes and the lowest geometry level. + ** They are built as TGeoVolumes, shape box, material silicon. + ** x size is determined by strip pitch 58 mu and 1024 strips + ** plus guard ring of 1.3 mm at each border -> 6.1992 cm. + ** Sensor type 1 is half of that (3.0792 cm). + ** y size is determined by strip length (2.2 / 4.2 / 6.3 cm) plus + ** guard ring of 1.3 mm at top and bottom -> 2.46 / 4.46 / 6.46 cm. + ** z size is a parameter, to be set by gkSensorThickness. + ** + ** 2. Sectors (see function CreateSectors) + ** Sectors consist of several chained sensors. These are arranged + ** vertically on top of each other with a gap to be set by + ** gkChainGapY. Sectors are constructed as TGeoVolumeAssembly. + ** The sectors are auxiliary volumes used for proper placement + ** of the sensor(s) in the module. They do not show up in the + ** final geometry. + ** + ** 3. Modules (see function ConstructModule) + ** A module is a readout unit, consisting of one sensor or + ** a chain of sensors (see sector) and a cable. + ** The cable extends from the top of the sector vertically to the + ** top of the halfladder the module is placed in. The cable and module + ** volume thus depend on the vertical position of the sector in + ** the halfladder. The cables consist of silicon with a thickness to be + ** set by gkCableThickness. + ** Modules are constructed as TGeoVolume, shape box, medium gStsMedium. + ** The module construction can be switched off (gkConstructCables) + ** to reproduce older geometries. + ** + ** 4. Halfladders (see function ConstructHalfLadder) + ** A halfladder is a vertical assembly of several modules. The modules + ** are placed vertically such that their sectors overlap by + ** gkSectorOverlapY. They are displaced in z direction to allow for the + ** overlap in y by gkSectorGapZ. + ** The horizontal placement of modules in the halfladder can be choosen + ** to left aligned or right aligned, which only matters if sensors of + ** different x size are involved. + ** Halfladders are constructed as TGeoVolumeAssembly. + ** + ** 5. Ladders (see function CreateLadders and ConstructLadder) + ** A ladder is a vertical assembly of two halfladders, and is such the + ** vertical building block of a station. The second (bottom) half ladder + ** is rotated upside down. The vertical arrangement is such that the + ** inner sectors of the two halfladders have the overlap gkSectorOverlapY + ** (function CreateLadder) or that there is a vertical gap for the beam + ** hole (function CreateLadderWithGap). + ** Ladders are constructed as TGeoVolumeAssembly. + ** + ** 6. Stations (see function ConstructStation) + ** A station represents one layer of the STS geometry: one measurement + ** at (approximately) a given z position. It consist of several ladders + ** arranged horizontally to cover the acceptance. + ** The ladders are arranged such that there is a horizontal overlap + ** between neighbouring ladders (gkLadderOverLapX) and a vertical gap + ** to allow for this overlap (gkLadderGapZ). Each second ladder is + ** rotated around its y axis to face away from or into the beam. + ** Stations are constructed as TGeoVolumes, shape box minus tube (for + ** the beam hole), material gStsMedium. + ** + ** 7. STS + ** The STS is a volume hosting the entire detectors system. It consists + ** of several stations located at different z positions. + ** The STS is constructed as TGeoVolume, shape box minus cone (for the + ** beam pipe), material gStsMedium. The size of the box is computed to + ** enclose all stations. + *****************************************************************************/ + + +// Remark: With the proper steering variables, this should exactly reproduce +// the geometry version v11b of A. Kotynia's described in the ASCII format. +// The only exception is a minimal difference in the z position of the +// sectors/sensors. This is because of ladder types 2 and 4 containing the half +// sensors around the beam hole (stations 1,2 and 3). In v11b, the two ladders +// covering the beam hole cannot be transformed into each other by rotations, +// but only by a reflection. This means they are constructionally different. +// To avoid introducing another two ladder types, the difference in z position +// was accepted. + + +// Differences to v12: +// gkChainGap reduced from 1 mm to 0 +// gkCableThickness increased from 100 mum to 200 mum (2 cables per module) +// gkSectorOverlapY reduced from 3 mm to 2.4 mm +// New sensor types 05 and 06 +// New sector types 07 and 08 +// Re-definiton of ladders (17 types instead of 8) +// Re-definiton of station from new ladders + + +#include <iomanip> +#include <iostream> +#include "TGeoManager.h" + +#include "TGeoTube.h" +#include "TGeoPara.h" +#include "TGeoCone.h" +#include "TGeoTrd2.h" +#include "TGeoCompositeShape.h" +#include "TGeoXtru.h" +#include "TGeoPhysicalNode.h" + +// forward declarations +Int_t CreateSensors(); +Int_t CreateSectors(); +Int_t CreateLadders(); +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength); +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY); +TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ); +TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation); +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile); +void PostProcessGdml(TGeoVolume* gdmlTop); +void CheckVolume(TGeoVolume* volume); +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren = kTRUE); +Double_t BeamPipeRadius(Double_t z); +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x); +TGeoVolume* ConstructSmallCone(Double_t coneDz); +TGeoVolume* ConstructBigCone(Double_t coneDz); + +// ------------- Version highlight ----------------------------------- + +const std::string gVersionHighlight = R"( +Summary: + This version adds passive materials imported from GDML model to the STS geometry: + * Taken from and largely correspond to mechanical CAD drawings of the detector + * Thermal insulation box: + - made out of carbon sandwitch panel (2mm carbon fiber sheet + layer of carbon foam + 2mm carbon fiber sheet) + - front window of complex shape with interface to MVD / target chamber + - back window with large aperture (2000 x 1200 mm) square cut into carbon foam + * Structural units: + - made of 2 complex shape aluminum C-Frames, 15mm thick + - placed at 25, 35, ... ,105 cm absolute Z + - contain front-end and power distribution boxes with equivalent X_0 values + + Scripted geometry tweaks: + * Ladders and cables are extended towards the read-out planes having same lengths in respective rows + * Adjusted form and shape of carbon ladder structures from L-type to X-type + * Reduced verbosity of this file + + Sensor arrangement is the same as in version v16g + + !! Important for this version is the discrepancy from the mechanical CAD w.r.t. front wall. + The square window was replaced by a round one to avoid overlaps with present beam pipe designs, e.g. pipe_v16b_1e +)"; + +// ------------- Steering variables ----------------------------------- + +// ---> Horizontal width of sensors [cm] +const Double_t gkSensorSizeX = 6.2; // was 6.2092; // 6.2 - Oleg CAD 15/05/2020 + +// ---> Thickness of sensors [cm] +const Double_t gkSensorThickness = 0.03; + +// ---> Vertical gap between chained sensors [cm] +const Double_t gkChainGapY = 0.00; + +// ---> Thickness of cables [cm] +const Double_t gkCableThickness = 0.02; + +// ---> Horizontal overlap of neighbouring ladders [cm] +const Double_t gkLadderOverlapX = 0.25; // delta X - Oleg CAD 14/05/2020 + +// ---> Vertical overlap of neighbouring sectors in a ladder [cm] +const Double_t gkSectorOverlapY = 0.46; // delta Y - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring sectors in a ladder [cm] +const Double_t gkSectorGapZ = 0.17; // gap + thickness = pitch // delta Z pitch = 0.20 - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring ladders [cm] +const Double_t gkLadderGapZ = 0.50 - 0.20; // for asym // 0.5 for sym // delta Z prime + +// ---> Gap in z between lowest sector to carbon support structure [cm] +const Double_t gkSectorGapZFrame = 0.280 - 0.025; // Oleg CAD 05/05/2020 // there is a 2.8 mm gap between the bottom side of the sensor and the top ledge of the carbon ladder + +// ---> Switch to construct / not to construct readout cables +const Bool_t gkConstructCables = kTRUE; + +// ---> Switch to construct / not to construct frames +const Bool_t gkConstructCones = kFALSE; // kTRUE; // switch this false by default for v15c and v16x +const Bool_t gkConstructFrames = kTRUE; // kFALSE; // switch this true by default for v15c and v16x +const Bool_t gkConstructSmallFrames = kTRUE; // kFALSE; +const Bool_t gkCylindricalFrames = kTRUE; // kFALSE; + +// ---> Size of the frame +const Double_t gkFrameThickness = 0.2; +const Double_t gkThinFrameThickness = 0.05; +const Double_t gkFrameStep = 4.0; // size of frame cell along y direction + +const Double_t gkCylinderDiaInner = 0.07; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) +const Double_t gkCylinderDiaOuter = 0.15; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) + +// ---> Switch to import / not to import the Passive materials from GDML file +//const Bool_t gkImportPassive = kTRUE; +const Bool_t gkImportPassive = kFALSE; + +// ---------------------------------------------------------------------------- + + +// -------------- Parameters of beam pipe in the STS region -------------- +// ---> Needed to compute stations and STS such as to avoid overlaps +const Double_t gkPipeZ1 = 22.0; +const Double_t gkPipeR1 = 1.8; +const Double_t gkPipeZ2 = 50.0; +const Double_t gkPipeR2 = 1.8; +const Double_t gkPipeZ3 = 125.0; +const Double_t gkPipeR3 = 5.5; + +//DE const Double_t gkPipeZ1 = 27.0; +//DE const Double_t gkPipeR1 = 1.05; +//DE const Double_t gkPipeZ2 = 160.0; +//DE const Double_t gkPipeR2 = 3.25; +// ---------------------------------------------------------------------------- + +//TString unitName[16] = // names of units for v16e +// { "Unit00D", +// "Unit01U", "Unit01D", +// "Unit02U", "Unit02D", +// "Unit03U", "Unit03D", +// "Unit04U", "Unit04D", +// "Unit05U", "Unit05D", +// "Unit06U", "Unit06D", +// "Unit07U", "Unit07D", +// "Unit08U" }; + +//TString unitName[32] = // names of units for v16f +// { "Unit00DR", "Unit00DL", +// "Unit01UR", "Unit01UL", "Unit01DR", "Unit01DL", +// "Unit02UR", "Unit02UL", "Unit02DR", "Unit02DL", +// "Unit03UR", "Unit03UL", "Unit03DR", "Unit03DL", +// "Unit04UR", "Unit04UL", "Unit04DR", "Unit04DL", +// "Unit05UR", "Unit05UL", "Unit05DR", "Unit05DL", +// "Unit06UR", "Unit06UL", "Unit06DR", "Unit06DL", +// "Unit07UR", "Unit07UL", "Unit07DR", "Unit07DL", +// "Unit08UR", "Unit08UL" }; + +TString unitName[32] = // names of units for v16g - while merging D and U parts + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", "Unit01R", "Unit01L", + "Unit02R", "Unit02L", "Unit02R", "Unit02L", + "Unit03R", "Unit03L", "Unit03R", "Unit03L", + "Unit04R", "Unit04L", "Unit04R", "Unit04L", + "Unit05R", "Unit05L", "Unit05R", "Unit05L", + "Unit06R", "Unit06L", "Unit06R", "Unit06L", + "Unit07R", "Unit07L", "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +TString unitName18[18] = // names of units for v16g + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", + "Unit02R", "Unit02L", + "Unit03R", "Unit03L", + "Unit04R", "Unit04L", + "Unit05R", "Unit05L", + "Unit06R", "Unit06L", + "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +// ------------- Other global variables ----------------------------------- +// ---> STS medium (for every volume except silicon) +TGeoMedium* gStsMedium = NULL; // will be set later +// ---> TGeoManager (too lazy to write out 'Manager' all the time +TGeoManager* gGeoMan = NULL; // will be set later +// ---------------------------------------------------------------------------- + + + + +// ============================================================================ +// ====== Main function ===== +// ============================================================================ + +void create_stsgeo_v19m(const char* geoTag="v19m") +{ + + // ------- Geometry file name (output) ---------------------------------- + TString geoFileName = "sts_"; + geoFileName = geoFileName + geoTag + ".geo.root"; + // -------------------------------------------------------------------------- + + + // ------- Open info file ----------------------------------------------- + TString infoFileName = geoFileName; + infoFileName.ReplaceAll("root", "info"); + fstream infoFile; + infoFile.open(infoFileName.Data(), fstream::out); + infoFile << "STS geometry created with create_stsgeo_v19m.C" << endl; + infoFile << gVersionHighlight << endl; + infoFile << "Global variables: " << endl; + infoFile << "Sensor thickness = " << gkSensorThickness << " cm" << endl; + infoFile << "Vertical gap in sensor chain = " + << gkChainGapY << " cm" << endl; + infoFile << "Vertical overlap of sensors = " + << gkSectorOverlapY << " cm" << endl; + infoFile << "Gap in z between neighbour sensors = " + << gkSectorGapZ << " cm" << endl; + infoFile << "Horizontal overlap of sensors = " + << gkLadderOverlapX << " cm" << endl; + infoFile << "Gap in z between neighbour ladders = " + << gkLadderGapZ << " cm" << endl; + if ( gkConstructCables ) + infoFile << "Cable thickness = " << gkCableThickness << " cm" << endl; + else + infoFile << "No cables" << endl; + infoFile << endl; + infoFile << "Beam pipe: R1 = " << gkPipeR1 << " cm at z = " + << gkPipeZ1 << " cm" << endl; + infoFile << "Beam pipe: R2 = " << gkPipeR2 << " cm at z = " + << gkPipeZ2 << " cm" << endl; + infoFile << "Beam pipe: R3 = " << gkPipeR3 << " cm at z = " + << gkPipeZ3 << " cm" << endl; + // -------------------------------------------------------------------------- + + + // ------- Load media from media file ----------------------------------- + FairGeoLoader* geoLoad = new FairGeoLoader("TGeo","FairGeoLoader"); + FairGeoInterface* geoFace = geoLoad->getGeoInterface(); + TString geoPath = gSystem->Getenv("VMCWORKDIR"); + TString medFile = geoPath + "/geometry/media.geo"; + geoFace->setMediaFile(medFile); + geoFace->readMedia(); + gGeoMan = gGeoManager; + // -------------------------------------------------------------------------- + + + // ----------------- Get and create the required media ----------------- + FairGeoMedia* geoMedia = geoFace->getMedia(); + FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder(); + + // ---> air + FairGeoMedium* mAir = geoMedia->getMedium("air"); + if ( ! mAir ) Fatal("Main", "FairMedium air not found"); + geoBuild->createMedium(mAir); + TGeoMedium* air = gGeoMan->GetMedium("air"); + if ( ! air ) Fatal("Main", "Medium air not found"); + + // ---> silicon + FairGeoMedium* mSilicon = geoMedia->getMedium("silicon"); + if ( ! mSilicon ) Fatal("Main", "FairMedium silicon not found"); + geoBuild->createMedium(mSilicon); + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + if ( ! silicon ) Fatal("Main", "Medium silicon not found"); + + // ---> carbon + FairGeoMedium* mCarbon = geoMedia->getMedium("carbon"); + if ( ! mCarbon ) Fatal("Main", "FairMedium carbon not found"); + geoBuild->createMedium(mCarbon); + TGeoMedium* carbon = gGeoMan->GetMedium("carbon"); + if ( ! carbon ) Fatal("Main", "Medium carbon not found"); + + // ---> STSBoxCarbonFoam + FairGeoMedium* mSTSBoxCarbonFoam = geoMedia->getMedium("STSBoxCarbonFoam"); + if ( ! mSTSBoxCarbonFoam ) Fatal("Main", "FairMedium STSBoxCarbonFoam not found"); + geoBuild->createMedium(mSTSBoxCarbonFoam); + TGeoMedium* STSBoxCarbonFoam = gGeoMan->GetMedium("STSBoxCarbonFoam"); + if ( ! STSBoxCarbonFoam ) Fatal("Main", "Medium STSBoxCarbonFoam not found"); + + // ---> STSBoxCarbonFibre + FairGeoMedium* mSTSBoxCarbonFibre = geoMedia->getMedium("STSBoxCarbonFibre"); + if ( ! mSTSBoxCarbonFibre ) Fatal("Main", "FairMedium STSBoxCarbonFibre not found"); + geoBuild->createMedium(mSTSBoxCarbonFibre); + TGeoMedium* STSBoxCarbonFibre = gGeoMan->GetMedium("STSBoxCarbonFibre"); + if ( ! STSBoxCarbonFibre ) Fatal("Main", "Medium STSBoxCarbonFibre not found"); + + // ---> STScable + FairGeoMedium* mSTScable = geoMedia->getMedium("STScable"); + if ( ! mSTScable ) Fatal("Main", "FairMedium STScable not found"); + geoBuild->createMedium(mSTScable); + TGeoMedium* STScable = gGeoMan->GetMedium("STScable"); + if ( ! STScable ) Fatal("Main", "Medium STScable not found"); + + // ---> Aluminium + FairGeoMedium* mAluminium = geoMedia->getMedium("aluminium"); + if ( ! mAluminium ) Fatal("Main", "FairMedium aluminium not found"); + geoBuild->createMedium(mAluminium); + TGeoMedium* aluminium = gGeoMan->GetMedium("aluminium"); + if ( ! aluminium ) Fatal("Main", "Medium aluminium not found"); + + // --- + gStsMedium = air; + // -------------------------------------------------------------------------- + + + // -------------- Create geometry and top volume ------------------------- + gGeoMan = (TGeoManager*)gROOT->FindObject("FAIRGeom"); +// gGeoMan->SetName("STSgeom"); + TGeoVolume* top = new TGeoVolumeAssembly("top"); +// TGeoBBox* topbox= new TGeoBBox("", 120., 120., 120.); +// TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air")); + gGeoMan->SetTopVolume(top); + // -------------------------------------------------------------------------- + + + // -------------- Create media ------------------------------------------ + /* + cout << endl; + cout << "===> Creating media...."; + cout << CreateMedia(); + cout << " media created" << endl; + TList* media = gGeoMan->GetListOfMedia(); + for (Int_t iMedium = 0; iMedium < media->GetSize(); iMedium++ ) { + cout << "Medium " << iMedium << ": " + << ((TGeoMedium*) media->At(iMedium))->GetName() << endl; + } + gStsMedium = gGeoMan->GetMedium("air"); + if ( ! gStsMedium ) Fatal("Main", "medium sts_air not found"); + */ + // -------------------------------------------------------------------------- + + + // --------------- Create sensors --------------------------------------- + cout << endl << endl; + cout << "===> Creating sensors...." << endl << endl; + infoFile << endl << "Sensors: " << endl; + Int_t nSensors = CreateSensors(); + for (Int_t iSensor = 1; iSensor <= nSensors; iSensor++) { + TString name = Form("Sensor%02d",iSensor); + TGeoVolume* sensor = gGeoMan->GetVolume(name); + + // add color to sensors + if (iSensor == 1) + sensor->SetLineColor(kRed); + if (iSensor == 2) + sensor->SetLineColor(kGreen); + if (iSensor == 3) + sensor->SetLineColor(kBlue); + if (iSensor == 4) + sensor->SetLineColor(kAzure); + if (iSensor == 5) + sensor->SetLineColor(kYellow); + if (iSensor == 6) + sensor->SetLineColor(kYellow); + if (iSensor == 7) + sensor->SetLineColor(kYellow); + + CheckVolume(sensor); + CheckVolume(sensor, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create sectors -------------------------------------- + cout << endl << endl; + cout << "===> Creating sectors...." << endl; + // infoFile << endl << "Sectors: " << endl; + Int_t nSectors = CreateSectors(); + for (Int_t iSector = 1; iSector <= nSectors; iSector++) { + // cout << endl; + TString name = Form("Sector%02d", iSector); + TGeoVolume* sector = gGeoMan->GetVolume(name); + CheckVolume(sector); + // CheckVolume(sector, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create ladders -------------------------------------- + cout << endl << endl; + cout << "===> Creating ladders...." << endl; + infoFile << endl << "Ladders:" << endl; + + TString name = ""; + TGeoVolume* ladder; + + + Int_t nLadders = CreateLadders(); + + for (Int_t iLadder = 1; iLadder <= nLadders; iLadder++) { + cout << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType0%02d", iLadder); // v19b + name = Form("LadderType00%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF1: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType1%02d", iLadder); // v19b + name = Form("LadderType01%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF2: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType10%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF3: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType11%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF4: ladder name: " << name << endl << endl; + } + // -------------------------------------------------------------------------- + + + // ---------------- Create cones ---------------------------------------- + Double_t coneDz = 1.64; + TGeoVolume* coneSmallVolum = ConstructSmallCone(coneDz); + if (!coneSmallVolum) Fatal("ConstructSmallCone", "Volume Cone not found"); + TGeoVolume* coneBigVolum = ConstructBigCone(coneDz); + if (!coneBigVolum) Fatal("ConstructBigCone", "Volume Cone not found"); + // -------------------------------------------------------------------------- + + + // ---------------- Create stations ------------------------------------- + cout << endl << endl; + cout << "===> Creating stations...." << endl; + infoFile << endl << "Stations: " << endl; + Int_t angle = 0; + nLadders = 0; + Int_t ladderTypes[16]; // there are max 16 ladders in one layer + TGeoTranslation* statTrans = NULL; + + TGeoVolume *myunit[32]; // units + +// Int_t statPos[8] = { 30, 40, 50, 60, 70, 80, 90, 100 }; // z positions of stations +// Int_t statPos[16] = { 28, 32, 38, 42, 48, 52, 58, 62, +// 68, 72, 78, 82, 88, 92, 98,102 }; // z positions of units +// Int_t statPos[16] = { 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units +// Int_t statPos18[18] = { 30, 30, // expanded for placement of Unit00 +// 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units + // v19h + Double_t statPos[16] = { 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of units + Double_t statPos18[18] = { 26.0, 26.0, // expanded for placement of Unit00 + 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of unit + +// // v19d +// Double_t statPos[16] = { 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units +// Double_t statPos18[18] = { 30.0, 30.0, // expanded for placement of Unit00 +// 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units + +////Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.9 , 3.7 , 3.7 , 4.2 , 4.2 }; // size of cutouts in stations +// Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.43, 3.04, 3.35, 3.96, 4.2 }; // size of cutouts in stations, derived from gapXYZ[x][1]/2 + + Int_t cone_size[8] = { 0, 0, 0, 1, 1, 1, 1, 1 }; // size of cones: 0 = small, 1 = large + + Double_t cone_offset[2] = { 0.305, 0.285 }; + +// Int_t allLadderTypes[8][16]= +// { { -1, -1, -1, -1, 10, 109, 9, 101, 1, 109, 9, 110, -1, -1, -1, -1 }, // station 1 +// { -1, -1, 111, 10, 110, 9, 109, 2, 102, 9, 109, 10, 110, 11, -1, -1 }, // station 2 +// { -1, -1, 14, 113, 12, 112, 12, 103, 3, 112, 12, 112, 13, 114, -1, -1 }, // station 3 +// { -1, 15, 114, 13, 112, 12, 112, 4, 104, 12, 112, 12, 113, 14, 115, -1 }, // station 4 +// { -1, 119, 18, 117, 17, 116, 16, 105, 5, 116, 16, 117, 17, 118, 19, -1 }, // station 5 +// { -1, 19, 118, 17, 117, 16, 116, 6, 106, 16, 116, 17, 117, 18, 119, -1 }, // station 6 +// { 21, 119, 18, 120, 20, 120, 20, 107, 7, 120, 20, 120, 20, 118, 19, 121 }, // station 7 +// { 119, 17, 123, 22, 122, 22, 122, 8, 108, 22, 122, 22, 122, 23, 117, 19 } }; // station 8 + +//============================================================================================== + +// explanation: type xyzz +// where x = carbon ladder orientation +// where y = FEB box orientation +// where zz = sensor arrangement on ladder +// with FEB orientation - v19b + Int_t allUnitTypes[16][16]= + { { -1, -1, -1, -1, 10, 0, 9, 0, 101, 0, 109, 0, -1, -1, -1, -1 }, // unit00D Station01 00 + { -1, -1, -1, -1, 0, 1109, 0, 1101, 0, 1009, 0, 1010, -1, -1, -1, -1 }, // unit01U Station01 01 + + { -1, -1, 0, 10, 0, 9, 0, 2, 0, 109, 0, 110, 0, 111, -1, -1 }, // unit01D Station02 02 + { -1, -1, 1111, 0, 1110, 0, 1109, 0, 1002, 0, 1009, 0, 1010, 0, -1, -1 }, // unit02U Station02 03 + + { -1, -1, 14, 0, 12, 0, 12, 0, 103, 0, 112, 0, 113, 0, -1, -1 }, // unit02D Station03 04 + { -1, -1, 0, 1113, 0, 1112, 0, 1103, 0, 1012, 0, 1012, 0, 1014, -1, -1 }, // unit03U Station03 05 + + { -1, 15, 0, 13, 0, 12, 0, 4, 0, 112, 0, 112, 0, 114, 0, -1 }, // unit03D Station04 06 + { -1, 0, 1114, 0, 1112, 0, 1112, 0, 1004, 0, 1012, 0, 1013, 0, 1015, -1 }, // unit04U Station04 07 + + { -1, 0, 18, 0, 17, 0, 16, 0, 105, 0, 116, 0, 117, 0, 119, -1 }, // unit04D Station05 08 + { -1, 1119, 0, 1117, 0, 1116, 0, 1105, 0, 1016, 0, 1017, 0, 1018, 0, -1 }, // unit05U Station05 09 + + { -1, 19, 0, 17, 0, 16, 0, 6, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05D Station06 10 + { -1, 0, 1118, 0, 1117, 0, 1116, 0, 1006, 0, 1016, 0, 1017, 0, 1019, -1 }, // unit06U Station06 11 + + { 21, 0, 25, 0, 20, 0, 20, 0, 107, 0, 120, 0, 120, 0, 127, 0 }, // unit06D Station07 12 + { 0, 1127, 0, 1120, 0, 1120, 0, 1107, 0, 1020, 0, 1020, 0, 1025, 0, 1021 }, // unit07U Station07 13 + + { 0, 24, 0, 22, 0, 22, 0, 8, 0, 122, 0, 122, 0, 123, 0, 126 }, // unit07D Station08 14 + { 1126, 0, 1123, 0, 1122, 0, 1122, 0, 1008, 0, 1022, 0, 1022, 0, 1024, 0 } }; // unit08U Station08 15 + +//============================================================================================== + +// without FEB orientation - v19a +// v19a Int_t allUnitTypes[16][16]= +// v19a { { -1, -1, -1, -1, 10, 0, 9, 0, 1, 0, 9, 0, -1, -1, -1, -1 }, // unit00D Station01 00 +// v19a { -1, -1, -1, -1, 0, 109, 0, 101, 0, 109, 0, 110, -1, -1, -1, -1 }, // unit01U Station01 01 +// v19a { -1, -1, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, -1, -1 }, // unit01D Station02 02 +// v19a { -1, -1, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, -1, -1 }, // unit02U Station02 03 +// v19a { -1, -1, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, -1, -1 }, // unit02D Station03 04 +// v19a { -1, -1, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, -1, -1 }, // unit03U Station03 05 +// v19a { -1, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, -1 }, // unit03D Station04 06 +// v19a { -1, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, -1 }, // unit04U Station04 07 +// v19a { -1, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, -1 }, // unit04D Station05 08 +// v19a { -1, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05U Station05 09 +// v19a { -1, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, -1 }, // unit05D Station06 10 +// v19a { -1, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, -1 }, // unit06U Station06 11 +// v19a { 21, 0, 25, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 27, 0 }, // unit06D Station07 12 +// v19a { 0, 127, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 125, 0, 121 }, // unit07U Station07 13 +// v19a { 0, 24, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 26 }, // unit07D Station08 14 +// v19a { 126, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 124, 0 } }; // unit08U Station08 15 + + +// unitTypes[0] = { 0, 0, 0, 0, 10, 0, 9, 0, 1, 0, 9, 0, 0, 0, 0, 0 }; // unit 0D +// unitTypes[1] = { 0, 0, 0, 0, 0, 109, 0, 101, 0, 109, 0, 110, 0, 0, 0, 0 }; // unit 1U +// unitTypes[2] = { 0, 0, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, 0, 0 }; // unit 1D +// unitTypes[3] = { 0, 0, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, 0, 0 }; // unit 2U +// unitTypes[4] = { 0, 0, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, 0, 0 }; // unit 2D +// unitTypes[5] = { 0, 0, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, 0, 0 }; // unit 3U +// unitTypes[6] = { 0, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, 0 }; // unit 3D +// unitTypes[7] = { 0, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, 0 }; // unit 4U +// unitTypes[8] = { 0, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, 0 }; // unit 4D +// unitTypes[9] = { 0, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, 0 }; // unit 5U +// unitTypes[10] = { 0, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, 0 }; // unit 5D +// unitTypes[11] = { 0, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, 0 }; // unit 6U +// unitTypes[12] = { 21, 0, 18, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 19, 0 }; // unit 6D +// unitTypes[13] = { 0, 119, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 118, 0, 121 }; // unit 7U +// unitTypes[14] = { 0, 17, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 19 }; // unit 7D +// unitTypes[15] = { 119, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 117, 0 }; // unit 8U + + +// // generate unit +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) +// for (Int_t iLadder = 0; iLadder < 16; iLadder++) +// { +// allUnitTypes[iUnit][iLadder] = 0; +// if ((iUnit % 2 == 0) && (allLadderTypes[iUnit/2][iLadder] < 100)) // if carbon structure is oriented upstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// if ((iUnit % 2 == 1) && (allLadderTypes[iUnit/2][iLadder] >= 100)) // if carbon structure is oriented downstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// } + + + // dump unit + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << "DE unitTypes[" << iUnit << "] = { "; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + { + cout << allUnitTypes[iUnit][iLadder]; + if (iLadder < 15) + cout << ", "; + else + cout << " };"; + } + cout << endl; + } + + + // --- Units 01 - 16 + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << endl; + + nLadders = 0; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + if (allUnitTypes[iUnit][iLadder] >= 0) + { + ladderTypes[nLadders] = allUnitTypes[iUnit][iLadder]; + cout << "DE ladderTypes[" << nLadders << "] = " << allUnitTypes[iUnit][iLadder] << ";" << endl; + nLadders++; + } + myunit[iUnit*2+0] = ConstructUnit(0, iUnit*2+0, nLadders, ladderTypes, iUnit/2+1); + myunit[iUnit*2+1] = ConstructUnit(1, iUnit*2+1, nLadders, ladderTypes, iUnit/2+1); + +// if (gkConstructCones) { +// if (iUnit%2 == 0) +// angle = 90; +// else +// angle = -90; +// +// // upstream +// TGeoRotation* coneRot11 = new TGeoRotation; +// coneRot11->RotateZ(angle); +// coneRot11->RotateY(180); +// TGeoCombiTrans* conePosRot11 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-cone_offset[cone_size[iUnit]]-gkLadderGapZ/2., coneRot11); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 1, conePosRot11); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 1, conePosRot11); +// +// // downstream +// TGeoRotation* coneRot12 = new TGeoRotation; +// coneRot12->RotateZ(angle); +// TGeoCombiTrans* conePosRot12 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+cone_offset[cone_size[iUnit]]+gkLadderGapZ/2., coneRot12); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 2, conePosRot12); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 2, conePosRot12); +// +// myunit[iUnit]->GetShape()->ComputeBBox(); +// } + +// CheckVolume(myunit[iUnit]); +// CheckVolume(myunit[iUnit], infoFile); + if ((iUnit%2 == 0)||(iUnit == 15)) + { + CheckVolume(myunit[iUnit*2+0]); + CheckVolume(myunit[iUnit*2+0], infoFile); + CheckVolume(myunit[iUnit*2+1]); + CheckVolume(myunit[iUnit*2+1], infoFile); + } + infoFile << "Position z = " << statPos[iUnit] << endl; + } + // -------------------------------------------------------------------------- + + + // --------------- Create STS volume ------------------------------------ + cout << endl << endl; + cout << "===> Creating STS...." << endl; + +// // --- Determine size of STS box +// Double_t stsX = 0.; +// Double_t stsY = 0.; +// Double_t stsZ = 0.; +// Double_t stsBorder = 2*5.; // 5 cm space for carbon ladders on each side +// for (Int_t iStation = 1; iStation<=8; iStation++) { +// TString statName = Form("Station%02d", iStation); +// TGeoVolume* station = gGeoMan->GetVolume(statName); +// TGeoBBox* shape = (TGeoBBox*) station->GetShape(); +// stsX = TMath::Max(stsX, 2.* shape->GetDX() ); +// stsY = TMath::Max(stsY, 2.* shape->GetDY() ); +// cout << "Station " << iStation << ": Y " << stsY << endl; +// } +// // --- Some border around the stations +// stsX += stsBorder; +// stsY += stsBorder; +// stsZ = ( statPos[7] - statPos[0] ) + stsBorder; +// +// // --- Create box around the stations +// new TGeoBBox("stsBox", stsX/2., stsY/2., stsZ/2.); +// cout << "size of STS box: x " << stsX << " - y " << stsY << " - z " << stsZ << endl; +// +// // --- Create cone hosting the beam pipe +// // --- One straight section with constant radius followed by a cone +// Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +// Double_t z2 = gkPipeZ2; +// Double_t z3 = statPos[7] + 0.5 * stsBorder; // end of STS box +// Double_t r1 = BeamPipeRadius(z1); +// Double_t r2 = BeamPipeRadius(z2); +// Double_t r3 = BeamPipeRadius(z3); +// r1 += 0.01; // safety margin +// r2 += 0.01; // safety margin +// r3 += 0.01; // safety margin +// +// cout << endl; +// cout << z1 << " " << r1 << endl; +// cout << z2 << " " << r2 << endl; +// cout << z3 << " " << r3 << endl; +// +// cout << endl; +// cout << "station1 : " << BeamPipeRadius(statPos[0]) << endl; +// cout << "station2 : " << BeamPipeRadius(statPos[1]) << endl; +// cout << "station3 : " << BeamPipeRadius(statPos[2]) << endl; +// cout << "station4 : " << BeamPipeRadius(statPos[3]) << endl; +// cout << "station5 : " << BeamPipeRadius(statPos[4]) << endl; +// cout << "station6 : " << BeamPipeRadius(statPos[5]) << endl; +// cout << "station7 : " << BeamPipeRadius(statPos[6]) << endl; +// cout << "station8 : " << BeamPipeRadius(statPos[7]) << endl; +// +// // TGeoPcon* cutout = new TGeoPcon("stsCone", 0., 360., 3); // 2.*TMath::Pi(), 3); +// // cutout->DefineSection(0, z1, 0., r1); +// // cutout->DefineSection(1, z2, 0., r2); +// // cutout->DefineSection(2, z3, 0., r3); +// new TGeoTrd2("stsCone1", r1, r2, r1, r2, (z2-z1)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans1 = new TGeoTranslation("trans1", 0., 0., -(z3-z1)/2.+(z2-z1)/2.); +// trans1->RegisterYourself(); +// new TGeoTrd2("stsCone2", r2, r3, r2, r3, (z3-z2)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans2 = new TGeoTranslation("trans2", 0., 0., +(z3-z1)/2.-(z3-z2)/2.); +// trans2->RegisterYourself(); +// +////DE Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +////DE Double_t z2 = statPos[7] + 0.5 * stsBorder; // end of STS box +////DE Double_t slope = (gkPipeR2 - gkPipeR1) / (gkPipeZ2 - gkPipeZ1); +////DE Double_t r1 = gkPipeR1 + slope * (z1 - gkPipeZ1); // at start of STS +////DE Double_t r2 = gkPipeR1 + slope * (z2 - gkPipeZ1); // at end of STS +////DE r1 += 0.1; // safety margin +////DE r2 += 0.1; // safety margin +////DE // new TGeoCone("stsCone", stsZ/2., 0., r1, 0., r2); +////DE new TGeoTrd2("stsCone", r1, r2, r1, r2, stsZ/2.); + + + // // Create holding/cooling plates + // static std::vector< std::vector<Double_t> > plateSizes = { + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // }; + + // // 8-vertex cut-outs { minWidth, maxWidth, minHeight, maxHeight } + // static std::vector< std::vector<Double_t> > plateCutOuts = { + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 17.6, 47.6 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 49.0, 79.0 }, + // { 85.5,115.5, 51.5, 82.8 }, + // { 85.5,115.5, 59.0, 91.4 }, + // { 85.5,115.5, 68.0, 99.0 }, + // }; + + // for (Int_t iPlate = 0; iPlate < 9; iPlate++) { + // Int_t iUnit = iPlate * 2; + // TGeoBBox* outerPlate = new TGeoBBox(Form("outerPlate%02d",iPlate), + // plateSizes[iPlate][0], plateSizes[iPlate][1], plateSizes[iPlate][2]); + + // TGeoBBox* unitShapeR = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+0])->GetShape(); + // TGeoBBox* unitShapeL = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+1])->GetShape(); + + // Double_t maxDx = (unitShapeR->GetDX() + unitShapeL->GetDX()) / 2.; + // Double_t maxDy = TMath::Max(unitShapeR->GetDY(), unitShapeL->GetDY()); + // cout << maxDy << endl; + + // Double_t* cutOutX = new Double_t[8]; + // Double_t* cutOutY = new Double_t[8]; + + // cutOutX[0] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[0] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[1] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[1] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[2] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[2] = 1/2. * plateCutOuts[iPlate][2]; + // cutOutX[3] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[3] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[4] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[4] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[5] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[5] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[6] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[6] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[7] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[7] = 1/2. * plateCutOuts[iPlate][2]; + + // TGeoXtru* cutOutShape = new TGeoXtru(2); + // cutOutShape->SetName(Form("innerPlate%02d", iPlate)); + // cutOutShape->DefinePolygon(8, cutOutX, cutOutY); + // cutOutShape->DefineSection(0, -1*plateSizes[iPlate][2]-1e-7); + // cutOutShape->DefineSection(1, +1*plateSizes[iPlate][2]+1e-7); + + // TGeoShape* plateShape = new TGeoCompositeShape(Form("PlateShape%02d",iPlate), Form("outerPlate%02d-innerPlate%02d",iPlate,iPlate)); + // TGeoVolume* plate = new TGeoVolume(Form("Plate%02d", iPlate), plateShape, gGeoManager->GetMedium("aluminium")); + // plate->SetLineColor(kRed); + // plate->SetTransparency(65); + // plate->GetShape()->ComputeBBox(); + // } + + // --- Create STS volume + TString stsName = "sts_"; + stsName += geoTag; + +// TGeoShape* stsShape = new TGeoCompositeShape("stsShape", +// "stsBox-stsCone1:trans1-stsCone2:trans2"); +// TGeoVolume* sts = new TGeoVolume(stsName.Data(), stsShape, gStsMedium); + + Double_t stsBorder = 2 * 5.; + + TGeoVolume* sts = new TGeoVolumeAssembly(stsName.Data()); + + // --- Place stations in the STS + Double_t stsPosZ = 0.5 * ( statPos[15] + statPos[0] ); // todo units: update statPos[7] + // cout << "stsPosZ " << stsPosZ << " " << statPos[15] << " " << statPos[0] << "*****" << endl; + +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) { + for (Int_t iUnit = 0; iUnit < 18; iUnit++) { +// for (Int_t iUnit = 0; iUnit < 32; iUnit++) { + TGeoVolume* station = gGeoMan->GetVolume(unitName18[iUnit]); +// Double_t posZ = statPos[iUnit] - stsPosZ; + Double_t posZ = statPos18[iUnit] - stsPosZ; +// Double_t posZ = statPos[iUnit/2] - stsPosZ; + TGeoTranslation* trans = new TGeoTranslation(0., 0., posZ); + sts->AddNode(station, iUnit+1, trans); + sts->GetShape()->ComputeBBox(); + } + + // --- Import passive elements from GDML file + if (gkImportPassive) { + ImportPassive(sts, geoTag, infoFile); + } + + cout << endl; + CheckVolume(sts); + // -------------------------------------------------------------------------- + + + // --------------- Finish ----------------------------------------------- + TGeoTranslation* stsTrans = new TGeoTranslation(0., 0., stsPosZ); + top->AddNode(sts, 1, stsTrans); + top->GetShape()->ComputeBBox(); + cout << endl << endl; + + CheckVolume(top); + cout << endl << endl; + gGeoMan->CloseGeometry(); + gGeoMan->CheckOverlaps(0.0001); + gGeoMan->PrintOverlaps(); + gGeoMan->CheckOverlaps(0.0001, "s"); + gGeoMan->PrintOverlaps(); + gGeoMan->Test(); + + TFile* geoFile = new TFile(geoFileName, "RECREATE"); + top->Write(); + cout << endl; + cout << "Geometry " << top->GetName() << " written to " + << geoFileName << endl; + geoFile->Close(); + + TString geoFileName_ = "sts_"; + geoFileName_ = geoFileName_ + geoTag + "_geo.root"; + + geoFile = new TFile(geoFileName_, "RECREATE"); + gGeoMan->Write(); // use this is you want GeoManager format in the output + geoFile->Close(); + + TString geoFileName__ = "sts_"; + geoFileName_ = geoFileName__ + geoTag + "-geo.root"; + sts->Export(geoFileName_); + + geoFile = new TFile(geoFileName_, "UPDATE"); + stsTrans->Write(); + geoFile->Close(); + + // gGeoManager->FindVolumeFast("LadderType10_CarbonElement")->Draw("ogl"); + top->Draw("ogl"); + gGeoManager->SetVisLevel(8); + + infoFile.close(); + +} +// ============================================================================ +// ====== End of main function ===== +// ============================================================================ + + + + + +// **************************************************************************** +// ***** Definition of media, sensors, sectors and ladders ***** +// ***** ***** +// ***** Decoupled from main function for better readability ***** +// **************************************************************************** + + +/** =========================================================================== + ** Create media + ** + ** Currently created: air, active silicon, passive silion + ** + ** Not used for the time being + **/ +Int_t CreateMedia() { + + Int_t nMedia = 0; + Double_t density = 0.; + + // --- Material air + density = 1.205e-3; // [g/cm^3] + TGeoMixture* matAir = new TGeoMixture("sts_air", 3, density); + matAir->AddElement(14.0067, 7, 0.755); // Nitrogen + matAir->AddElement(15.999, 8, 0.231); // Oxygen + matAir->AddElement(39.948, 18, 0.014); // Argon + + // --- Material silicon + density = 2.33; // [g/cm^3] + TGeoElement* elSi = gGeoMan->GetElementTable()->GetElement(14); + TGeoMaterial* matSi = new TGeoMaterial("matSi", elSi, density); + + + // --- Air (passive) + TGeoMedium* medAir = new TGeoMedium("air", nMedia++, matAir); + medAir->SetParam(0, 0.); // is passive + medAir->SetParam(1, 1.); // is in magnetic field + medAir->SetParam(2, 20.); // max. field [kG] + medAir->SetParam(6, 0.001); // boundary crossing precision [cm] + + + // --- Active silicon for sensors + TGeoMedium* medSiAct = new TGeoMedium("silicon", + nMedia++, matSi); + medSiAct->SetParam(0, 1.); // is active + medSiAct->SetParam(1, 1.); // is in magnetic field + medSiAct->SetParam(2, 20.); // max. field [kG] + medSiAct->SetParam(6, 0.001); // boundary crossing precisison [cm] + + // --- Passive silicon for cables + TGeoMedium* medSiPas = new TGeoMedium("carbon", + nMedia++, matSi); + medSiPas->SetParam(0, 0.); // is passive + medSiPas->SetParam(1, 1.); // is in magnetic field + medSiPas->SetParam(2, 20.); // max. field [kG] + medSiPas->SetParam(6, 0.001); // boundary crossing precisison [cm] + + return nMedia; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sensors + ** + ** Sensors are created as volumes with box shape and active silicon as medium. + ** Four kinds of sensors: 3.2x2.2, 6.2x2.2, 6.2x4.2, 6.2x6.2 + **/ +Int_t CreateSensors() { + + Int_t nSensors = 0; + + Double_t xSize = 0.; + Double_t ySize = 0.; + Double_t zSize = gkSensorThickness; + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + + + // --- Sensor type 01: Small sensor (6.2 cm x 2.2 cm) + xSize = gkSensorSizeX; + ySize = 2.2; + TGeoBBox* shape_sensor01 = new TGeoBBox("sensor01", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor01", shape_sensor01, silicon); + nSensors++; + + + // --- Sensor type 02: Medium sensor (6.2 cm x 4.2 cm) + xSize = gkSensorSizeX; + ySize = 4.2; + TGeoBBox* shape_sensor02 = new TGeoBBox("sensor02", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor02", shape_sensor02, silicon); + nSensors++; + + + // --- Sensor type 03: Big sensor (6.2 cm x 6.2 cm) + xSize = gkSensorSizeX; + ySize = 6.2; + TGeoBBox* shape_sensor03 = new TGeoBBox("sensor03", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor03", shape_sensor03, silicon); + nSensors++; + + + // --- Sensor type 04: Big sensor (6.2 cm x 12.4 cm) + xSize = gkSensorSizeX; + ySize = 12.4; + TGeoBBox* shape_sensor04 = new TGeoBBox("sensor04", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor04", shape_sensor04, silicon); + nSensors++; + + + // below are extra small sensors, those are not available in the CAD model + + // --- Sensor Type 05: Half small sensor (4 cm x 2.5 cm) + xSize = 4.0; + ySize = 2.5; + TGeoBBox* shape_sensor05 = new TGeoBBox("sensor05", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor05", shape_sensor05, silicon); + nSensors++; + + + // --- Sensor type 06: Additional "in hole" sensor (3.1 cm x 4.2 cm) + xSize = 3.1; + ySize = 4.2; + TGeoBBox* shape_sensor06 = new TGeoBBox("sensor06", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor06", shape_sensor06, silicon); + nSensors++; + + + // --- Sensor type 07: Mini Medium sensor (1.5 cm x 4.2 cm) + xSize = 1.5; + ySize = 4.2; + TGeoBBox* shape_sensor07 = new TGeoBBox("sensor07", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor07", shape_sensor07, silicon); + nSensors++; + + + return nSensors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sectors + ** + ** A sector is either a single sensor or several chained sensors. + ** It is implemented as TGeoVolumeAssembly. + ** Currently available: + ** - single sensors of type 1 - 4 + ** - two chained sensors of type 4 + ** - three chained sensors of type 4 + **/ +Int_t CreateSectors() { + + Int_t nSectors = 0; + + TGeoVolume* sensor01 = gGeoMan->GetVolume("Sensor01"); + TGeoVolume* sensor02 = gGeoMan->GetVolume("Sensor02"); + TGeoVolume* sensor03 = gGeoMan->GetVolume("Sensor03"); + TGeoVolume* sensor04 = gGeoMan->GetVolume("Sensor04"); + TGeoVolume* sensor05 = gGeoMan->GetVolume("Sensor05"); + TGeoVolume* sensor06 = gGeoMan->GetVolume("Sensor06"); + TGeoVolume* sensor07 = gGeoMan->GetVolume("Sensor07"); + // TGeoBBox* box4 = (TGeoBBox*) sensor04->GetShape(); + + // --- Sector type 1: single sensor of type 1 + TGeoVolumeAssembly* sector01 = new TGeoVolumeAssembly("Sector01"); + sector01->AddNode(sensor01, 1); + sector01->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 2: single sensor of type 2 + TGeoVolumeAssembly* sector02 = new TGeoVolumeAssembly("Sector02"); + sector02->AddNode(sensor02, 1); + sector02->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 3: single sensor of type 3 + TGeoVolumeAssembly* sector03 = new TGeoVolumeAssembly("Sector03"); + sector03->AddNode(sensor03, 1); + sector03->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 4: single sensor of type 4 + TGeoVolumeAssembly* sector04 = new TGeoVolumeAssembly("Sector04"); + sector04->AddNode(sensor04, 1); + sector04->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 5: single sensor of type 5 + TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); + sector05->AddNode(sensor05, 1); + sector05->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 6: single sensor of type 6 + TGeoVolumeAssembly* sector06 = new TGeoVolumeAssembly("Sector06"); + sector06->AddNode(sensor06, 1); + sector06->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 7: single sensor of type 7 + TGeoVolumeAssembly* sector07 = new TGeoVolumeAssembly("Sector07"); + sector07->AddNode(sensor07, 1); + sector07->GetShape()->ComputeBBox(); + nSectors++; + +// // --- Sector type 5: two sensors of type 4 +// TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); +// Double_t shift5 = 0.5 * gkChainGapY + box4->GetDY(); +// TGeoTranslation* transD5 = +// new TGeoTranslation("td", 0., -1. * shift5, 0.); +// TGeoTranslation* transU5 = +// new TGeoTranslation("tu", 0., shift5, 0.); +// sector05->AddNode(sensor04, 1, transD5); +// sector05->AddNode(sensor04, 2, transU5); +// sector05->GetShape()->ComputeBBox(); +// nSectors++; + + return nSectors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create ladders + ** + ** Ladders are the building blocks of the stations. They contain + ** several modules placed one after the other along the z axis + ** such that the sectors are arranged vertically (with overlap). + ** + ** A ladder is constructed out of two half ladders, the second of which + ** is rotated in the x-y plane by 180 degrees and displaced + ** in z direction. + **/ +Int_t CreateLadders() { + + Int_t nLadders = 0; + + // --- Some variables + Int_t nSectors = 0; + Int_t sectorTypes[10]; + TGeoBBox* shape = NULL; + TString s0name; + TString hlname; + char align; + TGeoVolume* s0vol = NULL; + TGeoVolume* halfLadderU = NULL; + TGeoVolume* halfLadderD = NULL; + + // --- Ladders 01-23 + Int_t allSectorTypes[27][6] = { { 1, 2, 3, 3, 0, -1 }, // ladder 01 - 5 - last column defines alignment of small sensors + { 1, 2, 3, 3, 0, 0 }, // ladder 02 - 5 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, -1 }, // ladder 03 - 6 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 04 - 6 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, -1 }, // ladder 05 - 7 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 06 - 7 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 07 - last column defines alignment of small sensors + { 3, 4, 4, 4, 0, 0 }, // ladder 08 - last column defines alignment of small sensors + + { 1, 1, 2, 3, 3, 0 }, // ladder 09 - last column defines alignment of small sensors + { 1, 1, 2, 2, 3, 0 }, // ladder 10 - last column defines alignment of small sensors + { 2, 2, 0, 0, 0, 0 }, // ladder 11 - last column defines alignment of small sensors + { 2, 2, 2, 3, 4, 0 }, // ladder 12 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 13 - last column defines alignment of small sensors + + { 2, 3, 4, 0, 0, 0 }, // ladder 14 - last column defines alignment of small sensors + { 3, 3, 0, 0, 0, 0 }, // ladder 15 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 16 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 17 - last column defines alignment of small sensors + { 3, 4, 4, 0, 0, 0 }, // ladder 18 - last column defines alignment of small sensors + + { 4, 4, 0, 0, 0, 0 }, // ladder 19 - last column defines alignment of small sensors + { 1, 2, 4, 4, 4, 0 }, // ladder 20 - last column defines alignment of small sensors + { 4, 0, 0, 0, 0, 0 }, // ladder 21 - last column defines alignment of small sensors + { 2, 3, 4, 4, 4, 0 }, // ladder 22 - last column defines alignment of small sensors + { 2, 3, 3, 4, 4, 0 }, // ladder 23 - last column defines alignment of small sensors + + { 2, 3, 4, 4, 0, 0 }, // ladder 24 - copy of 17 with different total length + { 3, 4, 4, 0, 0, 0 }, // ladder 25 - copy of 18 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 26 - copy of 19 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 27 - copy of 19 with different total length + }; + +// Issue #405 +// Counting from the most upstream ladder, the gaps between sensors are as follows: +// 01 (most upstream): 41.3mm +// 02: 41.3mm +// 03: 42.0mm +// 04: 48.6mm +// 05: 60.8mm +// 06: 67.0mm +// 07: 79.2mm +// 08 (most downstream): 88.0mm + + Double_t gapXYZ[27][3] = { + { 0., 4.13, 0. }, // ladder 01 + { 0., 4.13, 0. }, // ladder 02 + { 0., 4.20, 0. }, // ladder 03 + { 0., 4.86, 0. }, // ladder 04 + { 0., 6.08, 0. }, // ladder 05 + { 0., 6.70, 0. }, // ladder 06 + { 0., 7.92, 0. }, // ladder 07 + { 0., 8.80, 0. }, // ladder 08 + { 0., -gkSectorOverlapY, 0. }, // ladder 09 + { 0., -gkSectorOverlapY, 0. }, // ladder 10 + { 0., -gkSectorOverlapY, 0. }, // ladder 11 + { 0., -gkSectorOverlapY, 0. }, // ladder 12 + { 0., -gkSectorOverlapY, 0. }, // ladder 13 + { 0., -gkSectorOverlapY, 0. }, // ladder 14 + { 0., -gkSectorOverlapY, 0. }, // ladder 15 + { 0., -gkSectorOverlapY, 0. }, // ladder 16 + { 0., -gkSectorOverlapY, 0. }, // ladder 17 + { 0., -gkSectorOverlapY, 0. }, // ladder 18 + { 0., -gkSectorOverlapY, 0. }, // ladder 19 + { 0., -gkSectorOverlapY, 0. }, // ladder 20 + { 0., -gkSectorOverlapY, 0. }, // ladder 21 + { 0., -gkSectorOverlapY, 0. }, // ladder 22 + { 0., -gkSectorOverlapY, 0. }, // ladder 23 + + { 0., -gkSectorOverlapY, 0. }, // ladder 24 - copy of 17 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 25 - copy of 18 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 26 - copy of 19 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 27 - copy of 19 with different total length + }; + + Double_t ladderLength[27] = { + 48.0, // ladder 01 + 48.0, // ladder 02 + 64.0, // ladder 03 + 64.0, // ladder 04 + 80.0, // ladder 05 + 80.0, // ladder 06 + 92.0, // ladder 07 + 96.0, // ladder 08 + 48.0, // ladder 09 + 48.0, // ladder 10 + 48.0, // ladder 11 + 64.0, // ladder 12 + 64.0, // ladder 13 + 64.0, // ladder 14 + 64.0, // ladder 15 + 80.0, // ladder 16 + 80.0, // ladder 17 + 80.0, // ladder 18 + 80.0, // ladder 19 + 92.0, // ladder 20 + 92.0, // ladder 21 + 96.0, // ladder 22 + 96.0, // ladder 23 + + 96.0, // ladder 24 - copy of 17 with different total length + 92.0, // ladder 25 - copy of 18 with different total length + 96.0, // ladder 26 - copy of 19 with different total length + 92.0, // ladder 27 - copy of 19 with different total length + }; +// ======================================================================== + + // calculate Z shift for ladders with and without gaps in the center + s0name = Form("Sector%02d", allSectorTypes[0][0]); + s0vol = gGeoMan->GetVolume(s0name); + shape = (TGeoBBox*) s0vol->GetShape(); + + for (Int_t iLadder = 0; iLadder < 27; iLadder++) + { + if (iLadder+1 <= 8) // for the 2 inner ladders of each station with gap for beampipe + gapXYZ[iLadder][2] = 0; // there is no offset in z for halfladders on ladders with a beampipe hole + else + gapXYZ[iLadder][2] = 2. * shape->GetDZ() + gkSectorGapZ; // set displacement in z for overlapping half ladders + } + +// ======================================================================== + + for (Int_t iLadder = 0; iLadder < 27; iLadder++) + { + cout << endl; + nSectors = 0; + for (Int_t i=0; i < 5; i++) + if (allSectorTypes[iLadder][i] != 0) + { + sectorTypes[nSectors] = allSectorTypes[iLadder][i]; // copy sectors for this ladder + cout << "DE iLadder " << iLadder+1 << " sectorTypes[" << nSectors << "] = " << allSectorTypes[iLadder][i] << ";" << endl; + nSectors++; // count how many sectors are in this ladder + } + + if (allSectorTypes[iLadder][5] == 0) + align = 'l'; + else + align = 'r'; + hlname = Form("HalfLadder%02du", iLadder+1); + // build upper half ladder + halfLadderU = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2.); // mirrored + + if (allSectorTypes[iLadder][5] == 0) + align = 'r'; + else + align = 'l'; + hlname = Form("HalfLadder%02dd", iLadder+1); + // build lower half ladder + halfLadderD = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2.); // mirrored + + // at this point half ladders are constructed + + // build all 4 possible ladders types for this sensor arrangement + ConstructLadder( iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19a + ConstructLadder( 100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19b + + ConstructLadder(1000+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19k + ConstructLadder(1100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19k + + nLadders++; + } + + return nLadders; +} +/** ======================================================================= **/ + + + +// **************************************************************************** +// ***** ***** +// ***** Generic functions for the construction of STS elements ***** +// ***** ***** +// ***** module: volume (made of a sector and a cable) ***** +// ***** haf ladder: assembly (made of modules) ***** +// ***** ladder: assembly (made of two half ladders) ***** +// ***** station: volume (made of ladders) ***** +// ***** ***** +// **************************************************************************** + + + +/** =========================================================================== + ** Construct a module + ** + ** A module is a sector plus the readout cable extending from the + ** top of the sector. The cable is made from passive silicon. + ** The cable has the same x size as the sector. + ** Its thickness is given by the global variable gkCableThickness. + ** The cable length is a parameter. + ** The sensor(s) of the sector is/are placed directly in the module; + ** the sector is just auxiliary for the proper placement. + ** + ** Arguments: + ** name volume name + ** sector pointer to sector volume + ** cableLength length of cable + **/ +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength) { + + // --- Check sector volume + if ( ! sector ) Fatal("CreateModule", "Sector volume not found!"); + + // --- Get size of sector + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + + // --- Get size of cable + Double_t cableX = sectorX; + Double_t cableY = cableLength; + Double_t cableZ = gkCableThickness; + + // --- Create module volume + Double_t moduleX = TMath::Max(sectorX, cableX); + Double_t moduleY = sectorY + cableLength; + + Double_t moduleZ = TMath::Max(sectorZ, cableZ); + + TGeoVolume* module = gGeoManager->MakeBox(name, gStsMedium, + moduleX/2., + moduleY/2., + moduleZ/2.); + + // --- Position of sector in module + // --- Sector is centred in x and z and aligned to the bottom + Double_t sectorXpos = 0.; + Double_t sectorYpos = 0.5 * (sectorY - moduleY); + Double_t sectorZpos = 0.; + + + // --- Get sensor(s) from sector + Int_t nSensors = sector->GetNdaughters(); + for (Int_t iSensor = 0; iSensor < nSensors; iSensor++) { + TGeoNode* sensor = sector->GetNode(iSensor); + + // --- Calculate position of sensor in module + const Double_t* xSensTrans = sensor->GetMatrix()->GetTranslation(); + Double_t sensorXpos = 0.; + Double_t sensorYpos = sectorYpos + xSensTrans[1]; + Double_t sensorZpos = 0.; + TGeoTranslation* sensTrans = new TGeoTranslation("sensTrans", + sensorXpos, + sensorYpos, + sensorZpos); + + // --- Add sensor volume to module + TGeoVolume* sensVol = sensor->GetVolume(); + module->AddNode(sensor->GetVolume(), iSensor+1, sensTrans); + module->GetShape()->ComputeBBox(); + } + + + // --- Create cable volume, if necessary, and place it in module + // --- Cable is centred in x and z and aligned to the top + if ( gkConstructCables && cableLength > 0.0001 ) { + TString cableName = TString(name) + "_cable"; + TGeoMedium* cableMedium = gGeoMan->GetMedium("STScable"); + if ( ! cableMedium ) Fatal("CreateModule", "Medium STScable not found!"); + TGeoVolume* cable = gGeoManager->MakeBox(cableName.Data(), + cableMedium, + cableX / 2., + cableY / 2., + cableZ / 2.); + // add color to cables + cable->SetLineColor(kOrange); + cable->SetTransparency(60); + Double_t cableXpos = 0.; + Double_t cableYpos = sectorY + 0.5 * cableY - 0.5 * moduleY; + Double_t cableZpos = 0.; + TGeoTranslation* cableTrans = new TGeoTranslation("cableTrans", + cableXpos, + cableYpos, + cableZpos); + module->AddNode(cable, 1, cableTrans); + module->GetShape()->ComputeBBox(); + } + + return module; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a half ladder + ** + ** A half ladder is a virtual volume (TGeoVolumeAssembly) consisting + ** of several modules arranged on top of each other. The modules + ** have a given overlap in y and a displacement in z to allow for the + ** overlap. + ** + ** The typ of sectors / modules to be placed must be specified: + ** 1 = sensor01 + ** 2 = sensor02 + ** 3 = sensor03 + ** 4 = sensor04 + ** 5 = 2 x sensor04 (chained) + ** 6 = 3 x sensor04 (chained) + ** The cable is added automatically from the top of each sensor to + ** the top of the half ladder. + ** The alignment can be left (l) or right (r), which matters in the + ** case of different x sizes of sensors (e.g. SensorType01). + ** + ** Arguments: + ** name volume name + ** nSectors number of sectors + ** sectorTypes array with sector types + ** align horizontal alignment of sectors + * ladderLength full length of the ladder towards FEE + * offsetY gap in the beam-pipe region + **/ +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY) { + + // --- Create half ladder volume assembly + TGeoVolumeAssembly* halfLadder = new TGeoVolumeAssembly(name); + + // --- Determine size of ladder + Double_t ladderX = 0.; + Double_t ladderY = 0.; + Double_t ladderZ = 0.; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + if ( ! sector ) + Fatal("ConstructHalfLadder", Form("Volume %s not found", sectorName.Data())); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + // --- Ladder x size equals largest sector x size + ladderX = TMath::Max(ladderX, 2. * box->GetDX()); + // --- Ladder y size is sum of sector ysizes + ladderY += 2. * box->GetDY(); + // --- Ladder z size is sum of sector z sizes + ladderZ += 2. * box->GetDZ(); + } + // --- Subtract overlaps in y + ladderY -= Double_t(nSectors-1) * gkSectorOverlapY; + // --- Add gaps in z direction + ladderZ += Double_t(nSectors-1) * gkSectorGapZ; + + ladderY = TMath::Max(ladderLength - offsetY, ladderY); + + // --- Create and place modules + Double_t yPosSect = -0.5 * ladderY; + Double_t zPosMod = -0.5 * ladderZ; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + yPosSect += 0.5 * sectorY; // Position of sector in ladder + Double_t cableLength = 0.5 * ladderY - yPosSect - 0.5 * sectorY; + TString moduleName = name + "_" + Form("Module%02d", + sectorTypes[iSector]); + TGeoVolume* module = ConstructModule(moduleName.Data(), + sector, cableLength); + + TGeoBBox* shapeMod = (TGeoBBox*) module->GetShape(); + Double_t moduleX = 2. * shapeMod->GetDX(); + Double_t moduleY = 2. * shapeMod->GetDY(); + Double_t moduleZ = 2. * shapeMod->GetDZ(); + Double_t xPosMod = 0.; + if ( align == 'l' ) + xPosMod = 0.5 * (moduleX - ladderX); // left aligned + else if ( align == 'r' ) + xPosMod = 0.5 * (ladderX - moduleX); // right aligned + else + xPosMod = 0.; // centred in x + Double_t yPosMod = 0.5 * (ladderY - moduleY); // top aligned + zPosMod += 0.5 * moduleZ; + TGeoTranslation* trans = new TGeoTranslation("t", xPosMod, + yPosMod, zPosMod); + halfLadder->AddNode(module, iSector+1, trans); + halfLadder->GetShape()->ComputeBBox(); + yPosSect += 0.5 * sectorY - gkSectorOverlapY; + zPosMod += 0.5 * moduleZ + gkSectorGapZ; + } + + CheckVolume(halfLadder); + cout << endl; + + return halfLadder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Add a carbon support to a ladder + ** + ** Arguments: + ** LadderIndex ladder number + ** ladder pointer to ladder + ** xu size of halfladder + ** ladderY height of ladder along y + ** ladderZ thickness of ladder along z + **/ +void AddCarbonLadder(Int_t LadderIndex, + TGeoVolume* ladder, + Double_t xu, + Double_t ladderY, + Double_t ladderZ) { + + // --- Some variables + TString name = Form("LadderType%04d", LadderIndex); // v19k + Int_t i; + Double_t j; + + Int_t YnumOfFrameBoxes = round(ladderY / gkFrameStep); + + // cout << "DEXZ: lad " << LadderIndex << " inum " << YnumOfFrameBoxes << endl; + + Double_t ladderDZ = (xu/2. + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2)/2.; + cout << "DEFR: frame Z size " << 2 * ladderDZ << " cm" << endl; + + TGeoBBox* fullFrameShp = new TGeoBBox (name+"_CarbonElement_shp", xu/2., gkFrameStep/2., ladderDZ); + TGeoVolume* fullFrameBoxVol = new TGeoVolume(name+"_CarbonElement", fullFrameShp, gStsMedium); + + ConstructFrameElement("CarbonElement", fullFrameBoxVol, xu/2.); + TGeoRotation* fullFrameRot = new TGeoRotation; + fullFrameRot->RotateY(180); + + Int_t inum = YnumOfFrameBoxes; + for (i=1; i<=inum; i++) + { + j=-(inum-1)/2.+(i-1); + // -(10-1)/2. +0 +10-1 -> -4.5 .. +4.5 -> -0.5, +0.5 (= 2) + // -(11-1)/2. +0 +11-1 -> -5.0 .. +5.0 -> -1, 0, 1 (= 3) + // cout << "DE: i " << i << " j " << j << endl; + + if (LadderIndex % 100 <= 3) // central ladders in stations 1 to 3 + { + if ((j>=-1) && (j<=1)) // keep the inner 2 (even) or 3 (odd) elements free for the cone + continue; + } + else if (LadderIndex % 100 <= 8) // central ladders in stations 4 to 8 + { + if ((j>=-2) && (j<=2)) // keep the inner 4 elements free for the cone + continue; + } + + cout << "DELZ: ladderDZ " << ladderDZ << " cm " << -ladderZ/2. - ladderDZ << " cm " << endl; + ladder->AddNode(fullFrameBoxVol, i, new TGeoCombiTrans(name+"_CarbonElement_posrot", 0., j*gkFrameStep, -(ladderZ/2.+ladderDZ), fullFrameRot)); + } + + ladder->GetShape()->ComputeBBox(); + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Construct a ladder out of two half ladders with vertical gap + ** + ** The second half ladder will be rotated by 180 degrees + ** in the x-y plane. The two half ladders will be put on top of each + ** other with a vertical gap. + ** + ** Arguments: + ** name volume name + ** halfLadderU pointer to upper half ladder + ** halfLadderD pointer to lower half ladder + ** gapY vertical gap + ** shiftZ relative displacement along the z axis + **/ + + TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ) { + + // --- Some variables + TGeoBBox* shape = NULL; + + // --- Dimensions of half ladders + shape = (TGeoBBox*) halfLadderU->GetShape(); + Double_t xu = 2. * shape->GetDX(); + Double_t yu = 2. * shape->GetDY(); + Double_t zu = 2. * shape->GetDZ(); + + shape = (TGeoBBox*) halfLadderD->GetShape(); + Double_t xd = 2. * shape->GetDX(); + Double_t yd = 2. * shape->GetDY(); + Double_t zd = 2. * shape->GetDZ(); + + + // --- Create ladder volume assembly + +// TString name = Form("LadderType%02d", LadderIndex); // v19a +// TString name = Form("LadderType%03d", LadderIndex); // v19b + TString name = Form("LadderType%04d", LadderIndex); // v19k + TGeoVolumeAssembly* ladder = new TGeoVolumeAssembly(name); + Double_t ladderX = TMath::Max(xu, xd); + Double_t ladderY = yu + yd + gapY; + Double_t ladderZ = TMath::Max(zu, zd + shiftZ); + + // --- Place half ladders + Double_t xPosU = 0.; // centred in x + Double_t yPosU = 0.5 * ( ladderY - yu ); // top aligned + Double_t zPosU = 0.5 * ( ladderZ - zu ); // front aligned // mount upper half ladder last + if (LadderIndex >= 1000) zPosU = -zPosU; // back aligned // mount upper half ladder first + + TGeoTranslation* tu = new TGeoTranslation("tu", xPosU, yPosU, zPosU); + ladder->AddNode(halfLadderU, 1, tu); + + Double_t xPosD = 0.; // centred in x + Double_t yPosD = 0.5 * ( yd - ladderY ); // bottom aligned + Double_t zPosD = 0.5 * ( zd - ladderZ ); // back aligned // mount lower half ladder first + if (LadderIndex >= 1000) zPosD = -zPosD; // front aligned // mount lower half ladder last + + TGeoRotation* rd = new TGeoRotation(); + rd->RotateZ(180.); + TGeoCombiTrans* cd = new TGeoCombiTrans(xPosD, yPosD, zPosD, rd); + ladder->AddNode(halfLadderD, 2, cd); + + ladder->GetShape()->ComputeBBox(); + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD0ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + cout << "DDDD ladder" << LadderIndex << endl; + cout << "DDDD1ladder" << LadderIndex << " ladderX " << ladderX << " ladderY " << ladderY << " ladderZ " << ladderZ << endl; + + // ---------------- Create and place frame boxes ------------------------ + + if (gkConstructFrames) + AddCarbonLadder(LadderIndex, ladder, ladderX, ladderY, ladderZ); + + // -------------------------------------------------------------------------- + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD2ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + return ladder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a unit + ** + ** The unit volume is the minimal box comprising all ladders + ** minus a tube accomodating the beam pipe. + ** + ** The ladders are arranged horizontally from left to right with + ** a given overlap in x. + ** Every second ladder is slightly displaced upstream from the centre + ** z plane and facing downstream, the others are slightly displaced + ** downstream and facing upstream (rotated around the y axis). + ** + ** Arguments: + ** name volume name + ** nLadders number of ladders + ** ladderTypes array of ladder types + **/ + + TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation) { + + Bool_t isFirstPartOfHalfUnit = kFALSE; + + // TString name = Form("Unit%02d", iUnit); // 0,1,2,3,4,5,6,7 - Unit00 missing in output + // TString name = Form("Unit%02d", iUnit+1); // 1,2,3,4,5,6,7,8 + + TGeoVolume* unit = gGeoMan->GetVolume(unitName[iUnit]); + if ( ! unit ) // if it does not yet exist, create a new one + { + unit = new TGeoVolumeAssembly(unitName[iUnit]); + isFirstPartOfHalfUnit = kTRUE; + } + + // --- Some local variables + TGeoBBox* ladderShape = NULL; + TGeoVolume* ladder = NULL; + TString ladderName; + Double_t subtractedVal; + + // --- Determine size of unit from ladders + Double_t statX = 0.; + // Double_t statY = 0.; + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { +// Int_t ladderType = ladderTypes[iLadder]%100; // v19a +// Int_t ladderType = ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100; // v19b + Int_t ladderType = ladderTypes[iLadder]; // v19k + +// if (iSide == 0) cout << "DWER " << ladderTypes[iLadder] << " " << ladderType << endl; + + if (ladderType > 0) + { +// ladderName = Form("LadderType%02d", ladderType); // v19a +// ladderName = Form("LadderType%03d", ladderType); // v19b + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + if ( ! ladder ) Fatal("ConstructUnit", + Form("Volume %s not found", ladderName.Data())); + ladderShape = (TGeoBBox*) ladder->GetShape(); + statX += 2. * ladderShape->GetDX(); + // statY = TMath::Max(statY, 2. * ladderShape->GetDY()); + } + else + statX += gkSensorSizeX; // empty ladder in unit + } + statX -= Double_t(nLadders-1) * gkLadderOverlapX; + +// if (iSide == 0) cout << "DWER -" << endl; + + // --- Place ladders in unit + cout << "xPos0: " << statX << endl; + Double_t xPos = -0.5 * statX; + cout << "xPos1: " << xPos << endl; + Double_t yPos = 0.; + Double_t zPos = 0.; + + Double_t maxdz = 0.; + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { // find maximum dz in this unit +// Int_t ladderType = ladderTypes[iLadder]%100; // v19a +// Int_t ladderType = ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100; // v19b + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { +// ladderName = Form("LadderType%02d", ladderType); // v19a +// ladderName = Form("LadderType%03d", ladderType); // v19b + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + if (maxdz < ladderShape->GetDZ()) + maxdz = ladderShape->GetDZ(); + } + } + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { +// Int_t ladderType = ladderTypes[iLadder]%100; // v19a +// Int_t ladderType = ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100; // v19b + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { +// ladderName = Form("LadderType%02d", ladderType); // v19a +// ladderName = Form("LadderType%03d", ladderType); // v19b + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + xPos += ladderShape->GetDX(); + cout << "xPos2: " << xPos << endl; + yPos = 0.; // vertically centred + TGeoRotation* rot = new TGeoRotation(); + + if (gkConstructFrames) + subtractedVal = ladderShape->GetDX() + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2; + else + subtractedVal = 0.; + + zPos = 0.5 * gkLadderGapZ + (2*maxdz-ladderShape->GetDZ()-subtractedVal/2.); // z-aligned ladders + +// v19a cout << "DE ladder" << ladderTypes[iLadder]%100 +// v19b cout << "DE ladder" << ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100 +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " dx: " << ladderShape->GetDX() + << " dy: " << ladderShape->GetDY() + << " dz: " << ladderShape->GetDZ() + << " max dz: " << maxdz << endl; + +// v19a cout << "DE ladder" << ladderTypes[iLadder]%100 +// v19b cout << "DE ladder" << ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100 +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " fra: " << gkFrameThickness/2. + << " sub: " << subtractedVal + << " zpo: " << zPos << endl << endl; + +// v19a if (ladderTypes[iLadder]/100 == 1) // flip some of the ladders to reproduce the CAD layout + if (ladderTypes[iLadder]/1000 == 1) // flip some of the ladders to reproduce the CAD layout + rot->RotateY(180.); + else + zPos = -zPos; + + if (!isFirstPartOfHalfUnit) + // zPos += 10; + zPos += 10.5; // v19d +// zPos += 11.0; // v19e + + TGeoCombiTrans* trans = new TGeoCombiTrans(xPos, yPos, zPos, rot); +// start +// cout << "DEEE** iLadder " << iLadder << " " << nLadders/2 << " " << nLadders << endl; + + if (iSide == 0) + { + if (iLadder < nLadders/2) // right side - only half unit -x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + else + { + if (iLadder >= nLadders/2) // left side - only half unit +x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + unit->GetShape()->ComputeBBox(); +// stop + xPos += ladderShape->GetDX() - gkLadderOverlapX; + cout << "xPos3: " << xPos << endl; + } + else + xPos += gkSensorSizeX - gkLadderOverlapX; + } + + return unit; + } +/** ======================================================================= **/ + + +/** =========================================================================== + ** Import and add the passive materials to the STS volume + **/ +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile) +{ + TString passiveName = TString("sts_passive_") + geoTag; + TString basePath = gSystem->Getenv("VMCWORKDIR"); + TString relPath = "/geometry/sts/passive/" + passiveName + ".gdml"; + TString passiveFileName = basePath + relPath; + infoFile << std::endl << std::endl; + infoFile << "Importing STS passive materials from GDML file '" << relPath << "'." << std::endl; + + TGDMLParse parser; + TGeoVolume* gdmlVolume = parser.GDMLReadFile(passiveFileName); + PostProcessGdml(gdmlVolume); + gdmlVolume->SetName(passiveName); + + TGeoTranslation* passiveTrans = new TGeoTranslation(0., 0., 4.68); + infoFile << "Passive assembly is translated for Z=4.68 cm downstream with respect to parent volume" << std::endl << std::endl; + + gdmlVolume->GetShape()->ComputeBBox(); + CheckVolume(gdmlVolume, infoFile); + + infoFile << std::endl; + for (Int_t iNode = 0; iNode < gdmlVolume->GetNdaughters(); iNode++) { + CheckVolume(gdmlVolume->GetNode(iNode)->GetVolume(), infoFile, kFALSE); + } + + stsVolume->AddNode(gdmlVolume, stsVolume->GetNdaughters(), passiveTrans, ""); +} + +/** =========================================================================== + ** Assign visual properties to the imported gdml volumes + **/ +void PostProcessGdml(TGeoVolume* gdmlVolume) +{ + const UInt_t kPOBColor = kRed-6; + const UInt_t kPOBTransparency = 0;// 5; + + const UInt_t kFEBColor = kOrange-6; + const UInt_t kFEBTransparency = 0;// 5; + + const UInt_t kUnitColor = kCyan-10; + const UInt_t kUnitTransparency = 0;// 5; + + const UInt_t kCfColor = kGray+3; + const UInt_t kCfTransparency = 0;// 10; + + // name <Color, Transparency> + std::map<std::string, std::tuple<UInt_t,UInt_t> > props { + { "passive_POB", std::tuple<UInt_t,UInt_t> {kPOBColor, kPOBTransparency} }, + { "passive_FEB", std::tuple<UInt_t,UInt_t> {kFEBColor, kFEBTransparency} }, + { "passive_unit", std::tuple<UInt_t,UInt_t> {kUnitColor, kUnitTransparency} }, + { "passive_Box_Wall", std::tuple<UInt_t,UInt_t> {kCfColor, kCfTransparency} }, + { "passive_Box_Wall_Front_CF2", std::tuple<UInt_t,UInt_t> {kCfColor-3, kCfTransparency} }, + }; + + // Match volume name and apply visual properties + const TObjArray* volumes = gGeoManager->GetListOfVolumes(); + for (auto& entry : props) { + TIter next(volumes); + TGeoVolume *vol = nullptr; + while ((vol=(TGeoVolume*)next())) { + if (TString(vol->GetName()).Contains(entry.first.c_str())) { + vol->SetLineColor(std::get<0>(entry.second)); + vol->SetTransparency(std::get<1>(entry.second)); + } + } + } +} + +/** =========================================================================== + ** Volume information for debugging + **/ +void CheckVolume(TGeoVolume* volume) { + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + cout << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) cout << ", assembly"; + else { + if ( volume->GetMedium() ) + cout << ", medium " << volume->GetMedium()->GetName(); + else cout << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + cout << endl; + if ( volume->GetNdaughters() ) { + cout << "Daughters: " << endl; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) { + TGeoNode* node = volume->GetNode(iNode); + TGeoBBox* shape = (TGeoBBox*) node->GetVolume()->GetShape(); + cout << setw(15) << node->GetName() << ", size " + << fixed << setprecision(3) + << setw(6) << 2. * shape->GetDX() << " x " + << setw(6) << 2. * shape->GetDY() << " x " + << setw(6) << 2. * shape->GetDZ() << ", position ( "; + TGeoMatrix* matrix = node->GetMatrix(); + const Double_t* pos = matrix->GetTranslation(); + cout << setfill(' '); + cout << fixed << setw(8) << pos[0] << ", " + << setw(8) << pos[1] << ", " + << setw(8) << pos[2] << " )" << endl; + } + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Volume information for output to file + **/ +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren) { + if ( ! file ) return; + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + file << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) file << ", assembly"; + else { + if ( volume->GetMedium() ) + file << ", medium " << volume->GetMedium()->GetName(); + else file << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + file << endl; + if ( volume->GetNdaughters() && listChildren) { + file << "Contains: "; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) + file << volume->GetNode(iNode)->GetVolume()->GetName() << " "; + file << endl; + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Calculate beam pipe outer radius for a given z + **/ +Double_t BeamPipeRadius(Double_t z) { + if ( z < gkPipeZ2 ) return gkPipeR1; + Double_t slope = (gkPipeR3 - gkPipeR2 ) / (gkPipeZ3 - gkPipeZ2); + return gkPipeR2 + slope * (z - gkPipeZ2); +} +/** ======================================================================= **/ + + + +/** ======================================================================= **/ +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + TGeoBBox* frameVertPillarShp; + + Double_t t = gkFrameThickness/2.; + + // --- Main vertical pillars +// TGeoBBox* frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, gkFrameStep/2., t); // square crossection, along y +// TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); +// frameVertPillarVol->SetLineColor(kGreen); +// frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoTranslation(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2.)); +// frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoTranslation(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkCylindricalFrames) + // TGeoBBox* frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", 0, t, gkFrameStep/2.); // circle crossection, along z + frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", gkCylinderDiaInner/2., gkCylinderDiaOuter/2., gkFrameStep/2.); // circle crossection, along z + else + frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, t, gkFrameStep/2.); // square crossection, along z + TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); + frameVertPillarVol->SetLineColor(kGreen); + + TGeoRotation* xRot90 = new TGeoRotation; + xRot90->RotateX(90.); + frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoCombiTrans(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoCombiTrans(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + + // TGeoRotation* vertRot = new TGeoRotation(name + "_vertpillar_rot_1", 90., 45., -90.); + TGeoRotation* vertRot = new TGeoRotation; + vertRot->RotateX(90.); + vertRot->RotateY(45.); + frameBoxVol->AddNode(frameVertPillarVol, 3, new TGeoCombiTrans(name + "_vertpillar_pos_3", 0., 0., (x-sqrt(2.)*t)/2., vertRot)); + + // --- Small horizontal pillar + // TGeoBBox* frameHorPillarShp = new TGeoBBox(name + "_horpillar_shape", x-2.*t, gkThinFrameThickness/2., gkThinFrameThickness/2.); + // TGeoVolume* frameHorPillarVol = new TGeoVolume(name + "_horpillar", frameHorPillarShp, framesMaterial); + // frameHorPillarVol->SetLineColor(kCyan); + // frameBoxVol->AddNode(frameHorPillarVol, 1, new TGeoTranslation(name + "_horpillar_pos_1", 0., -gkFrameStep/2.+gkThinFrameThickness/2., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkConstructSmallFrames) { + + // --- Small sloping pillars + TGeoPara* frameSlopePillarShp = new TGeoPara(name + "_slopepillar_shape", + (x-2.*t)/TMath::Cos(31.4/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., 31.4, 0., 90.); + TGeoVolume* frameSlopePillarVol = new TGeoVolume(name + "_slopepillar", frameSlopePillarShp, framesMaterial); + frameSlopePillarVol->SetLineColor(kCyan); + TGeoRotation* slopeRot = new TGeoRotation(name + "_slopepillar_rot_1", 0., 0., 31.4); + TGeoRotation* slopeRot2 = new TGeoRotation(name + "_slopepillar_rot_2", 0., 0., -31.4); + TGeoCombiTrans* slopeTrRot = new TGeoCombiTrans(name + "_slopepillar_posrot_1", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot); + TGeoCombiTrans* slopeTrRot2 = new TGeoCombiTrans(name + "_slopepillar_posrot_2", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot2); + + frameBoxVol->AddNode(frameSlopePillarVol, 1, slopeTrRot); + frameBoxVol->AddNodeOverlap(frameSlopePillarVol, 2, slopeTrRot2); + + + Double_t angl = 23.; + // --- Small sub pillar + TGeoPara* frameSubPillarShp = new TGeoPara(name + "_subpillar_shape", + (sqrt(2)*(x/2.-t)-t/2.)/TMath::Cos(angl/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., angl, 0., 90.); + TGeoVolume* frameSubPillarVol = new TGeoVolume(name + "_subpillar", frameSubPillarShp, framesMaterial); + frameSubPillarVol->SetLineColor(kMagenta); + + Double_t posZ = t * (1. - 3. / ( 2.*sqrt(2.) )); + + // one side of X direction + TGeoRotation* subRot1 = new TGeoRotation(name + "_subpillar_rot_1", 90., 45., -90.+angl); + TGeoCombiTrans* subTrRot1 = new TGeoCombiTrans(name + "_subpillar_posrot_1", -(-x/2.+t-t/(2.*sqrt(2.))), 1., posZ, subRot1); + + TGeoRotation* subRot2 = new TGeoRotation(name + "_subpillar_rot_2", 90., -90.-45., -90.+angl); + TGeoCombiTrans* subTrRot2 = new TGeoCombiTrans(name + "_subpillar_posrot_2", -(-x/2.+t-t/(2.*sqrt(2.))), -1., posZ, subRot2); + + // other side of X direction + TGeoRotation* subRot3 = new TGeoRotation(name + "_subpillar_rot_3", 90., 90.+45., -90.+angl); + TGeoCombiTrans* subTrRot3 = new TGeoCombiTrans(name + "_subpillar_posrot_3", -x/2.+t-t/(2.*sqrt(2.)), 1., posZ, subRot3); + + TGeoRotation* subRot4 = new TGeoRotation(name + "_subpillar_rot_4", 90., -45., -90.+angl); + TGeoCombiTrans* subTrRot4 = new TGeoCombiTrans(name + "_subpillar_posrot_4", -x/2.+t-t/(2.*sqrt(2.)), -1., posZ, subRot4); + + frameBoxVol->AddNode(frameSubPillarVol, 1, subTrRot1); + frameBoxVol->AddNode(frameSubPillarVol, 2, subTrRot2); + frameBoxVol->AddNode(frameSubPillarVol, 3, subTrRot3); + frameBoxVol->AddNode(frameSubPillarVol, 4, subTrRot4); + // frameBoxVol->GetShape()->ComputeBBox(); + } + + return frameBoxVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructSmallCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 6., 7.6, 6., 6.04, 0., 180.); +// TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + Double_t radius = 3.0; + Double_t thickness = 0.04; // 0.4 mm +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 3., 3.2, 3., 3.2, 0., 180.); + TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, radius, radius+thickness, radius, radius+thickness, 0., 180.); + TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + TGeoCombiTrans* M = new TGeoCombiTrans ("M"); + M->RotateX (45.); + M->SetDy (-5.575); + M->SetDz (6.935); + M->RegisterYourself(); + + TGeoShape* coneShp = new TGeoCompositeShape ("Cone_shp", "A-B:M"); + TGeoVolume* coneVol = new TGeoVolume ("Cone", coneShp, framesMaterial); + coneVol->SetLineColor(kGreen); +// coneVol->RegisterYourself(); + +// // --- Inner cone +// Double_t thickness = 0.02; +// Double_t thickness2 = 0.022; +// // TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); +// TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 3.+thickness, 4.6-thickness2, 2.99+thickness, 3.05-thickness2, 0., 180.); +// +// TGeoCombiTrans* M2 = new TGeoCombiTrans ("M2"); +// M2->RotateX (45.); +// M2->SetDy (-5.575+thickness*sqrt(2.)); +// M2->SetDz (6.935); +// M2->RegisterYourself(); +// +// TGeoShape* coneShp2 = new TGeoCompositeShape ("Cone2_shp", "A2-B:M2"); +// TGeoVolume* coneVol2 = new TGeoVolume ("Cone2", coneShp2, gStsMedium); +// coneVol2->SetLineColor(kGreen); +//// coneVol2->RegisterYourself(); +// +// coneVol->AddNode(coneVol2, 1); + + return coneVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructBigCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone + TGeoConeSeg* bA = new TGeoConeSeg ("bA", coneDz, 6., 7.6, 6., 6.04, 0., 180.); + TGeoBBox* bB = new TGeoBBox ("bB", 8., 6., 10.); + + TGeoCombiTrans* bM = new TGeoCombiTrans ("bM"); + bM->RotateX (45.); + bM->SetDy (-5.575); + bM->SetDz (6.935); + bM->RegisterYourself(); + + TGeoShape* coneBigShp = new TGeoCompositeShape ("ConeBig_shp", "bA-bB:bM"); + TGeoVolume* coneBigVol = new TGeoVolume ("ConeBig", coneBigShp, framesMaterial); + coneBigVol->SetLineColor(kGreen); +// coneBigVol->RegisterYourself(); + + // --- Inner cone + Double_t thickness = 0.02; + Double_t thickness2 = 0.022; + TGeoConeSeg* bA2 = new TGeoConeSeg ("bA2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); + + TGeoCombiTrans* bM2 = new TGeoCombiTrans ("bM2"); + bM2->RotateX (45.); + bM2->SetDy (-5.575+thickness*sqrt(2.)); + bM2->SetDz (6.935); + bM2->RegisterYourself(); + + TGeoShape* coneBigShp2 = new TGeoCompositeShape ("ConeBig2_shp", "bA2-bB:bM2"); + TGeoVolume* coneBigVol2 = new TGeoVolume ("ConeBig2", coneBigShp2, gStsMedium); + coneBigVol2->SetLineColor(kGreen); +// coneBigVol2->RegisterYourself(); + + coneBigVol->AddNode(coneBigVol2, 1); + + return coneBigVol; +} + +/** ======================================================================= **/ diff --git a/macro/sts/geometry/create_stsgeo_v19n.C b/macro/sts/geometry/create_stsgeo_v19n.C new file mode 100644 index 0000000000000000000000000000000000000000..776e9b544797c5db4e17cde71d1d8e704e29b1b7 --- /dev/null +++ b/macro/sts/geometry/create_stsgeo_v19n.C @@ -0,0 +1,2374 @@ +/****************************************************************************** + ** Creation of STS geometry in ROOT format (TGeo). + ** + ** @file create_stsgeo_v19n.C + ** @author Volker Friese <v.friese@gsi.de> + ** @since 15 June 2012 + ** @date 09.05.2014 + ** @author Tomas Balog <T.Balog@gsi.de> + ** + ** v19n: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.20 cm (bug fix of v19m) + ** v19m: based on v19k - parameters : delta Z prime = 0.55 cm - delta Z pitch = 0.20 cm (bug) + ** v19l: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.15 cm + ** v19k: ladders on upstream side of units get upper half ladders installed first, + ** ladders on downstream side of units get lower half ladders installed first, + ** this saves 1.5 mm space in z per station, 12 mm in total (LadderType went from 3 to 4 digits) + ** parameters : delta Z prime = 1.00 cm - delta Z pitch = 0.15 cm + ** v19j: use overlap and distance parameters from CAD model + ** v19h: put STS stations from v19d at z-positions = 260; 365; 470; 575; 680; 785; 890; 995 mm + ** v19g: place a box with services around v19e + ** v19f: place a box with services around v19d + ** v19e: increase spacing between stations by +10 mm from 100 mm + ** v19d: increase spacing between stations by + 5 mm from 100 mm + ** v19c: drop station 8 and increase spacing between remaining 7 stations from 10 cm to 12 c + ** v19b: introduce FEB orientation in ladder numbering (LadderType went from 2 to 3 digits) + ** v19a: import passive materials from gdml file + ** extend CF ladder structures and cables towards FEE plane + ** change CF ladder frame shape + ** v18d: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu (based on v18b) + ** v18c: fixed cut-out windows in cooling plates, improve the box shape/materials + ** v18b: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu + ** v18a: adds 9 cooling/holding plates and a box around the setup + ** v16g: v16g is the new standard geometry from November 2017 + ** v16g: switch from stations to units - left / right ("Unit01L", "Unit01R") + ** v16f: switch from stations to units + ** - split in upstream / downstream and left / right parts + ** - named Unit0xUR, Unit0xUL, Unit0xDR, Unit0xDL + ** v16e: switch from stations to units - upstream / downstream ("Unit01U", "Unit01D") + ** v16d: skip keeping volumes of sts and stations + ** v16c: like v16b, but senors of ladders beampipe next to beampipe + ** shifted closer to the pipe, like in the CAD model + ** v16b: like v16a, but yellow sensors removed + ** v16a: derived from v15c (no cones), but with sensor types renamed: + ** 2 -> 1, 3 -> 2, 4 -> 3, 5 -> 4, 1 -> 5 + ** + ** v15c: as v15b without cones + ** v15b: introduce modified carbon ladders from v13z + ** v15a: with flipped ladder orientation for stations 0,2,4,6 to match CAD design + ** + ** TODO: + ** + ** DONE: + ** v15b - use carbon macaroni as ladder support + ** v15b - introduce a small gap between lowest sensor and carbon ladder + ** v15b - build small cones for the first 2 stations + ** v15b - within a station the ladders of adjacent units should not touch eachother - set gkLadderGapZ to 10 mm + ** v15b - for all ladders set an even number of ladder elements + ** v15b - z offset of cones to ladders should not be 0.3 by default, but 0.26 + ** v15b - within a station the ladders should be aligned in z, defined either by the unit or the ladder with most sensors + ** v15b - get rid of cone overlap in stations 7 and 8 - done by adapting rHole size + ** + ** The geometry hierarachy is: + ** + ** 1. Sensors (see function CreateSensors) + ** The sensors are the active volumes and the lowest geometry level. + ** They are built as TGeoVolumes, shape box, material silicon. + ** x size is determined by strip pitch 58 mu and 1024 strips + ** plus guard ring of 1.3 mm at each border -> 6.1992 cm. + ** Sensor type 1 is half of that (3.0792 cm). + ** y size is determined by strip length (2.2 / 4.2 / 6.3 cm) plus + ** guard ring of 1.3 mm at top and bottom -> 2.46 / 4.46 / 6.46 cm. + ** z size is a parameter, to be set by gkSensorThickness. + ** + ** 2. Sectors (see function CreateSectors) + ** Sectors consist of several chained sensors. These are arranged + ** vertically on top of each other with a gap to be set by + ** gkChainGapY. Sectors are constructed as TGeoVolumeAssembly. + ** The sectors are auxiliary volumes used for proper placement + ** of the sensor(s) in the module. They do not show up in the + ** final geometry. + ** + ** 3. Modules (see function ConstructModule) + ** A module is a readout unit, consisting of one sensor or + ** a chain of sensors (see sector) and a cable. + ** The cable extends from the top of the sector vertically to the + ** top of the halfladder the module is placed in. The cable and module + ** volume thus depend on the vertical position of the sector in + ** the halfladder. The cables consist of silicon with a thickness to be + ** set by gkCableThickness. + ** Modules are constructed as TGeoVolume, shape box, medium gStsMedium. + ** The module construction can be switched off (gkConstructCables) + ** to reproduce older geometries. + ** + ** 4. Halfladders (see function ConstructHalfLadder) + ** A halfladder is a vertical assembly of several modules. The modules + ** are placed vertically such that their sectors overlap by + ** gkSectorOverlapY. They are displaced in z direction to allow for the + ** overlap in y by gkSectorGapZ. + ** The horizontal placement of modules in the halfladder can be choosen + ** to left aligned or right aligned, which only matters if sensors of + ** different x size are involved. + ** Halfladders are constructed as TGeoVolumeAssembly. + ** + ** 5. Ladders (see function CreateLadders and ConstructLadder) + ** A ladder is a vertical assembly of two halfladders, and is such the + ** vertical building block of a station. The second (bottom) half ladder + ** is rotated upside down. The vertical arrangement is such that the + ** inner sectors of the two halfladders have the overlap gkSectorOverlapY + ** (function CreateLadder) or that there is a vertical gap for the beam + ** hole (function CreateLadderWithGap). + ** Ladders are constructed as TGeoVolumeAssembly. + ** + ** 6. Stations (see function ConstructStation) + ** A station represents one layer of the STS geometry: one measurement + ** at (approximately) a given z position. It consist of several ladders + ** arranged horizontally to cover the acceptance. + ** The ladders are arranged such that there is a horizontal overlap + ** between neighbouring ladders (gkLadderOverLapX) and a vertical gap + ** to allow for this overlap (gkLadderGapZ). Each second ladder is + ** rotated around its y axis to face away from or into the beam. + ** Stations are constructed as TGeoVolumes, shape box minus tube (for + ** the beam hole), material gStsMedium. + ** + ** 7. STS + ** The STS is a volume hosting the entire detectors system. It consists + ** of several stations located at different z positions. + ** The STS is constructed as TGeoVolume, shape box minus cone (for the + ** beam pipe), material gStsMedium. The size of the box is computed to + ** enclose all stations. + *****************************************************************************/ + + +// Remark: With the proper steering variables, this should exactly reproduce +// the geometry version v11b of A. Kotynia's described in the ASCII format. +// The only exception is a minimal difference in the z position of the +// sectors/sensors. This is because of ladder types 2 and 4 containing the half +// sensors around the beam hole (stations 1,2 and 3). In v11b, the two ladders +// covering the beam hole cannot be transformed into each other by rotations, +// but only by a reflection. This means they are constructionally different. +// To avoid introducing another two ladder types, the difference in z position +// was accepted. + + +// Differences to v12: +// gkChainGap reduced from 1 mm to 0 +// gkCableThickness increased from 100 mum to 200 mum (2 cables per module) +// gkSectorOverlapY reduced from 3 mm to 2.4 mm +// New sensor types 05 and 06 +// New sector types 07 and 08 +// Re-definiton of ladders (17 types instead of 8) +// Re-definiton of station from new ladders + + +#include <iomanip> +#include <iostream> +#include "TGeoManager.h" + +#include "TGeoTube.h" +#include "TGeoPara.h" +#include "TGeoCone.h" +#include "TGeoTrd2.h" +#include "TGeoCompositeShape.h" +#include "TGeoXtru.h" +#include "TGeoPhysicalNode.h" + +// forward declarations +Int_t CreateSensors(); +Int_t CreateSectors(); +Int_t CreateLadders(); +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength); +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY); +TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ); +TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation); +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile); +void PostProcessGdml(TGeoVolume* gdmlTop); +void CheckVolume(TGeoVolume* volume); +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren = kTRUE); +Double_t BeamPipeRadius(Double_t z); +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x); +TGeoVolume* ConstructSmallCone(Double_t coneDz); +TGeoVolume* ConstructBigCone(Double_t coneDz); + +// ------------- Version highlight ----------------------------------- + +const std::string gVersionHighlight = R"( +Summary: + This version adds passive materials imported from GDML model to the STS geometry: + * Taken from and largely correspond to mechanical CAD drawings of the detector + * Thermal insulation box: + - made out of carbon sandwitch panel (2mm carbon fiber sheet + layer of carbon foam + 2mm carbon fiber sheet) + - front window of complex shape with interface to MVD / target chamber + - back window with large aperture (2000 x 1200 mm) square cut into carbon foam + * Structural units: + - made of 2 complex shape aluminum C-Frames, 15mm thick + - placed at 25, 35, ... ,105 cm absolute Z + - contain front-end and power distribution boxes with equivalent X_0 values + + Scripted geometry tweaks: + * Ladders and cables are extended towards the read-out planes having same lengths in respective rows + * Adjusted form and shape of carbon ladder structures from L-type to X-type + * Reduced verbosity of this file + + Sensor arrangement is the same as in version v16g + + !! Important for this version is the discrepancy from the mechanical CAD w.r.t. front wall. + The square window was replaced by a round one to avoid overlaps with present beam pipe designs, e.g. pipe_v16b_1e +)"; + +// ------------- Steering variables ----------------------------------- + +// ---> Horizontal width of sensors [cm] +const Double_t gkSensorSizeX = 6.2; // was 6.2092; // 6.2 - Oleg CAD 15/05/2020 + +// ---> Thickness of sensors [cm] +const Double_t gkSensorThickness = 0.03; + +// ---> Vertical gap between chained sensors [cm] +const Double_t gkChainGapY = 0.00; + +// ---> Thickness of cables [cm] +const Double_t gkCableThickness = 0.02; + +// ---> Horizontal overlap of neighbouring ladders [cm] +const Double_t gkLadderOverlapX = 0.25; // delta X - Oleg CAD 14/05/2020 + +// ---> Vertical overlap of neighbouring sectors in a ladder [cm] +const Double_t gkSectorOverlapY = 0.46; // delta Y - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring sectors in a ladder [cm] +const Double_t gkSectorGapZ = 0.17; // gap + thickness = pitch // delta Z pitch = 0.20 - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring ladders [cm] +const Double_t gkLadderGapZ = 0.50 - 0.20; // for asym // 0.5 for sym // delta Z prime + +// ---> Gap in z between lowest sector to carbon support structure [cm] +const Double_t gkSectorGapZFrame = 0.280 - 0.025; // Oleg CAD 05/05/2020 // there is a 2.8 mm gap between the bottom side of the sensor and the top ledge of the carbon ladder + +// ---> Switch to construct / not to construct readout cables +const Bool_t gkConstructCables = kTRUE; + +// ---> Switch to construct / not to construct frames +const Bool_t gkConstructCones = kFALSE; // kTRUE; // switch this false by default for v15c and v16x +const Bool_t gkConstructFrames = kTRUE; // kFALSE; // switch this true by default for v15c and v16x +const Bool_t gkConstructSmallFrames = kTRUE; // kFALSE; +const Bool_t gkCylindricalFrames = kTRUE; // kFALSE; + +// ---> Size of the frame +const Double_t gkFrameThickness = 0.2; +const Double_t gkThinFrameThickness = 0.05; +const Double_t gkFrameStep = 4.0; // size of frame cell along y direction + +const Double_t gkCylinderDiaInner = 0.07; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) +const Double_t gkCylinderDiaOuter = 0.15; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) + +// ---> Switch to import / not to import the Passive materials from GDML file +//const Bool_t gkImportPassive = kTRUE; +const Bool_t gkImportPassive = kFALSE; + +// ---------------------------------------------------------------------------- + + +// -------------- Parameters of beam pipe in the STS region -------------- +// ---> Needed to compute stations and STS such as to avoid overlaps +const Double_t gkPipeZ1 = 22.0; +const Double_t gkPipeR1 = 1.8; +const Double_t gkPipeZ2 = 50.0; +const Double_t gkPipeR2 = 1.8; +const Double_t gkPipeZ3 = 125.0; +const Double_t gkPipeR3 = 5.5; + +//DE const Double_t gkPipeZ1 = 27.0; +//DE const Double_t gkPipeR1 = 1.05; +//DE const Double_t gkPipeZ2 = 160.0; +//DE const Double_t gkPipeR2 = 3.25; +// ---------------------------------------------------------------------------- + +//TString unitName[16] = // names of units for v16e +// { "Unit00D", +// "Unit01U", "Unit01D", +// "Unit02U", "Unit02D", +// "Unit03U", "Unit03D", +// "Unit04U", "Unit04D", +// "Unit05U", "Unit05D", +// "Unit06U", "Unit06D", +// "Unit07U", "Unit07D", +// "Unit08U" }; + +//TString unitName[32] = // names of units for v16f +// { "Unit00DR", "Unit00DL", +// "Unit01UR", "Unit01UL", "Unit01DR", "Unit01DL", +// "Unit02UR", "Unit02UL", "Unit02DR", "Unit02DL", +// "Unit03UR", "Unit03UL", "Unit03DR", "Unit03DL", +// "Unit04UR", "Unit04UL", "Unit04DR", "Unit04DL", +// "Unit05UR", "Unit05UL", "Unit05DR", "Unit05DL", +// "Unit06UR", "Unit06UL", "Unit06DR", "Unit06DL", +// "Unit07UR", "Unit07UL", "Unit07DR", "Unit07DL", +// "Unit08UR", "Unit08UL" }; + +TString unitName[32] = // names of units for v16g - while merging D and U parts + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", "Unit01R", "Unit01L", + "Unit02R", "Unit02L", "Unit02R", "Unit02L", + "Unit03R", "Unit03L", "Unit03R", "Unit03L", + "Unit04R", "Unit04L", "Unit04R", "Unit04L", + "Unit05R", "Unit05L", "Unit05R", "Unit05L", + "Unit06R", "Unit06L", "Unit06R", "Unit06L", + "Unit07R", "Unit07L", "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +TString unitName18[18] = // names of units for v16g + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", + "Unit02R", "Unit02L", + "Unit03R", "Unit03L", + "Unit04R", "Unit04L", + "Unit05R", "Unit05L", + "Unit06R", "Unit06L", + "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +// ------------- Other global variables ----------------------------------- +// ---> STS medium (for every volume except silicon) +TGeoMedium* gStsMedium = NULL; // will be set later +// ---> TGeoManager (too lazy to write out 'Manager' all the time +TGeoManager* gGeoMan = NULL; // will be set later +// ---------------------------------------------------------------------------- + + + + +// ============================================================================ +// ====== Main function ===== +// ============================================================================ + +void create_stsgeo_v19n(const char* geoTag="v19n") +{ + + // ------- Geometry file name (output) ---------------------------------- + TString geoFileName = "sts_"; + geoFileName = geoFileName + geoTag + ".geo.root"; + // -------------------------------------------------------------------------- + + + // ------- Open info file ----------------------------------------------- + TString infoFileName = geoFileName; + infoFileName.ReplaceAll("root", "info"); + fstream infoFile; + infoFile.open(infoFileName.Data(), fstream::out); + infoFile << "STS geometry created with create_stsgeo_v19n.C" << endl; + infoFile << gVersionHighlight << endl; + infoFile << "Global variables: " << endl; + infoFile << "Sensor thickness = " << gkSensorThickness << " cm" << endl; + infoFile << "Vertical gap in sensor chain = " + << gkChainGapY << " cm" << endl; + infoFile << "Vertical overlap of sensors = " + << gkSectorOverlapY << " cm" << endl; + infoFile << "Gap in z between neighbour sensors = " + << gkSectorGapZ << " cm" << endl; + infoFile << "Horizontal overlap of sensors = " + << gkLadderOverlapX << " cm" << endl; + infoFile << "Gap in z between neighbour ladders = " + << gkLadderGapZ << " cm" << endl; + if ( gkConstructCables ) + infoFile << "Cable thickness = " << gkCableThickness << " cm" << endl; + else + infoFile << "No cables" << endl; + infoFile << endl; + infoFile << "Beam pipe: R1 = " << gkPipeR1 << " cm at z = " + << gkPipeZ1 << " cm" << endl; + infoFile << "Beam pipe: R2 = " << gkPipeR2 << " cm at z = " + << gkPipeZ2 << " cm" << endl; + infoFile << "Beam pipe: R3 = " << gkPipeR3 << " cm at z = " + << gkPipeZ3 << " cm" << endl; + // -------------------------------------------------------------------------- + + + // ------- Load media from media file ----------------------------------- + FairGeoLoader* geoLoad = new FairGeoLoader("TGeo","FairGeoLoader"); + FairGeoInterface* geoFace = geoLoad->getGeoInterface(); + TString geoPath = gSystem->Getenv("VMCWORKDIR"); + TString medFile = geoPath + "/geometry/media.geo"; + geoFace->setMediaFile(medFile); + geoFace->readMedia(); + gGeoMan = gGeoManager; + // -------------------------------------------------------------------------- + + + // ----------------- Get and create the required media ----------------- + FairGeoMedia* geoMedia = geoFace->getMedia(); + FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder(); + + // ---> air + FairGeoMedium* mAir = geoMedia->getMedium("air"); + if ( ! mAir ) Fatal("Main", "FairMedium air not found"); + geoBuild->createMedium(mAir); + TGeoMedium* air = gGeoMan->GetMedium("air"); + if ( ! air ) Fatal("Main", "Medium air not found"); + + // ---> silicon + FairGeoMedium* mSilicon = geoMedia->getMedium("silicon"); + if ( ! mSilicon ) Fatal("Main", "FairMedium silicon not found"); + geoBuild->createMedium(mSilicon); + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + if ( ! silicon ) Fatal("Main", "Medium silicon not found"); + + // ---> carbon + FairGeoMedium* mCarbon = geoMedia->getMedium("carbon"); + if ( ! mCarbon ) Fatal("Main", "FairMedium carbon not found"); + geoBuild->createMedium(mCarbon); + TGeoMedium* carbon = gGeoMan->GetMedium("carbon"); + if ( ! carbon ) Fatal("Main", "Medium carbon not found"); + + // ---> STSBoxCarbonFoam + FairGeoMedium* mSTSBoxCarbonFoam = geoMedia->getMedium("STSBoxCarbonFoam"); + if ( ! mSTSBoxCarbonFoam ) Fatal("Main", "FairMedium STSBoxCarbonFoam not found"); + geoBuild->createMedium(mSTSBoxCarbonFoam); + TGeoMedium* STSBoxCarbonFoam = gGeoMan->GetMedium("STSBoxCarbonFoam"); + if ( ! STSBoxCarbonFoam ) Fatal("Main", "Medium STSBoxCarbonFoam not found"); + + // ---> STSBoxCarbonFibre + FairGeoMedium* mSTSBoxCarbonFibre = geoMedia->getMedium("STSBoxCarbonFibre"); + if ( ! mSTSBoxCarbonFibre ) Fatal("Main", "FairMedium STSBoxCarbonFibre not found"); + geoBuild->createMedium(mSTSBoxCarbonFibre); + TGeoMedium* STSBoxCarbonFibre = gGeoMan->GetMedium("STSBoxCarbonFibre"); + if ( ! STSBoxCarbonFibre ) Fatal("Main", "Medium STSBoxCarbonFibre not found"); + + // ---> STScable + FairGeoMedium* mSTScable = geoMedia->getMedium("STScable"); + if ( ! mSTScable ) Fatal("Main", "FairMedium STScable not found"); + geoBuild->createMedium(mSTScable); + TGeoMedium* STScable = gGeoMan->GetMedium("STScable"); + if ( ! STScable ) Fatal("Main", "Medium STScable not found"); + + // ---> Aluminium + FairGeoMedium* mAluminium = geoMedia->getMedium("aluminium"); + if ( ! mAluminium ) Fatal("Main", "FairMedium aluminium not found"); + geoBuild->createMedium(mAluminium); + TGeoMedium* aluminium = gGeoMan->GetMedium("aluminium"); + if ( ! aluminium ) Fatal("Main", "Medium aluminium not found"); + + // --- + gStsMedium = air; + // -------------------------------------------------------------------------- + + + // -------------- Create geometry and top volume ------------------------- + gGeoMan = (TGeoManager*)gROOT->FindObject("FAIRGeom"); +// gGeoMan->SetName("STSgeom"); + TGeoVolume* top = new TGeoVolumeAssembly("top"); +// TGeoBBox* topbox= new TGeoBBox("", 120., 120., 120.); +// TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air")); + gGeoMan->SetTopVolume(top); + // -------------------------------------------------------------------------- + + + // -------------- Create media ------------------------------------------ + /* + cout << endl; + cout << "===> Creating media...."; + cout << CreateMedia(); + cout << " media created" << endl; + TList* media = gGeoMan->GetListOfMedia(); + for (Int_t iMedium = 0; iMedium < media->GetSize(); iMedium++ ) { + cout << "Medium " << iMedium << ": " + << ((TGeoMedium*) media->At(iMedium))->GetName() << endl; + } + gStsMedium = gGeoMan->GetMedium("air"); + if ( ! gStsMedium ) Fatal("Main", "medium sts_air not found"); + */ + // -------------------------------------------------------------------------- + + + // --------------- Create sensors --------------------------------------- + cout << endl << endl; + cout << "===> Creating sensors...." << endl << endl; + infoFile << endl << "Sensors: " << endl; + Int_t nSensors = CreateSensors(); + for (Int_t iSensor = 1; iSensor <= nSensors; iSensor++) { + TString name = Form("Sensor%02d",iSensor); + TGeoVolume* sensor = gGeoMan->GetVolume(name); + + // add color to sensors + if (iSensor == 1) + sensor->SetLineColor(kRed); + if (iSensor == 2) + sensor->SetLineColor(kGreen); + if (iSensor == 3) + sensor->SetLineColor(kBlue); + if (iSensor == 4) + sensor->SetLineColor(kAzure); + if (iSensor == 5) + sensor->SetLineColor(kYellow); + if (iSensor == 6) + sensor->SetLineColor(kYellow); + if (iSensor == 7) + sensor->SetLineColor(kYellow); + + CheckVolume(sensor); + CheckVolume(sensor, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create sectors -------------------------------------- + cout << endl << endl; + cout << "===> Creating sectors...." << endl; + // infoFile << endl << "Sectors: " << endl; + Int_t nSectors = CreateSectors(); + for (Int_t iSector = 1; iSector <= nSectors; iSector++) { + // cout << endl; + TString name = Form("Sector%02d", iSector); + TGeoVolume* sector = gGeoMan->GetVolume(name); + CheckVolume(sector); + // CheckVolume(sector, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create ladders -------------------------------------- + cout << endl << endl; + cout << "===> Creating ladders...." << endl; + infoFile << endl << "Ladders:" << endl; + + TString name = ""; + TGeoVolume* ladder; + + + Int_t nLadders = CreateLadders(); + + for (Int_t iLadder = 1; iLadder <= nLadders; iLadder++) { + cout << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType0%02d", iLadder); // v19b + name = Form("LadderType00%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF1: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType1%02d", iLadder); // v19b + name = Form("LadderType01%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF2: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType10%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF3: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType11%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF4: ladder name: " << name << endl << endl; + } + // -------------------------------------------------------------------------- + + + // ---------------- Create cones ---------------------------------------- + Double_t coneDz = 1.64; + TGeoVolume* coneSmallVolum = ConstructSmallCone(coneDz); + if (!coneSmallVolum) Fatal("ConstructSmallCone", "Volume Cone not found"); + TGeoVolume* coneBigVolum = ConstructBigCone(coneDz); + if (!coneBigVolum) Fatal("ConstructBigCone", "Volume Cone not found"); + // -------------------------------------------------------------------------- + + + // ---------------- Create stations ------------------------------------- + cout << endl << endl; + cout << "===> Creating stations...." << endl; + infoFile << endl << "Stations: " << endl; + Int_t angle = 0; + nLadders = 0; + Int_t ladderTypes[16]; // there are max 16 ladders in one layer + TGeoTranslation* statTrans = NULL; + + TGeoVolume *myunit[32]; // units + +// Int_t statPos[8] = { 30, 40, 50, 60, 70, 80, 90, 100 }; // z positions of stations +// Int_t statPos[16] = { 28, 32, 38, 42, 48, 52, 58, 62, +// 68, 72, 78, 82, 88, 92, 98,102 }; // z positions of units +// Int_t statPos[16] = { 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units +// Int_t statPos18[18] = { 30, 30, // expanded for placement of Unit00 +// 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units + // v19h + Double_t statPos[16] = { 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of units + Double_t statPos18[18] = { 26.0, 26.0, // expanded for placement of Unit00 + 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of unit + +// // v19d +// Double_t statPos[16] = { 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units +// Double_t statPos18[18] = { 30.0, 30.0, // expanded for placement of Unit00 +// 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units + +////Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.9 , 3.7 , 3.7 , 4.2 , 4.2 }; // size of cutouts in stations +// Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.43, 3.04, 3.35, 3.96, 4.2 }; // size of cutouts in stations, derived from gapXYZ[x][1]/2 + + Int_t cone_size[8] = { 0, 0, 0, 1, 1, 1, 1, 1 }; // size of cones: 0 = small, 1 = large + + Double_t cone_offset[2] = { 0.305, 0.285 }; + +// Int_t allLadderTypes[8][16]= +// { { -1, -1, -1, -1, 10, 109, 9, 101, 1, 109, 9, 110, -1, -1, -1, -1 }, // station 1 +// { -1, -1, 111, 10, 110, 9, 109, 2, 102, 9, 109, 10, 110, 11, -1, -1 }, // station 2 +// { -1, -1, 14, 113, 12, 112, 12, 103, 3, 112, 12, 112, 13, 114, -1, -1 }, // station 3 +// { -1, 15, 114, 13, 112, 12, 112, 4, 104, 12, 112, 12, 113, 14, 115, -1 }, // station 4 +// { -1, 119, 18, 117, 17, 116, 16, 105, 5, 116, 16, 117, 17, 118, 19, -1 }, // station 5 +// { -1, 19, 118, 17, 117, 16, 116, 6, 106, 16, 116, 17, 117, 18, 119, -1 }, // station 6 +// { 21, 119, 18, 120, 20, 120, 20, 107, 7, 120, 20, 120, 20, 118, 19, 121 }, // station 7 +// { 119, 17, 123, 22, 122, 22, 122, 8, 108, 22, 122, 22, 122, 23, 117, 19 } }; // station 8 + +//============================================================================================== + +// explanation: type xyzz +// where x = carbon ladder orientation +// where y = FEB box orientation +// where zz = sensor arrangement on ladder +// with FEB orientation - v19b + Int_t allUnitTypes[16][16]= + { { -1, -1, -1, -1, 10, 0, 9, 0, 101, 0, 109, 0, -1, -1, -1, -1 }, // unit00D Station01 00 + { -1, -1, -1, -1, 0, 1109, 0, 1101, 0, 1009, 0, 1010, -1, -1, -1, -1 }, // unit01U Station01 01 + + { -1, -1, 0, 10, 0, 9, 0, 2, 0, 109, 0, 110, 0, 111, -1, -1 }, // unit01D Station02 02 + { -1, -1, 1111, 0, 1110, 0, 1109, 0, 1002, 0, 1009, 0, 1010, 0, -1, -1 }, // unit02U Station02 03 + + { -1, -1, 14, 0, 12, 0, 12, 0, 103, 0, 112, 0, 113, 0, -1, -1 }, // unit02D Station03 04 + { -1, -1, 0, 1113, 0, 1112, 0, 1103, 0, 1012, 0, 1012, 0, 1014, -1, -1 }, // unit03U Station03 05 + + { -1, 15, 0, 13, 0, 12, 0, 4, 0, 112, 0, 112, 0, 114, 0, -1 }, // unit03D Station04 06 + { -1, 0, 1114, 0, 1112, 0, 1112, 0, 1004, 0, 1012, 0, 1013, 0, 1015, -1 }, // unit04U Station04 07 + + { -1, 0, 18, 0, 17, 0, 16, 0, 105, 0, 116, 0, 117, 0, 119, -1 }, // unit04D Station05 08 + { -1, 1119, 0, 1117, 0, 1116, 0, 1105, 0, 1016, 0, 1017, 0, 1018, 0, -1 }, // unit05U Station05 09 + + { -1, 19, 0, 17, 0, 16, 0, 6, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05D Station06 10 + { -1, 0, 1118, 0, 1117, 0, 1116, 0, 1006, 0, 1016, 0, 1017, 0, 1019, -1 }, // unit06U Station06 11 + + { 21, 0, 25, 0, 20, 0, 20, 0, 107, 0, 120, 0, 120, 0, 127, 0 }, // unit06D Station07 12 + { 0, 1127, 0, 1120, 0, 1120, 0, 1107, 0, 1020, 0, 1020, 0, 1025, 0, 1021 }, // unit07U Station07 13 + + { 0, 24, 0, 22, 0, 22, 0, 8, 0, 122, 0, 122, 0, 123, 0, 126 }, // unit07D Station08 14 + { 1126, 0, 1123, 0, 1122, 0, 1122, 0, 1008, 0, 1022, 0, 1022, 0, 1024, 0 } }; // unit08U Station08 15 + +//============================================================================================== + +// without FEB orientation - v19a +// v19a Int_t allUnitTypes[16][16]= +// v19a { { -1, -1, -1, -1, 10, 0, 9, 0, 1, 0, 9, 0, -1, -1, -1, -1 }, // unit00D Station01 00 +// v19a { -1, -1, -1, -1, 0, 109, 0, 101, 0, 109, 0, 110, -1, -1, -1, -1 }, // unit01U Station01 01 +// v19a { -1, -1, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, -1, -1 }, // unit01D Station02 02 +// v19a { -1, -1, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, -1, -1 }, // unit02U Station02 03 +// v19a { -1, -1, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, -1, -1 }, // unit02D Station03 04 +// v19a { -1, -1, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, -1, -1 }, // unit03U Station03 05 +// v19a { -1, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, -1 }, // unit03D Station04 06 +// v19a { -1, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, -1 }, // unit04U Station04 07 +// v19a { -1, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, -1 }, // unit04D Station05 08 +// v19a { -1, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05U Station05 09 +// v19a { -1, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, -1 }, // unit05D Station06 10 +// v19a { -1, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, -1 }, // unit06U Station06 11 +// v19a { 21, 0, 25, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 27, 0 }, // unit06D Station07 12 +// v19a { 0, 127, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 125, 0, 121 }, // unit07U Station07 13 +// v19a { 0, 24, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 26 }, // unit07D Station08 14 +// v19a { 126, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 124, 0 } }; // unit08U Station08 15 + + +// unitTypes[0] = { 0, 0, 0, 0, 10, 0, 9, 0, 1, 0, 9, 0, 0, 0, 0, 0 }; // unit 0D +// unitTypes[1] = { 0, 0, 0, 0, 0, 109, 0, 101, 0, 109, 0, 110, 0, 0, 0, 0 }; // unit 1U +// unitTypes[2] = { 0, 0, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, 0, 0 }; // unit 1D +// unitTypes[3] = { 0, 0, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, 0, 0 }; // unit 2U +// unitTypes[4] = { 0, 0, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, 0, 0 }; // unit 2D +// unitTypes[5] = { 0, 0, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, 0, 0 }; // unit 3U +// unitTypes[6] = { 0, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, 0 }; // unit 3D +// unitTypes[7] = { 0, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, 0 }; // unit 4U +// unitTypes[8] = { 0, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, 0 }; // unit 4D +// unitTypes[9] = { 0, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, 0 }; // unit 5U +// unitTypes[10] = { 0, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, 0 }; // unit 5D +// unitTypes[11] = { 0, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, 0 }; // unit 6U +// unitTypes[12] = { 21, 0, 18, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 19, 0 }; // unit 6D +// unitTypes[13] = { 0, 119, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 118, 0, 121 }; // unit 7U +// unitTypes[14] = { 0, 17, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 19 }; // unit 7D +// unitTypes[15] = { 119, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 117, 0 }; // unit 8U + + +// // generate unit +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) +// for (Int_t iLadder = 0; iLadder < 16; iLadder++) +// { +// allUnitTypes[iUnit][iLadder] = 0; +// if ((iUnit % 2 == 0) && (allLadderTypes[iUnit/2][iLadder] < 100)) // if carbon structure is oriented upstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// if ((iUnit % 2 == 1) && (allLadderTypes[iUnit/2][iLadder] >= 100)) // if carbon structure is oriented downstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// } + + + // dump unit + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << "DE unitTypes[" << iUnit << "] = { "; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + { + cout << allUnitTypes[iUnit][iLadder]; + if (iLadder < 15) + cout << ", "; + else + cout << " };"; + } + cout << endl; + } + + + // --- Units 01 - 16 + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << endl; + + nLadders = 0; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + if (allUnitTypes[iUnit][iLadder] >= 0) + { + ladderTypes[nLadders] = allUnitTypes[iUnit][iLadder]; + cout << "DE ladderTypes[" << nLadders << "] = " << allUnitTypes[iUnit][iLadder] << ";" << endl; + nLadders++; + } + myunit[iUnit*2+0] = ConstructUnit(0, iUnit*2+0, nLadders, ladderTypes, iUnit/2+1); + myunit[iUnit*2+1] = ConstructUnit(1, iUnit*2+1, nLadders, ladderTypes, iUnit/2+1); + +// if (gkConstructCones) { +// if (iUnit%2 == 0) +// angle = 90; +// else +// angle = -90; +// +// // upstream +// TGeoRotation* coneRot11 = new TGeoRotation; +// coneRot11->RotateZ(angle); +// coneRot11->RotateY(180); +// TGeoCombiTrans* conePosRot11 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-cone_offset[cone_size[iUnit]]-gkLadderGapZ/2., coneRot11); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 1, conePosRot11); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 1, conePosRot11); +// +// // downstream +// TGeoRotation* coneRot12 = new TGeoRotation; +// coneRot12->RotateZ(angle); +// TGeoCombiTrans* conePosRot12 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+cone_offset[cone_size[iUnit]]+gkLadderGapZ/2., coneRot12); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 2, conePosRot12); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 2, conePosRot12); +// +// myunit[iUnit]->GetShape()->ComputeBBox(); +// } + +// CheckVolume(myunit[iUnit]); +// CheckVolume(myunit[iUnit], infoFile); + if ((iUnit%2 == 0)||(iUnit == 15)) + { + CheckVolume(myunit[iUnit*2+0]); + CheckVolume(myunit[iUnit*2+0], infoFile); + CheckVolume(myunit[iUnit*2+1]); + CheckVolume(myunit[iUnit*2+1], infoFile); + } + infoFile << "Position z = " << statPos[iUnit] << endl; + } + // -------------------------------------------------------------------------- + + + // --------------- Create STS volume ------------------------------------ + cout << endl << endl; + cout << "===> Creating STS...." << endl; + +// // --- Determine size of STS box +// Double_t stsX = 0.; +// Double_t stsY = 0.; +// Double_t stsZ = 0.; +// Double_t stsBorder = 2*5.; // 5 cm space for carbon ladders on each side +// for (Int_t iStation = 1; iStation<=8; iStation++) { +// TString statName = Form("Station%02d", iStation); +// TGeoVolume* station = gGeoMan->GetVolume(statName); +// TGeoBBox* shape = (TGeoBBox*) station->GetShape(); +// stsX = TMath::Max(stsX, 2.* shape->GetDX() ); +// stsY = TMath::Max(stsY, 2.* shape->GetDY() ); +// cout << "Station " << iStation << ": Y " << stsY << endl; +// } +// // --- Some border around the stations +// stsX += stsBorder; +// stsY += stsBorder; +// stsZ = ( statPos[7] - statPos[0] ) + stsBorder; +// +// // --- Create box around the stations +// new TGeoBBox("stsBox", stsX/2., stsY/2., stsZ/2.); +// cout << "size of STS box: x " << stsX << " - y " << stsY << " - z " << stsZ << endl; +// +// // --- Create cone hosting the beam pipe +// // --- One straight section with constant radius followed by a cone +// Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +// Double_t z2 = gkPipeZ2; +// Double_t z3 = statPos[7] + 0.5 * stsBorder; // end of STS box +// Double_t r1 = BeamPipeRadius(z1); +// Double_t r2 = BeamPipeRadius(z2); +// Double_t r3 = BeamPipeRadius(z3); +// r1 += 0.01; // safety margin +// r2 += 0.01; // safety margin +// r3 += 0.01; // safety margin +// +// cout << endl; +// cout << z1 << " " << r1 << endl; +// cout << z2 << " " << r2 << endl; +// cout << z3 << " " << r3 << endl; +// +// cout << endl; +// cout << "station1 : " << BeamPipeRadius(statPos[0]) << endl; +// cout << "station2 : " << BeamPipeRadius(statPos[1]) << endl; +// cout << "station3 : " << BeamPipeRadius(statPos[2]) << endl; +// cout << "station4 : " << BeamPipeRadius(statPos[3]) << endl; +// cout << "station5 : " << BeamPipeRadius(statPos[4]) << endl; +// cout << "station6 : " << BeamPipeRadius(statPos[5]) << endl; +// cout << "station7 : " << BeamPipeRadius(statPos[6]) << endl; +// cout << "station8 : " << BeamPipeRadius(statPos[7]) << endl; +// +// // TGeoPcon* cutout = new TGeoPcon("stsCone", 0., 360., 3); // 2.*TMath::Pi(), 3); +// // cutout->DefineSection(0, z1, 0., r1); +// // cutout->DefineSection(1, z2, 0., r2); +// // cutout->DefineSection(2, z3, 0., r3); +// new TGeoTrd2("stsCone1", r1, r2, r1, r2, (z2-z1)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans1 = new TGeoTranslation("trans1", 0., 0., -(z3-z1)/2.+(z2-z1)/2.); +// trans1->RegisterYourself(); +// new TGeoTrd2("stsCone2", r2, r3, r2, r3, (z3-z2)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans2 = new TGeoTranslation("trans2", 0., 0., +(z3-z1)/2.-(z3-z2)/2.); +// trans2->RegisterYourself(); +// +////DE Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +////DE Double_t z2 = statPos[7] + 0.5 * stsBorder; // end of STS box +////DE Double_t slope = (gkPipeR2 - gkPipeR1) / (gkPipeZ2 - gkPipeZ1); +////DE Double_t r1 = gkPipeR1 + slope * (z1 - gkPipeZ1); // at start of STS +////DE Double_t r2 = gkPipeR1 + slope * (z2 - gkPipeZ1); // at end of STS +////DE r1 += 0.1; // safety margin +////DE r2 += 0.1; // safety margin +////DE // new TGeoCone("stsCone", stsZ/2., 0., r1, 0., r2); +////DE new TGeoTrd2("stsCone", r1, r2, r1, r2, stsZ/2.); + + + // // Create holding/cooling plates + // static std::vector< std::vector<Double_t> > plateSizes = { + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // }; + + // // 8-vertex cut-outs { minWidth, maxWidth, minHeight, maxHeight } + // static std::vector< std::vector<Double_t> > plateCutOuts = { + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 17.6, 47.6 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 49.0, 79.0 }, + // { 85.5,115.5, 51.5, 82.8 }, + // { 85.5,115.5, 59.0, 91.4 }, + // { 85.5,115.5, 68.0, 99.0 }, + // }; + + // for (Int_t iPlate = 0; iPlate < 9; iPlate++) { + // Int_t iUnit = iPlate * 2; + // TGeoBBox* outerPlate = new TGeoBBox(Form("outerPlate%02d",iPlate), + // plateSizes[iPlate][0], plateSizes[iPlate][1], plateSizes[iPlate][2]); + + // TGeoBBox* unitShapeR = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+0])->GetShape(); + // TGeoBBox* unitShapeL = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+1])->GetShape(); + + // Double_t maxDx = (unitShapeR->GetDX() + unitShapeL->GetDX()) / 2.; + // Double_t maxDy = TMath::Max(unitShapeR->GetDY(), unitShapeL->GetDY()); + // cout << maxDy << endl; + + // Double_t* cutOutX = new Double_t[8]; + // Double_t* cutOutY = new Double_t[8]; + + // cutOutX[0] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[0] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[1] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[1] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[2] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[2] = 1/2. * plateCutOuts[iPlate][2]; + // cutOutX[3] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[3] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[4] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[4] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[5] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[5] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[6] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[6] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[7] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[7] = 1/2. * plateCutOuts[iPlate][2]; + + // TGeoXtru* cutOutShape = new TGeoXtru(2); + // cutOutShape->SetName(Form("innerPlate%02d", iPlate)); + // cutOutShape->DefinePolygon(8, cutOutX, cutOutY); + // cutOutShape->DefineSection(0, -1*plateSizes[iPlate][2]-1e-7); + // cutOutShape->DefineSection(1, +1*plateSizes[iPlate][2]+1e-7); + + // TGeoShape* plateShape = new TGeoCompositeShape(Form("PlateShape%02d",iPlate), Form("outerPlate%02d-innerPlate%02d",iPlate,iPlate)); + // TGeoVolume* plate = new TGeoVolume(Form("Plate%02d", iPlate), plateShape, gGeoManager->GetMedium("aluminium")); + // plate->SetLineColor(kRed); + // plate->SetTransparency(65); + // plate->GetShape()->ComputeBBox(); + // } + + // --- Create STS volume + TString stsName = "sts_"; + stsName += geoTag; + +// TGeoShape* stsShape = new TGeoCompositeShape("stsShape", +// "stsBox-stsCone1:trans1-stsCone2:trans2"); +// TGeoVolume* sts = new TGeoVolume(stsName.Data(), stsShape, gStsMedium); + + Double_t stsBorder = 2 * 5.; + + TGeoVolume* sts = new TGeoVolumeAssembly(stsName.Data()); + + // --- Place stations in the STS + Double_t stsPosZ = 0.5 * ( statPos[15] + statPos[0] ); // todo units: update statPos[7] + // cout << "stsPosZ " << stsPosZ << " " << statPos[15] << " " << statPos[0] << "*****" << endl; + +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) { + for (Int_t iUnit = 0; iUnit < 18; iUnit++) { +// for (Int_t iUnit = 0; iUnit < 32; iUnit++) { + TGeoVolume* station = gGeoMan->GetVolume(unitName18[iUnit]); +// Double_t posZ = statPos[iUnit] - stsPosZ; + Double_t posZ = statPos18[iUnit] - stsPosZ; +// Double_t posZ = statPos[iUnit/2] - stsPosZ; + TGeoTranslation* trans = new TGeoTranslation(0., 0., posZ); + sts->AddNode(station, iUnit+1, trans); + sts->GetShape()->ComputeBBox(); + } + + // --- Import passive elements from GDML file + if (gkImportPassive) { + ImportPassive(sts, geoTag, infoFile); + } + + cout << endl; + CheckVolume(sts); + // -------------------------------------------------------------------------- + + + // --------------- Finish ----------------------------------------------- + TGeoTranslation* stsTrans = new TGeoTranslation(0., 0., stsPosZ); + top->AddNode(sts, 1, stsTrans); + top->GetShape()->ComputeBBox(); + cout << endl << endl; + + CheckVolume(top); + cout << endl << endl; + gGeoMan->CloseGeometry(); + gGeoMan->CheckOverlaps(0.0001); + gGeoMan->PrintOverlaps(); + gGeoMan->CheckOverlaps(0.0001, "s"); + gGeoMan->PrintOverlaps(); + gGeoMan->Test(); + + TFile* geoFile = new TFile(geoFileName, "RECREATE"); + top->Write(); + cout << endl; + cout << "Geometry " << top->GetName() << " written to " + << geoFileName << endl; + geoFile->Close(); + + TString geoFileName_ = "sts_"; + geoFileName_ = geoFileName_ + geoTag + "_geo.root"; + + geoFile = new TFile(geoFileName_, "RECREATE"); + gGeoMan->Write(); // use this is you want GeoManager format in the output + geoFile->Close(); + + TString geoFileName__ = "sts_"; + geoFileName_ = geoFileName__ + geoTag + "-geo.root"; + sts->Export(geoFileName_); + + geoFile = new TFile(geoFileName_, "UPDATE"); + stsTrans->Write(); + geoFile->Close(); + + // gGeoManager->FindVolumeFast("LadderType10_CarbonElement")->Draw("ogl"); + top->Draw("ogl"); + gGeoManager->SetVisLevel(8); + + infoFile.close(); + +} +// ============================================================================ +// ====== End of main function ===== +// ============================================================================ + + + + + +// **************************************************************************** +// ***** Definition of media, sensors, sectors and ladders ***** +// ***** ***** +// ***** Decoupled from main function for better readability ***** +// **************************************************************************** + + +/** =========================================================================== + ** Create media + ** + ** Currently created: air, active silicon, passive silion + ** + ** Not used for the time being + **/ +Int_t CreateMedia() { + + Int_t nMedia = 0; + Double_t density = 0.; + + // --- Material air + density = 1.205e-3; // [g/cm^3] + TGeoMixture* matAir = new TGeoMixture("sts_air", 3, density); + matAir->AddElement(14.0067, 7, 0.755); // Nitrogen + matAir->AddElement(15.999, 8, 0.231); // Oxygen + matAir->AddElement(39.948, 18, 0.014); // Argon + + // --- Material silicon + density = 2.33; // [g/cm^3] + TGeoElement* elSi = gGeoMan->GetElementTable()->GetElement(14); + TGeoMaterial* matSi = new TGeoMaterial("matSi", elSi, density); + + + // --- Air (passive) + TGeoMedium* medAir = new TGeoMedium("air", nMedia++, matAir); + medAir->SetParam(0, 0.); // is passive + medAir->SetParam(1, 1.); // is in magnetic field + medAir->SetParam(2, 20.); // max. field [kG] + medAir->SetParam(6, 0.001); // boundary crossing precision [cm] + + + // --- Active silicon for sensors + TGeoMedium* medSiAct = new TGeoMedium("silicon", + nMedia++, matSi); + medSiAct->SetParam(0, 1.); // is active + medSiAct->SetParam(1, 1.); // is in magnetic field + medSiAct->SetParam(2, 20.); // max. field [kG] + medSiAct->SetParam(6, 0.001); // boundary crossing precisison [cm] + + // --- Passive silicon for cables + TGeoMedium* medSiPas = new TGeoMedium("carbon", + nMedia++, matSi); + medSiPas->SetParam(0, 0.); // is passive + medSiPas->SetParam(1, 1.); // is in magnetic field + medSiPas->SetParam(2, 20.); // max. field [kG] + medSiPas->SetParam(6, 0.001); // boundary crossing precisison [cm] + + return nMedia; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sensors + ** + ** Sensors are created as volumes with box shape and active silicon as medium. + ** Four kinds of sensors: 3.2x2.2, 6.2x2.2, 6.2x4.2, 6.2x6.2 + **/ +Int_t CreateSensors() { + + Int_t nSensors = 0; + + Double_t xSize = 0.; + Double_t ySize = 0.; + Double_t zSize = gkSensorThickness; + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + + + // --- Sensor type 01: Small sensor (6.2 cm x 2.2 cm) + xSize = gkSensorSizeX; + ySize = 2.2; + TGeoBBox* shape_sensor01 = new TGeoBBox("sensor01", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor01", shape_sensor01, silicon); + nSensors++; + + + // --- Sensor type 02: Medium sensor (6.2 cm x 4.2 cm) + xSize = gkSensorSizeX; + ySize = 4.2; + TGeoBBox* shape_sensor02 = new TGeoBBox("sensor02", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor02", shape_sensor02, silicon); + nSensors++; + + + // --- Sensor type 03: Big sensor (6.2 cm x 6.2 cm) + xSize = gkSensorSizeX; + ySize = 6.2; + TGeoBBox* shape_sensor03 = new TGeoBBox("sensor03", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor03", shape_sensor03, silicon); + nSensors++; + + + // --- Sensor type 04: Big sensor (6.2 cm x 12.4 cm) + xSize = gkSensorSizeX; + ySize = 12.4; + TGeoBBox* shape_sensor04 = new TGeoBBox("sensor04", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor04", shape_sensor04, silicon); + nSensors++; + + + // below are extra small sensors, those are not available in the CAD model + + // --- Sensor Type 05: Half small sensor (4 cm x 2.5 cm) + xSize = 4.0; + ySize = 2.5; + TGeoBBox* shape_sensor05 = new TGeoBBox("sensor05", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor05", shape_sensor05, silicon); + nSensors++; + + + // --- Sensor type 06: Additional "in hole" sensor (3.1 cm x 4.2 cm) + xSize = 3.1; + ySize = 4.2; + TGeoBBox* shape_sensor06 = new TGeoBBox("sensor06", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor06", shape_sensor06, silicon); + nSensors++; + + + // --- Sensor type 07: Mini Medium sensor (1.5 cm x 4.2 cm) + xSize = 1.5; + ySize = 4.2; + TGeoBBox* shape_sensor07 = new TGeoBBox("sensor07", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor07", shape_sensor07, silicon); + nSensors++; + + + return nSensors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sectors + ** + ** A sector is either a single sensor or several chained sensors. + ** It is implemented as TGeoVolumeAssembly. + ** Currently available: + ** - single sensors of type 1 - 4 + ** - two chained sensors of type 4 + ** - three chained sensors of type 4 + **/ +Int_t CreateSectors() { + + Int_t nSectors = 0; + + TGeoVolume* sensor01 = gGeoMan->GetVolume("Sensor01"); + TGeoVolume* sensor02 = gGeoMan->GetVolume("Sensor02"); + TGeoVolume* sensor03 = gGeoMan->GetVolume("Sensor03"); + TGeoVolume* sensor04 = gGeoMan->GetVolume("Sensor04"); + TGeoVolume* sensor05 = gGeoMan->GetVolume("Sensor05"); + TGeoVolume* sensor06 = gGeoMan->GetVolume("Sensor06"); + TGeoVolume* sensor07 = gGeoMan->GetVolume("Sensor07"); + // TGeoBBox* box4 = (TGeoBBox*) sensor04->GetShape(); + + // --- Sector type 1: single sensor of type 1 + TGeoVolumeAssembly* sector01 = new TGeoVolumeAssembly("Sector01"); + sector01->AddNode(sensor01, 1); + sector01->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 2: single sensor of type 2 + TGeoVolumeAssembly* sector02 = new TGeoVolumeAssembly("Sector02"); + sector02->AddNode(sensor02, 1); + sector02->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 3: single sensor of type 3 + TGeoVolumeAssembly* sector03 = new TGeoVolumeAssembly("Sector03"); + sector03->AddNode(sensor03, 1); + sector03->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 4: single sensor of type 4 + TGeoVolumeAssembly* sector04 = new TGeoVolumeAssembly("Sector04"); + sector04->AddNode(sensor04, 1); + sector04->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 5: single sensor of type 5 + TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); + sector05->AddNode(sensor05, 1); + sector05->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 6: single sensor of type 6 + TGeoVolumeAssembly* sector06 = new TGeoVolumeAssembly("Sector06"); + sector06->AddNode(sensor06, 1); + sector06->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 7: single sensor of type 7 + TGeoVolumeAssembly* sector07 = new TGeoVolumeAssembly("Sector07"); + sector07->AddNode(sensor07, 1); + sector07->GetShape()->ComputeBBox(); + nSectors++; + +// // --- Sector type 5: two sensors of type 4 +// TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); +// Double_t shift5 = 0.5 * gkChainGapY + box4->GetDY(); +// TGeoTranslation* transD5 = +// new TGeoTranslation("td", 0., -1. * shift5, 0.); +// TGeoTranslation* transU5 = +// new TGeoTranslation("tu", 0., shift5, 0.); +// sector05->AddNode(sensor04, 1, transD5); +// sector05->AddNode(sensor04, 2, transU5); +// sector05->GetShape()->ComputeBBox(); +// nSectors++; + + return nSectors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create ladders + ** + ** Ladders are the building blocks of the stations. They contain + ** several modules placed one after the other along the z axis + ** such that the sectors are arranged vertically (with overlap). + ** + ** A ladder is constructed out of two half ladders, the second of which + ** is rotated in the x-y plane by 180 degrees and displaced + ** in z direction. + **/ +Int_t CreateLadders() { + + Int_t nLadders = 0; + + // --- Some variables + Int_t nSectors = 0; + Int_t sectorTypes[10]; + TGeoBBox* shape = NULL; + TString s0name; + TString hlname; + char align; + TGeoVolume* s0vol = NULL; + TGeoVolume* halfLadderU = NULL; + TGeoVolume* halfLadderD = NULL; + + // --- Ladders 01-23 + Int_t allSectorTypes[27][6] = { { 1, 2, 3, 3, 0, -1 }, // ladder 01 - 5 - last column defines alignment of small sensors + { 1, 2, 3, 3, 0, 0 }, // ladder 02 - 5 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, -1 }, // ladder 03 - 6 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 04 - 6 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, -1 }, // ladder 05 - 7 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 06 - 7 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 07 - last column defines alignment of small sensors + { 3, 4, 4, 4, 0, 0 }, // ladder 08 - last column defines alignment of small sensors + + { 1, 1, 2, 3, 3, 0 }, // ladder 09 - last column defines alignment of small sensors + { 1, 1, 2, 2, 3, 0 }, // ladder 10 - last column defines alignment of small sensors + { 2, 2, 0, 0, 0, 0 }, // ladder 11 - last column defines alignment of small sensors + { 2, 2, 2, 3, 4, 0 }, // ladder 12 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 13 - last column defines alignment of small sensors + + { 2, 3, 4, 0, 0, 0 }, // ladder 14 - last column defines alignment of small sensors + { 3, 3, 0, 0, 0, 0 }, // ladder 15 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 16 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 17 - last column defines alignment of small sensors + { 3, 4, 4, 0, 0, 0 }, // ladder 18 - last column defines alignment of small sensors + + { 4, 4, 0, 0, 0, 0 }, // ladder 19 - last column defines alignment of small sensors + { 1, 2, 4, 4, 4, 0 }, // ladder 20 - last column defines alignment of small sensors + { 4, 0, 0, 0, 0, 0 }, // ladder 21 - last column defines alignment of small sensors + { 2, 3, 4, 4, 4, 0 }, // ladder 22 - last column defines alignment of small sensors + { 2, 3, 3, 4, 4, 0 }, // ladder 23 - last column defines alignment of small sensors + + { 2, 3, 4, 4, 0, 0 }, // ladder 24 - copy of 17 with different total length + { 3, 4, 4, 0, 0, 0 }, // ladder 25 - copy of 18 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 26 - copy of 19 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 27 - copy of 19 with different total length + }; + +// Issue #405 +// Counting from the most upstream ladder, the gaps between sensors are as follows: +// 01 (most upstream): 41.3mm +// 02: 41.3mm +// 03: 42.0mm +// 04: 48.6mm +// 05: 60.8mm +// 06: 67.0mm +// 07: 79.2mm +// 08 (most downstream): 88.0mm + + Double_t gapXYZ[27][3] = { + { 0., 4.13, 0. }, // ladder 01 + { 0., 4.13, 0. }, // ladder 02 + { 0., 4.20, 0. }, // ladder 03 + { 0., 4.86, 0. }, // ladder 04 + { 0., 6.08, 0. }, // ladder 05 + { 0., 6.70, 0. }, // ladder 06 + { 0., 7.92, 0. }, // ladder 07 + { 0., 8.80, 0. }, // ladder 08 + { 0., -gkSectorOverlapY, 0. }, // ladder 09 + { 0., -gkSectorOverlapY, 0. }, // ladder 10 + { 0., -gkSectorOverlapY, 0. }, // ladder 11 + { 0., -gkSectorOverlapY, 0. }, // ladder 12 + { 0., -gkSectorOverlapY, 0. }, // ladder 13 + { 0., -gkSectorOverlapY, 0. }, // ladder 14 + { 0., -gkSectorOverlapY, 0. }, // ladder 15 + { 0., -gkSectorOverlapY, 0. }, // ladder 16 + { 0., -gkSectorOverlapY, 0. }, // ladder 17 + { 0., -gkSectorOverlapY, 0. }, // ladder 18 + { 0., -gkSectorOverlapY, 0. }, // ladder 19 + { 0., -gkSectorOverlapY, 0. }, // ladder 20 + { 0., -gkSectorOverlapY, 0. }, // ladder 21 + { 0., -gkSectorOverlapY, 0. }, // ladder 22 + { 0., -gkSectorOverlapY, 0. }, // ladder 23 + + { 0., -gkSectorOverlapY, 0. }, // ladder 24 - copy of 17 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 25 - copy of 18 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 26 - copy of 19 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 27 - copy of 19 with different total length + }; + + Double_t ladderLength[27] = { + 48.0, // ladder 01 + 48.0, // ladder 02 + 64.0, // ladder 03 + 64.0, // ladder 04 + 80.0, // ladder 05 + 80.0, // ladder 06 + 92.0, // ladder 07 + 96.0, // ladder 08 + 48.0, // ladder 09 + 48.0, // ladder 10 + 48.0, // ladder 11 + 64.0, // ladder 12 + 64.0, // ladder 13 + 64.0, // ladder 14 + 64.0, // ladder 15 + 80.0, // ladder 16 + 80.0, // ladder 17 + 80.0, // ladder 18 + 80.0, // ladder 19 + 92.0, // ladder 20 + 92.0, // ladder 21 + 96.0, // ladder 22 + 96.0, // ladder 23 + + 96.0, // ladder 24 - copy of 17 with different total length + 92.0, // ladder 25 - copy of 18 with different total length + 96.0, // ladder 26 - copy of 19 with different total length + 92.0, // ladder 27 - copy of 19 with different total length + }; +// ======================================================================== + + // calculate Z shift for ladders with and without gaps in the center + s0name = Form("Sector%02d", allSectorTypes[0][0]); + s0vol = gGeoMan->GetVolume(s0name); + shape = (TGeoBBox*) s0vol->GetShape(); + + for (Int_t iLadder = 0; iLadder < 27; iLadder++) + { + if (iLadder+1 <= 8) // for the 2 inner ladders of each station with gap for beampipe + gapXYZ[iLadder][2] = 0; // there is no offset in z for halfladders on ladders with a beampipe hole + else + gapXYZ[iLadder][2] = 2. * shape->GetDZ() + gkSectorGapZ; // set displacement in z for overlapping half ladders + } + +// ======================================================================== + + for (Int_t iLadder = 0; iLadder < 27; iLadder++) + { + cout << endl; + nSectors = 0; + for (Int_t i=0; i < 5; i++) + if (allSectorTypes[iLadder][i] != 0) + { + sectorTypes[nSectors] = allSectorTypes[iLadder][i]; // copy sectors for this ladder + cout << "DE iLadder " << iLadder+1 << " sectorTypes[" << nSectors << "] = " << allSectorTypes[iLadder][i] << ";" << endl; + nSectors++; // count how many sectors are in this ladder + } + + if (allSectorTypes[iLadder][5] == 0) + align = 'l'; + else + align = 'r'; + hlname = Form("HalfLadder%02du", iLadder+1); + // build upper half ladder + halfLadderU = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2.); // mirrored + + if (allSectorTypes[iLadder][5] == 0) + align = 'r'; + else + align = 'l'; + hlname = Form("HalfLadder%02dd", iLadder+1); + // build lower half ladder + halfLadderD = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2.); // mirrored + + // at this point half ladders are constructed + + // build all 4 possible ladders types for this sensor arrangement + ConstructLadder( iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19a + ConstructLadder( 100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19b + + ConstructLadder(1000+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19k + ConstructLadder(1100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19k + + nLadders++; + } + + return nLadders; +} +/** ======================================================================= **/ + + + +// **************************************************************************** +// ***** ***** +// ***** Generic functions for the construction of STS elements ***** +// ***** ***** +// ***** module: volume (made of a sector and a cable) ***** +// ***** haf ladder: assembly (made of modules) ***** +// ***** ladder: assembly (made of two half ladders) ***** +// ***** station: volume (made of ladders) ***** +// ***** ***** +// **************************************************************************** + + + +/** =========================================================================== + ** Construct a module + ** + ** A module is a sector plus the readout cable extending from the + ** top of the sector. The cable is made from passive silicon. + ** The cable has the same x size as the sector. + ** Its thickness is given by the global variable gkCableThickness. + ** The cable length is a parameter. + ** The sensor(s) of the sector is/are placed directly in the module; + ** the sector is just auxiliary for the proper placement. + ** + ** Arguments: + ** name volume name + ** sector pointer to sector volume + ** cableLength length of cable + **/ +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength) { + + // --- Check sector volume + if ( ! sector ) Fatal("CreateModule", "Sector volume not found!"); + + // --- Get size of sector + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + + // --- Get size of cable + Double_t cableX = sectorX; + Double_t cableY = cableLength; + Double_t cableZ = gkCableThickness; + + // --- Create module volume + Double_t moduleX = TMath::Max(sectorX, cableX); + Double_t moduleY = sectorY + cableLength; + + Double_t moduleZ = TMath::Max(sectorZ, cableZ); + + TGeoVolume* module = gGeoManager->MakeBox(name, gStsMedium, + moduleX/2., + moduleY/2., + moduleZ/2.); + + // --- Position of sector in module + // --- Sector is centred in x and z and aligned to the bottom + Double_t sectorXpos = 0.; + Double_t sectorYpos = 0.5 * (sectorY - moduleY); + Double_t sectorZpos = 0.; + + + // --- Get sensor(s) from sector + Int_t nSensors = sector->GetNdaughters(); + for (Int_t iSensor = 0; iSensor < nSensors; iSensor++) { + TGeoNode* sensor = sector->GetNode(iSensor); + + // --- Calculate position of sensor in module + const Double_t* xSensTrans = sensor->GetMatrix()->GetTranslation(); + Double_t sensorXpos = 0.; + Double_t sensorYpos = sectorYpos + xSensTrans[1]; + Double_t sensorZpos = 0.; + TGeoTranslation* sensTrans = new TGeoTranslation("sensTrans", + sensorXpos, + sensorYpos, + sensorZpos); + + // --- Add sensor volume to module + TGeoVolume* sensVol = sensor->GetVolume(); + module->AddNode(sensor->GetVolume(), iSensor+1, sensTrans); + module->GetShape()->ComputeBBox(); + } + + + // --- Create cable volume, if necessary, and place it in module + // --- Cable is centred in x and z and aligned to the top + if ( gkConstructCables && cableLength > 0.0001 ) { + TString cableName = TString(name) + "_cable"; + TGeoMedium* cableMedium = gGeoMan->GetMedium("STScable"); + if ( ! cableMedium ) Fatal("CreateModule", "Medium STScable not found!"); + TGeoVolume* cable = gGeoManager->MakeBox(cableName.Data(), + cableMedium, + cableX / 2., + cableY / 2., + cableZ / 2.); + // add color to cables + cable->SetLineColor(kOrange); + cable->SetTransparency(60); + Double_t cableXpos = 0.; + Double_t cableYpos = sectorY + 0.5 * cableY - 0.5 * moduleY; + Double_t cableZpos = 0.; + TGeoTranslation* cableTrans = new TGeoTranslation("cableTrans", + cableXpos, + cableYpos, + cableZpos); + module->AddNode(cable, 1, cableTrans); + module->GetShape()->ComputeBBox(); + } + + return module; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a half ladder + ** + ** A half ladder is a virtual volume (TGeoVolumeAssembly) consisting + ** of several modules arranged on top of each other. The modules + ** have a given overlap in y and a displacement in z to allow for the + ** overlap. + ** + ** The typ of sectors / modules to be placed must be specified: + ** 1 = sensor01 + ** 2 = sensor02 + ** 3 = sensor03 + ** 4 = sensor04 + ** 5 = 2 x sensor04 (chained) + ** 6 = 3 x sensor04 (chained) + ** The cable is added automatically from the top of each sensor to + ** the top of the half ladder. + ** The alignment can be left (l) or right (r), which matters in the + ** case of different x sizes of sensors (e.g. SensorType01). + ** + ** Arguments: + ** name volume name + ** nSectors number of sectors + ** sectorTypes array with sector types + ** align horizontal alignment of sectors + * ladderLength full length of the ladder towards FEE + * offsetY gap in the beam-pipe region + **/ +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY) { + + // --- Create half ladder volume assembly + TGeoVolumeAssembly* halfLadder = new TGeoVolumeAssembly(name); + + // --- Determine size of ladder + Double_t ladderX = 0.; + Double_t ladderY = 0.; + Double_t ladderZ = 0.; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + if ( ! sector ) + Fatal("ConstructHalfLadder", Form("Volume %s not found", sectorName.Data())); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + // --- Ladder x size equals largest sector x size + ladderX = TMath::Max(ladderX, 2. * box->GetDX()); + // --- Ladder y size is sum of sector ysizes + ladderY += 2. * box->GetDY(); + // --- Ladder z size is sum of sector z sizes + ladderZ += 2. * box->GetDZ(); + } + // --- Subtract overlaps in y + ladderY -= Double_t(nSectors-1) * gkSectorOverlapY; + // --- Add gaps in z direction + ladderZ += Double_t(nSectors-1) * gkSectorGapZ; + + ladderY = TMath::Max(ladderLength - offsetY, ladderY); + + // --- Create and place modules + Double_t yPosSect = -0.5 * ladderY; + Double_t zPosMod = -0.5 * ladderZ; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + yPosSect += 0.5 * sectorY; // Position of sector in ladder + Double_t cableLength = 0.5 * ladderY - yPosSect - 0.5 * sectorY; + TString moduleName = name + "_" + Form("Module%02d", + sectorTypes[iSector]); + TGeoVolume* module = ConstructModule(moduleName.Data(), + sector, cableLength); + + TGeoBBox* shapeMod = (TGeoBBox*) module->GetShape(); + Double_t moduleX = 2. * shapeMod->GetDX(); + Double_t moduleY = 2. * shapeMod->GetDY(); + Double_t moduleZ = 2. * shapeMod->GetDZ(); + Double_t xPosMod = 0.; + if ( align == 'l' ) + xPosMod = 0.5 * (moduleX - ladderX); // left aligned + else if ( align == 'r' ) + xPosMod = 0.5 * (ladderX - moduleX); // right aligned + else + xPosMod = 0.; // centred in x + Double_t yPosMod = 0.5 * (ladderY - moduleY); // top aligned + zPosMod += 0.5 * moduleZ; + TGeoTranslation* trans = new TGeoTranslation("t", xPosMod, + yPosMod, zPosMod); + halfLadder->AddNode(module, iSector+1, trans); + halfLadder->GetShape()->ComputeBBox(); + yPosSect += 0.5 * sectorY - gkSectorOverlapY; + zPosMod += 0.5 * moduleZ + gkSectorGapZ; + } + + CheckVolume(halfLadder); + cout << endl; + + return halfLadder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Add a carbon support to a ladder + ** + ** Arguments: + ** LadderIndex ladder number + ** ladder pointer to ladder + ** xu size of halfladder + ** ladderY height of ladder along y + ** ladderZ thickness of ladder along z + **/ +void AddCarbonLadder(Int_t LadderIndex, + TGeoVolume* ladder, + Double_t xu, + Double_t ladderY, + Double_t ladderZ) { + + // --- Some variables + TString name = Form("LadderType%04d", LadderIndex); // v19k + Int_t i; + Double_t j; + + Int_t YnumOfFrameBoxes = round(ladderY / gkFrameStep); + + // cout << "DEXZ: lad " << LadderIndex << " inum " << YnumOfFrameBoxes << endl; + + Double_t ladderDZ = (xu/2. + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2)/2.; + cout << "DEFR: frame Z size " << 2 * ladderDZ << " cm" << endl; + + TGeoBBox* fullFrameShp = new TGeoBBox (name+"_CarbonElement_shp", xu/2., gkFrameStep/2., ladderDZ); + TGeoVolume* fullFrameBoxVol = new TGeoVolume(name+"_CarbonElement", fullFrameShp, gStsMedium); + + ConstructFrameElement("CarbonElement", fullFrameBoxVol, xu/2.); + TGeoRotation* fullFrameRot = new TGeoRotation; + fullFrameRot->RotateY(180); + + Int_t inum = YnumOfFrameBoxes; + for (i=1; i<=inum; i++) + { + j=-(inum-1)/2.+(i-1); + // -(10-1)/2. +0 +10-1 -> -4.5 .. +4.5 -> -0.5, +0.5 (= 2) + // -(11-1)/2. +0 +11-1 -> -5.0 .. +5.0 -> -1, 0, 1 (= 3) + // cout << "DE: i " << i << " j " << j << endl; + + if (LadderIndex % 100 <= 3) // central ladders in stations 1 to 3 + { + if ((j>=-1) && (j<=1)) // keep the inner 2 (even) or 3 (odd) elements free for the cone + continue; + } + else if (LadderIndex % 100 <= 8) // central ladders in stations 4 to 8 + { + if ((j>=-2) && (j<=2)) // keep the inner 4 elements free for the cone + continue; + } + + cout << "DELZ: ladderDZ " << ladderDZ << " cm " << -ladderZ/2. - ladderDZ << " cm " << endl; + ladder->AddNode(fullFrameBoxVol, i, new TGeoCombiTrans(name+"_CarbonElement_posrot", 0., j*gkFrameStep, -(ladderZ/2.+ladderDZ), fullFrameRot)); + } + + ladder->GetShape()->ComputeBBox(); + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Construct a ladder out of two half ladders with vertical gap + ** + ** The second half ladder will be rotated by 180 degrees + ** in the x-y plane. The two half ladders will be put on top of each + ** other with a vertical gap. + ** + ** Arguments: + ** name volume name + ** halfLadderU pointer to upper half ladder + ** halfLadderD pointer to lower half ladder + ** gapY vertical gap + ** shiftZ relative displacement along the z axis + **/ + + TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ) { + + // --- Some variables + TGeoBBox* shape = NULL; + + // --- Dimensions of half ladders + shape = (TGeoBBox*) halfLadderU->GetShape(); + Double_t xu = 2. * shape->GetDX(); + Double_t yu = 2. * shape->GetDY(); + Double_t zu = 2. * shape->GetDZ(); + + shape = (TGeoBBox*) halfLadderD->GetShape(); + Double_t xd = 2. * shape->GetDX(); + Double_t yd = 2. * shape->GetDY(); + Double_t zd = 2. * shape->GetDZ(); + + + // --- Create ladder volume assembly + +// TString name = Form("LadderType%02d", LadderIndex); // v19a +// TString name = Form("LadderType%03d", LadderIndex); // v19b + TString name = Form("LadderType%04d", LadderIndex); // v19k + TGeoVolumeAssembly* ladder = new TGeoVolumeAssembly(name); + Double_t ladderX = TMath::Max(xu, xd); + Double_t ladderY = yu + yd + gapY; + Double_t ladderZ = TMath::Max(zu, zd + shiftZ); + + // --- Place half ladders + Double_t xPosU = 0.; // centred in x + Double_t yPosU = 0.5 * ( ladderY - yu ); // top aligned + Double_t zPosU = 0.5 * ( ladderZ - zu ); // front aligned // mount upper half ladder last + if (LadderIndex >= 1000) zPosU = -zPosU; // back aligned // mount upper half ladder first + + TGeoTranslation* tu = new TGeoTranslation("tu", xPosU, yPosU, zPosU); + ladder->AddNode(halfLadderU, 1, tu); + + Double_t xPosD = 0.; // centred in x + Double_t yPosD = 0.5 * ( yd - ladderY ); // bottom aligned + Double_t zPosD = 0.5 * ( zd - ladderZ ); // back aligned // mount lower half ladder first + if (LadderIndex >= 1000) zPosD = -zPosD; // front aligned // mount lower half ladder last + + TGeoRotation* rd = new TGeoRotation(); + rd->RotateZ(180.); + TGeoCombiTrans* cd = new TGeoCombiTrans(xPosD, yPosD, zPosD, rd); + ladder->AddNode(halfLadderD, 2, cd); + + ladder->GetShape()->ComputeBBox(); + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD0ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + cout << "DDDD ladder" << LadderIndex << endl; + cout << "DDDD1ladder" << LadderIndex << " ladderX " << ladderX << " ladderY " << ladderY << " ladderZ " << ladderZ << endl; + + // ---------------- Create and place frame boxes ------------------------ + + if (gkConstructFrames) + AddCarbonLadder(LadderIndex, ladder, ladderX, ladderY, ladderZ); + + // -------------------------------------------------------------------------- + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD2ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + return ladder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a unit + ** + ** The unit volume is the minimal box comprising all ladders + ** minus a tube accomodating the beam pipe. + ** + ** The ladders are arranged horizontally from left to right with + ** a given overlap in x. + ** Every second ladder is slightly displaced upstream from the centre + ** z plane and facing downstream, the others are slightly displaced + ** downstream and facing upstream (rotated around the y axis). + ** + ** Arguments: + ** name volume name + ** nLadders number of ladders + ** ladderTypes array of ladder types + **/ + + TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation) { + + Bool_t isFirstPartOfHalfUnit = kFALSE; + + // TString name = Form("Unit%02d", iUnit); // 0,1,2,3,4,5,6,7 - Unit00 missing in output + // TString name = Form("Unit%02d", iUnit+1); // 1,2,3,4,5,6,7,8 + + TGeoVolume* unit = gGeoMan->GetVolume(unitName[iUnit]); + if ( ! unit ) // if it does not yet exist, create a new one + { + unit = new TGeoVolumeAssembly(unitName[iUnit]); + isFirstPartOfHalfUnit = kTRUE; + } + + // --- Some local variables + TGeoBBox* ladderShape = NULL; + TGeoVolume* ladder = NULL; + TString ladderName; + Double_t subtractedVal; + + // --- Determine size of unit from ladders + Double_t statX = 0.; + // Double_t statY = 0.; + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { +// Int_t ladderType = ladderTypes[iLadder]%100; // v19a +// Int_t ladderType = ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100; // v19b + Int_t ladderType = ladderTypes[iLadder]; // v19k + +// if (iSide == 0) cout << "DWER " << ladderTypes[iLadder] << " " << ladderType << endl; + + if (ladderType > 0) + { +// ladderName = Form("LadderType%02d", ladderType); // v19a +// ladderName = Form("LadderType%03d", ladderType); // v19b + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + if ( ! ladder ) Fatal("ConstructUnit", + Form("Volume %s not found", ladderName.Data())); + ladderShape = (TGeoBBox*) ladder->GetShape(); + statX += 2. * ladderShape->GetDX(); + // statY = TMath::Max(statY, 2. * ladderShape->GetDY()); + } + else + statX += gkSensorSizeX; // empty ladder in unit + } + statX -= Double_t(nLadders-1) * gkLadderOverlapX; + +// if (iSide == 0) cout << "DWER -" << endl; + + // --- Place ladders in unit + cout << "xPos0: " << statX << endl; + Double_t xPos = -0.5 * statX; + cout << "xPos1: " << xPos << endl; + Double_t yPos = 0.; + Double_t zPos = 0.; + + Double_t maxdz = 0.; + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { // find maximum dz in this unit +// Int_t ladderType = ladderTypes[iLadder]%100; // v19a +// Int_t ladderType = ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100; // v19b + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { +// ladderName = Form("LadderType%02d", ladderType); // v19a +// ladderName = Form("LadderType%03d", ladderType); // v19b + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + if (maxdz < ladderShape->GetDZ()) + maxdz = ladderShape->GetDZ(); + } + } + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { +// Int_t ladderType = ladderTypes[iLadder]%100; // v19a +// Int_t ladderType = ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100; // v19b + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { +// ladderName = Form("LadderType%02d", ladderType); // v19a +// ladderName = Form("LadderType%03d", ladderType); // v19b + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + xPos += ladderShape->GetDX(); + cout << "xPos2: " << xPos << endl; + yPos = 0.; // vertically centred + TGeoRotation* rot = new TGeoRotation(); + + if (gkConstructFrames) + subtractedVal = ladderShape->GetDX() + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2; + else + subtractedVal = 0.; + + zPos = 0.5 * gkLadderGapZ + (2*maxdz-ladderShape->GetDZ()-subtractedVal/2.); // z-aligned ladders + +// v19a cout << "DE ladder" << ladderTypes[iLadder]%100 +// v19b cout << "DE ladder" << ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100 +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " dx: " << ladderShape->GetDX() + << " dy: " << ladderShape->GetDY() + << " dz: " << ladderShape->GetDZ() + << " max dz: " << maxdz << endl; + +// v19a cout << "DE ladder" << ladderTypes[iLadder]%100 +// v19b cout << "DE ladder" << ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100 +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " fra: " << gkFrameThickness/2. + << " sub: " << subtractedVal + << " zpo: " << zPos << endl << endl; + +// v19a if (ladderTypes[iLadder]/100 == 1) // flip some of the ladders to reproduce the CAD layout + if (ladderTypes[iLadder]/1000 == 1) // flip some of the ladders to reproduce the CAD layout + rot->RotateY(180.); + else + zPos = -zPos; + + if (!isFirstPartOfHalfUnit) + // zPos += 10; + zPos += 10.5; // v19d +// zPos += 11.0; // v19e + + TGeoCombiTrans* trans = new TGeoCombiTrans(xPos, yPos, zPos, rot); +// start +// cout << "DEEE** iLadder " << iLadder << " " << nLadders/2 << " " << nLadders << endl; + + if (iSide == 0) + { + if (iLadder < nLadders/2) // right side - only half unit -x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + else + { + if (iLadder >= nLadders/2) // left side - only half unit +x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + unit->GetShape()->ComputeBBox(); +// stop + xPos += ladderShape->GetDX() - gkLadderOverlapX; + cout << "xPos3: " << xPos << endl; + } + else + xPos += gkSensorSizeX - gkLadderOverlapX; + } + + return unit; + } +/** ======================================================================= **/ + + +/** =========================================================================== + ** Import and add the passive materials to the STS volume + **/ +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile) +{ + TString passiveName = TString("sts_passive_") + geoTag; + TString basePath = gSystem->Getenv("VMCWORKDIR"); + TString relPath = "/geometry/sts/passive/" + passiveName + ".gdml"; + TString passiveFileName = basePath + relPath; + infoFile << std::endl << std::endl; + infoFile << "Importing STS passive materials from GDML file '" << relPath << "'." << std::endl; + + TGDMLParse parser; + TGeoVolume* gdmlVolume = parser.GDMLReadFile(passiveFileName); + PostProcessGdml(gdmlVolume); + gdmlVolume->SetName(passiveName); + + TGeoTranslation* passiveTrans = new TGeoTranslation(0., 0., 4.68); + infoFile << "Passive assembly is translated for Z=4.68 cm downstream with respect to parent volume" << std::endl << std::endl; + + gdmlVolume->GetShape()->ComputeBBox(); + CheckVolume(gdmlVolume, infoFile); + + infoFile << std::endl; + for (Int_t iNode = 0; iNode < gdmlVolume->GetNdaughters(); iNode++) { + CheckVolume(gdmlVolume->GetNode(iNode)->GetVolume(), infoFile, kFALSE); + } + + stsVolume->AddNode(gdmlVolume, stsVolume->GetNdaughters(), passiveTrans, ""); +} + +/** =========================================================================== + ** Assign visual properties to the imported gdml volumes + **/ +void PostProcessGdml(TGeoVolume* gdmlVolume) +{ + const UInt_t kPOBColor = kRed-6; + const UInt_t kPOBTransparency = 0;// 5; + + const UInt_t kFEBColor = kOrange-6; + const UInt_t kFEBTransparency = 0;// 5; + + const UInt_t kUnitColor = kCyan-10; + const UInt_t kUnitTransparency = 0;// 5; + + const UInt_t kCfColor = kGray+3; + const UInt_t kCfTransparency = 0;// 10; + + // name <Color, Transparency> + std::map<std::string, std::tuple<UInt_t,UInt_t> > props { + { "passive_POB", std::tuple<UInt_t,UInt_t> {kPOBColor, kPOBTransparency} }, + { "passive_FEB", std::tuple<UInt_t,UInt_t> {kFEBColor, kFEBTransparency} }, + { "passive_unit", std::tuple<UInt_t,UInt_t> {kUnitColor, kUnitTransparency} }, + { "passive_Box_Wall", std::tuple<UInt_t,UInt_t> {kCfColor, kCfTransparency} }, + { "passive_Box_Wall_Front_CF2", std::tuple<UInt_t,UInt_t> {kCfColor-3, kCfTransparency} }, + }; + + // Match volume name and apply visual properties + const TObjArray* volumes = gGeoManager->GetListOfVolumes(); + for (auto& entry : props) { + TIter next(volumes); + TGeoVolume *vol = nullptr; + while ((vol=(TGeoVolume*)next())) { + if (TString(vol->GetName()).Contains(entry.first.c_str())) { + vol->SetLineColor(std::get<0>(entry.second)); + vol->SetTransparency(std::get<1>(entry.second)); + } + } + } +} + +/** =========================================================================== + ** Volume information for debugging + **/ +void CheckVolume(TGeoVolume* volume) { + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + cout << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) cout << ", assembly"; + else { + if ( volume->GetMedium() ) + cout << ", medium " << volume->GetMedium()->GetName(); + else cout << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + cout << endl; + if ( volume->GetNdaughters() ) { + cout << "Daughters: " << endl; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) { + TGeoNode* node = volume->GetNode(iNode); + TGeoBBox* shape = (TGeoBBox*) node->GetVolume()->GetShape(); + cout << setw(15) << node->GetName() << ", size " + << fixed << setprecision(3) + << setw(6) << 2. * shape->GetDX() << " x " + << setw(6) << 2. * shape->GetDY() << " x " + << setw(6) << 2. * shape->GetDZ() << ", position ( "; + TGeoMatrix* matrix = node->GetMatrix(); + const Double_t* pos = matrix->GetTranslation(); + cout << setfill(' '); + cout << fixed << setw(8) << pos[0] << ", " + << setw(8) << pos[1] << ", " + << setw(8) << pos[2] << " )" << endl; + } + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Volume information for output to file + **/ +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren) { + if ( ! file ) return; + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + file << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) file << ", assembly"; + else { + if ( volume->GetMedium() ) + file << ", medium " << volume->GetMedium()->GetName(); + else file << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + file << endl; + if ( volume->GetNdaughters() && listChildren) { + file << "Contains: "; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) + file << volume->GetNode(iNode)->GetVolume()->GetName() << " "; + file << endl; + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Calculate beam pipe outer radius for a given z + **/ +Double_t BeamPipeRadius(Double_t z) { + if ( z < gkPipeZ2 ) return gkPipeR1; + Double_t slope = (gkPipeR3 - gkPipeR2 ) / (gkPipeZ3 - gkPipeZ2); + return gkPipeR2 + slope * (z - gkPipeZ2); +} +/** ======================================================================= **/ + + + +/** ======================================================================= **/ +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + TGeoBBox* frameVertPillarShp; + + Double_t t = gkFrameThickness/2.; + + // --- Main vertical pillars +// TGeoBBox* frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, gkFrameStep/2., t); // square crossection, along y +// TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); +// frameVertPillarVol->SetLineColor(kGreen); +// frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoTranslation(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2.)); +// frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoTranslation(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkCylindricalFrames) + // TGeoBBox* frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", 0, t, gkFrameStep/2.); // circle crossection, along z + frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", gkCylinderDiaInner/2., gkCylinderDiaOuter/2., gkFrameStep/2.); // circle crossection, along z + else + frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, t, gkFrameStep/2.); // square crossection, along z + TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); + frameVertPillarVol->SetLineColor(kGreen); + + TGeoRotation* xRot90 = new TGeoRotation; + xRot90->RotateX(90.); + frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoCombiTrans(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoCombiTrans(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + + // TGeoRotation* vertRot = new TGeoRotation(name + "_vertpillar_rot_1", 90., 45., -90.); + TGeoRotation* vertRot = new TGeoRotation; + vertRot->RotateX(90.); + vertRot->RotateY(45.); + frameBoxVol->AddNode(frameVertPillarVol, 3, new TGeoCombiTrans(name + "_vertpillar_pos_3", 0., 0., (x-sqrt(2.)*t)/2., vertRot)); + + // --- Small horizontal pillar + // TGeoBBox* frameHorPillarShp = new TGeoBBox(name + "_horpillar_shape", x-2.*t, gkThinFrameThickness/2., gkThinFrameThickness/2.); + // TGeoVolume* frameHorPillarVol = new TGeoVolume(name + "_horpillar", frameHorPillarShp, framesMaterial); + // frameHorPillarVol->SetLineColor(kCyan); + // frameBoxVol->AddNode(frameHorPillarVol, 1, new TGeoTranslation(name + "_horpillar_pos_1", 0., -gkFrameStep/2.+gkThinFrameThickness/2., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkConstructSmallFrames) { + + // --- Small sloping pillars + TGeoPara* frameSlopePillarShp = new TGeoPara(name + "_slopepillar_shape", + (x-2.*t)/TMath::Cos(31.4/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., 31.4, 0., 90.); + TGeoVolume* frameSlopePillarVol = new TGeoVolume(name + "_slopepillar", frameSlopePillarShp, framesMaterial); + frameSlopePillarVol->SetLineColor(kCyan); + TGeoRotation* slopeRot = new TGeoRotation(name + "_slopepillar_rot_1", 0., 0., 31.4); + TGeoRotation* slopeRot2 = new TGeoRotation(name + "_slopepillar_rot_2", 0., 0., -31.4); + TGeoCombiTrans* slopeTrRot = new TGeoCombiTrans(name + "_slopepillar_posrot_1", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot); + TGeoCombiTrans* slopeTrRot2 = new TGeoCombiTrans(name + "_slopepillar_posrot_2", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot2); + + frameBoxVol->AddNode(frameSlopePillarVol, 1, slopeTrRot); + frameBoxVol->AddNodeOverlap(frameSlopePillarVol, 2, slopeTrRot2); + + + Double_t angl = 23.; + // --- Small sub pillar + TGeoPara* frameSubPillarShp = new TGeoPara(name + "_subpillar_shape", + (sqrt(2)*(x/2.-t)-t/2.)/TMath::Cos(angl/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., angl, 0., 90.); + TGeoVolume* frameSubPillarVol = new TGeoVolume(name + "_subpillar", frameSubPillarShp, framesMaterial); + frameSubPillarVol->SetLineColor(kMagenta); + + Double_t posZ = t * (1. - 3. / ( 2.*sqrt(2.) )); + + // one side of X direction + TGeoRotation* subRot1 = new TGeoRotation(name + "_subpillar_rot_1", 90., 45., -90.+angl); + TGeoCombiTrans* subTrRot1 = new TGeoCombiTrans(name + "_subpillar_posrot_1", -(-x/2.+t-t/(2.*sqrt(2.))), 1., posZ, subRot1); + + TGeoRotation* subRot2 = new TGeoRotation(name + "_subpillar_rot_2", 90., -90.-45., -90.+angl); + TGeoCombiTrans* subTrRot2 = new TGeoCombiTrans(name + "_subpillar_posrot_2", -(-x/2.+t-t/(2.*sqrt(2.))), -1., posZ, subRot2); + + // other side of X direction + TGeoRotation* subRot3 = new TGeoRotation(name + "_subpillar_rot_3", 90., 90.+45., -90.+angl); + TGeoCombiTrans* subTrRot3 = new TGeoCombiTrans(name + "_subpillar_posrot_3", -x/2.+t-t/(2.*sqrt(2.)), 1., posZ, subRot3); + + TGeoRotation* subRot4 = new TGeoRotation(name + "_subpillar_rot_4", 90., -45., -90.+angl); + TGeoCombiTrans* subTrRot4 = new TGeoCombiTrans(name + "_subpillar_posrot_4", -x/2.+t-t/(2.*sqrt(2.)), -1., posZ, subRot4); + + frameBoxVol->AddNode(frameSubPillarVol, 1, subTrRot1); + frameBoxVol->AddNode(frameSubPillarVol, 2, subTrRot2); + frameBoxVol->AddNode(frameSubPillarVol, 3, subTrRot3); + frameBoxVol->AddNode(frameSubPillarVol, 4, subTrRot4); + // frameBoxVol->GetShape()->ComputeBBox(); + } + + return frameBoxVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructSmallCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 6., 7.6, 6., 6.04, 0., 180.); +// TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + Double_t radius = 3.0; + Double_t thickness = 0.04; // 0.4 mm +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 3., 3.2, 3., 3.2, 0., 180.); + TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, radius, radius+thickness, radius, radius+thickness, 0., 180.); + TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + TGeoCombiTrans* M = new TGeoCombiTrans ("M"); + M->RotateX (45.); + M->SetDy (-5.575); + M->SetDz (6.935); + M->RegisterYourself(); + + TGeoShape* coneShp = new TGeoCompositeShape ("Cone_shp", "A-B:M"); + TGeoVolume* coneVol = new TGeoVolume ("Cone", coneShp, framesMaterial); + coneVol->SetLineColor(kGreen); +// coneVol->RegisterYourself(); + +// // --- Inner cone +// Double_t thickness = 0.02; +// Double_t thickness2 = 0.022; +// // TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); +// TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 3.+thickness, 4.6-thickness2, 2.99+thickness, 3.05-thickness2, 0., 180.); +// +// TGeoCombiTrans* M2 = new TGeoCombiTrans ("M2"); +// M2->RotateX (45.); +// M2->SetDy (-5.575+thickness*sqrt(2.)); +// M2->SetDz (6.935); +// M2->RegisterYourself(); +// +// TGeoShape* coneShp2 = new TGeoCompositeShape ("Cone2_shp", "A2-B:M2"); +// TGeoVolume* coneVol2 = new TGeoVolume ("Cone2", coneShp2, gStsMedium); +// coneVol2->SetLineColor(kGreen); +//// coneVol2->RegisterYourself(); +// +// coneVol->AddNode(coneVol2, 1); + + return coneVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructBigCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone + TGeoConeSeg* bA = new TGeoConeSeg ("bA", coneDz, 6., 7.6, 6., 6.04, 0., 180.); + TGeoBBox* bB = new TGeoBBox ("bB", 8., 6., 10.); + + TGeoCombiTrans* bM = new TGeoCombiTrans ("bM"); + bM->RotateX (45.); + bM->SetDy (-5.575); + bM->SetDz (6.935); + bM->RegisterYourself(); + + TGeoShape* coneBigShp = new TGeoCompositeShape ("ConeBig_shp", "bA-bB:bM"); + TGeoVolume* coneBigVol = new TGeoVolume ("ConeBig", coneBigShp, framesMaterial); + coneBigVol->SetLineColor(kGreen); +// coneBigVol->RegisterYourself(); + + // --- Inner cone + Double_t thickness = 0.02; + Double_t thickness2 = 0.022; + TGeoConeSeg* bA2 = new TGeoConeSeg ("bA2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); + + TGeoCombiTrans* bM2 = new TGeoCombiTrans ("bM2"); + bM2->RotateX (45.); + bM2->SetDy (-5.575+thickness*sqrt(2.)); + bM2->SetDz (6.935); + bM2->RegisterYourself(); + + TGeoShape* coneBigShp2 = new TGeoCompositeShape ("ConeBig2_shp", "bA2-bB:bM2"); + TGeoVolume* coneBigVol2 = new TGeoVolume ("ConeBig2", coneBigShp2, gStsMedium); + coneBigVol2->SetLineColor(kGreen); +// coneBigVol2->RegisterYourself(); + + coneBigVol->AddNode(coneBigVol2, 1); + + return coneBigVol; +} + +/** ======================================================================= **/ diff --git a/macro/sts/geometry/create_stsgeo_v19o.C b/macro/sts/geometry/create_stsgeo_v19o.C new file mode 100644 index 0000000000000000000000000000000000000000..b9bbaa6d709fae81ca4359a1928130bf5afabda5 --- /dev/null +++ b/macro/sts/geometry/create_stsgeo_v19o.C @@ -0,0 +1,2375 @@ +/****************************************************************************** + ** Creation of STS geometry in ROOT format (TGeo). + ** + ** @file create_stsgeo_v19o.C + ** @author Volker Friese <v.friese@gsi.de> + ** @since 15 June 2012 + ** @date 09.05.2014 + ** @author Tomas Balog <T.Balog@gsi.de> + ** + ** v19o: based on v19k - parameters : delta Z prime = 0.30 cm - delta Z pitch = 0.20 cm + ** v19n: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.20 cm (bug fix of v19m) + ** v19m: based on v19k - parameters : delta Z prime = 0.55 cm - delta Z pitch = 0.20 cm (bug) + ** v19l: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.15 cm + ** v19k: ladders on upstream side of units get upper half ladders installed first, + ** ladders on downstream side of units get lower half ladders installed first, + ** this saves 1.5 mm space in z per station, 12 mm in total (LadderType went from 3 to 4 digits) + ** parameters : delta Z prime = 1.00 cm - delta Z pitch = 0.15 cm + ** v19j: use overlap and distance parameters from CAD model + ** v19h: put STS stations from v19d at z-positions = 260; 365; 470; 575; 680; 785; 890; 995 mm + ** v19g: place a box with services around v19e + ** v19f: place a box with services around v19d + ** v19e: increase spacing between stations by +10 mm from 100 mm + ** v19d: increase spacing between stations by + 5 mm from 100 mm + ** v19c: drop station 8 and increase spacing between remaining 7 stations from 10 cm to 12 c + ** v19b: introduce FEB orientation in ladder numbering (LadderType went from 2 to 3 digits) + ** v19a: import passive materials from gdml file + ** extend CF ladder structures and cables towards FEE plane + ** change CF ladder frame shape + ** v18d: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu (based on v18b) + ** v18c: fixed cut-out windows in cooling plates, improve the box shape/materials + ** v18b: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu + ** v18a: adds 9 cooling/holding plates and a box around the setup + ** v16g: v16g is the new standard geometry from November 2017 + ** v16g: switch from stations to units - left / right ("Unit01L", "Unit01R") + ** v16f: switch from stations to units + ** - split in upstream / downstream and left / right parts + ** - named Unit0xUR, Unit0xUL, Unit0xDR, Unit0xDL + ** v16e: switch from stations to units - upstream / downstream ("Unit01U", "Unit01D") + ** v16d: skip keeping volumes of sts and stations + ** v16c: like v16b, but senors of ladders beampipe next to beampipe + ** shifted closer to the pipe, like in the CAD model + ** v16b: like v16a, but yellow sensors removed + ** v16a: derived from v15c (no cones), but with sensor types renamed: + ** 2 -> 1, 3 -> 2, 4 -> 3, 5 -> 4, 1 -> 5 + ** + ** v15c: as v15b without cones + ** v15b: introduce modified carbon ladders from v13z + ** v15a: with flipped ladder orientation for stations 0,2,4,6 to match CAD design + ** + ** TODO: + ** + ** DONE: + ** v15b - use carbon macaroni as ladder support + ** v15b - introduce a small gap between lowest sensor and carbon ladder + ** v15b - build small cones for the first 2 stations + ** v15b - within a station the ladders of adjacent units should not touch eachother - set gkLadderGapZ to 10 mm + ** v15b - for all ladders set an even number of ladder elements + ** v15b - z offset of cones to ladders should not be 0.3 by default, but 0.26 + ** v15b - within a station the ladders should be aligned in z, defined either by the unit or the ladder with most sensors + ** v15b - get rid of cone overlap in stations 7 and 8 - done by adapting rHole size + ** + ** The geometry hierarachy is: + ** + ** 1. Sensors (see function CreateSensors) + ** The sensors are the active volumes and the lowest geometry level. + ** They are built as TGeoVolumes, shape box, material silicon. + ** x size is determined by strip pitch 58 mu and 1024 strips + ** plus guard ring of 1.3 mm at each border -> 6.1992 cm. + ** Sensor type 1 is half of that (3.0792 cm). + ** y size is determined by strip length (2.2 / 4.2 / 6.3 cm) plus + ** guard ring of 1.3 mm at top and bottom -> 2.46 / 4.46 / 6.46 cm. + ** z size is a parameter, to be set by gkSensorThickness. + ** + ** 2. Sectors (see function CreateSectors) + ** Sectors consist of several chained sensors. These are arranged + ** vertically on top of each other with a gap to be set by + ** gkChainGapY. Sectors are constructed as TGeoVolumeAssembly. + ** The sectors are auxiliary volumes used for proper placement + ** of the sensor(s) in the module. They do not show up in the + ** final geometry. + ** + ** 3. Modules (see function ConstructModule) + ** A module is a readout unit, consisting of one sensor or + ** a chain of sensors (see sector) and a cable. + ** The cable extends from the top of the sector vertically to the + ** top of the halfladder the module is placed in. The cable and module + ** volume thus depend on the vertical position of the sector in + ** the halfladder. The cables consist of silicon with a thickness to be + ** set by gkCableThickness. + ** Modules are constructed as TGeoVolume, shape box, medium gStsMedium. + ** The module construction can be switched off (gkConstructCables) + ** to reproduce older geometries. + ** + ** 4. Halfladders (see function ConstructHalfLadder) + ** A halfladder is a vertical assembly of several modules. The modules + ** are placed vertically such that their sectors overlap by + ** gkSectorOverlapY. They are displaced in z direction to allow for the + ** overlap in y by gkSectorGapZ. + ** The horizontal placement of modules in the halfladder can be choosen + ** to left aligned or right aligned, which only matters if sensors of + ** different x size are involved. + ** Halfladders are constructed as TGeoVolumeAssembly. + ** + ** 5. Ladders (see function CreateLadders and ConstructLadder) + ** A ladder is a vertical assembly of two halfladders, and is such the + ** vertical building block of a station. The second (bottom) half ladder + ** is rotated upside down. The vertical arrangement is such that the + ** inner sectors of the two halfladders have the overlap gkSectorOverlapY + ** (function CreateLadder) or that there is a vertical gap for the beam + ** hole (function CreateLadderWithGap). + ** Ladders are constructed as TGeoVolumeAssembly. + ** + ** 6. Stations (see function ConstructStation) + ** A station represents one layer of the STS geometry: one measurement + ** at (approximately) a given z position. It consist of several ladders + ** arranged horizontally to cover the acceptance. + ** The ladders are arranged such that there is a horizontal overlap + ** between neighbouring ladders (gkLadderOverLapX) and a vertical gap + ** to allow for this overlap (gkLadderGapZ). Each second ladder is + ** rotated around its y axis to face away from or into the beam. + ** Stations are constructed as TGeoVolumes, shape box minus tube (for + ** the beam hole), material gStsMedium. + ** + ** 7. STS + ** The STS is a volume hosting the entire detectors system. It consists + ** of several stations located at different z positions. + ** The STS is constructed as TGeoVolume, shape box minus cone (for the + ** beam pipe), material gStsMedium. The size of the box is computed to + ** enclose all stations. + *****************************************************************************/ + + +// Remark: With the proper steering variables, this should exactly reproduce +// the geometry version v11b of A. Kotynia's described in the ASCII format. +// The only exception is a minimal difference in the z position of the +// sectors/sensors. This is because of ladder types 2 and 4 containing the half +// sensors around the beam hole (stations 1,2 and 3). In v11b, the two ladders +// covering the beam hole cannot be transformed into each other by rotations, +// but only by a reflection. This means they are constructionally different. +// To avoid introducing another two ladder types, the difference in z position +// was accepted. + + +// Differences to v12: +// gkChainGap reduced from 1 mm to 0 +// gkCableThickness increased from 100 mum to 200 mum (2 cables per module) +// gkSectorOverlapY reduced from 3 mm to 2.4 mm +// New sensor types 05 and 06 +// New sector types 07 and 08 +// Re-definiton of ladders (17 types instead of 8) +// Re-definiton of station from new ladders + + +#include <iomanip> +#include <iostream> +#include "TGeoManager.h" + +#include "TGeoTube.h" +#include "TGeoPara.h" +#include "TGeoCone.h" +#include "TGeoTrd2.h" +#include "TGeoCompositeShape.h" +#include "TGeoXtru.h" +#include "TGeoPhysicalNode.h" + +// forward declarations +Int_t CreateSensors(); +Int_t CreateSectors(); +Int_t CreateLadders(); +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength); +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY); +TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ); +TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation); +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile); +void PostProcessGdml(TGeoVolume* gdmlTop); +void CheckVolume(TGeoVolume* volume); +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren = kTRUE); +Double_t BeamPipeRadius(Double_t z); +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x); +TGeoVolume* ConstructSmallCone(Double_t coneDz); +TGeoVolume* ConstructBigCone(Double_t coneDz); + +// ------------- Version highlight ----------------------------------- + +const std::string gVersionHighlight = R"( +Summary: + This version adds passive materials imported from GDML model to the STS geometry: + * Taken from and largely correspond to mechanical CAD drawings of the detector + * Thermal insulation box: + - made out of carbon sandwitch panel (2mm carbon fiber sheet + layer of carbon foam + 2mm carbon fiber sheet) + - front window of complex shape with interface to MVD / target chamber + - back window with large aperture (2000 x 1200 mm) square cut into carbon foam + * Structural units: + - made of 2 complex shape aluminum C-Frames, 15mm thick + - placed at 25, 35, ... ,105 cm absolute Z + - contain front-end and power distribution boxes with equivalent X_0 values + + Scripted geometry tweaks: + * Ladders and cables are extended towards the read-out planes having same lengths in respective rows + * Adjusted form and shape of carbon ladder structures from L-type to X-type + * Reduced verbosity of this file + + Sensor arrangement is the same as in version v16g + + !! Important for this version is the discrepancy from the mechanical CAD w.r.t. front wall. + The square window was replaced by a round one to avoid overlaps with present beam pipe designs, e.g. pipe_v16b_1e +)"; + +// ------------- Steering variables ----------------------------------- + +// ---> Horizontal width of sensors [cm] +const Double_t gkSensorSizeX = 6.2; // was 6.2092; // 6.2 - Oleg CAD 15/05/2020 + +// ---> Thickness of sensors [cm] +const Double_t gkSensorThickness = 0.03; + +// ---> Vertical gap between chained sensors [cm] +const Double_t gkChainGapY = 0.00; + +// ---> Thickness of cables [cm] +const Double_t gkCableThickness = 0.02; + +// ---> Horizontal overlap of neighbouring ladders [cm] +const Double_t gkLadderOverlapX = 0.25; // delta X - Oleg CAD 14/05/2020 + +// ---> Vertical overlap of neighbouring sectors in a ladder [cm] +const Double_t gkSectorOverlapY = 0.46; // delta Y - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring sectors in a ladder [cm] +const Double_t gkSectorGapZ = 0.17; // gap + thickness = pitch // delta Z pitch = 0.20 - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring ladders [cm] +const Double_t gkLadderGapZ = 0.30 - 0.20; // for asym // 0.5 for sym // delta Z prime + +// ---> Gap in z between lowest sector to carbon support structure [cm] +const Double_t gkSectorGapZFrame = 0.280 - 0.025; // Oleg CAD 05/05/2020 // there is a 2.8 mm gap between the bottom side of the sensor and the top ledge of the carbon ladder + +// ---> Switch to construct / not to construct readout cables +const Bool_t gkConstructCables = kTRUE; + +// ---> Switch to construct / not to construct frames +const Bool_t gkConstructCones = kFALSE; // kTRUE; // switch this false by default for v15c and v16x +const Bool_t gkConstructFrames = kTRUE; // kFALSE; // switch this true by default for v15c and v16x +const Bool_t gkConstructSmallFrames = kTRUE; // kFALSE; +const Bool_t gkCylindricalFrames = kTRUE; // kFALSE; + +// ---> Size of the frame +const Double_t gkFrameThickness = 0.2; +const Double_t gkThinFrameThickness = 0.05; +const Double_t gkFrameStep = 4.0; // size of frame cell along y direction + +const Double_t gkCylinderDiaInner = 0.07; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) +const Double_t gkCylinderDiaOuter = 0.15; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) + +// ---> Switch to import / not to import the Passive materials from GDML file +//const Bool_t gkImportPassive = kTRUE; +const Bool_t gkImportPassive = kFALSE; + +// ---------------------------------------------------------------------------- + + +// -------------- Parameters of beam pipe in the STS region -------------- +// ---> Needed to compute stations and STS such as to avoid overlaps +const Double_t gkPipeZ1 = 22.0; +const Double_t gkPipeR1 = 1.8; +const Double_t gkPipeZ2 = 50.0; +const Double_t gkPipeR2 = 1.8; +const Double_t gkPipeZ3 = 125.0; +const Double_t gkPipeR3 = 5.5; + +//DE const Double_t gkPipeZ1 = 27.0; +//DE const Double_t gkPipeR1 = 1.05; +//DE const Double_t gkPipeZ2 = 160.0; +//DE const Double_t gkPipeR2 = 3.25; +// ---------------------------------------------------------------------------- + +//TString unitName[16] = // names of units for v16e +// { "Unit00D", +// "Unit01U", "Unit01D", +// "Unit02U", "Unit02D", +// "Unit03U", "Unit03D", +// "Unit04U", "Unit04D", +// "Unit05U", "Unit05D", +// "Unit06U", "Unit06D", +// "Unit07U", "Unit07D", +// "Unit08U" }; + +//TString unitName[32] = // names of units for v16f +// { "Unit00DR", "Unit00DL", +// "Unit01UR", "Unit01UL", "Unit01DR", "Unit01DL", +// "Unit02UR", "Unit02UL", "Unit02DR", "Unit02DL", +// "Unit03UR", "Unit03UL", "Unit03DR", "Unit03DL", +// "Unit04UR", "Unit04UL", "Unit04DR", "Unit04DL", +// "Unit05UR", "Unit05UL", "Unit05DR", "Unit05DL", +// "Unit06UR", "Unit06UL", "Unit06DR", "Unit06DL", +// "Unit07UR", "Unit07UL", "Unit07DR", "Unit07DL", +// "Unit08UR", "Unit08UL" }; + +TString unitName[32] = // names of units for v16g - while merging D and U parts + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", "Unit01R", "Unit01L", + "Unit02R", "Unit02L", "Unit02R", "Unit02L", + "Unit03R", "Unit03L", "Unit03R", "Unit03L", + "Unit04R", "Unit04L", "Unit04R", "Unit04L", + "Unit05R", "Unit05L", "Unit05R", "Unit05L", + "Unit06R", "Unit06L", "Unit06R", "Unit06L", + "Unit07R", "Unit07L", "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +TString unitName18[18] = // names of units for v16g + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", + "Unit02R", "Unit02L", + "Unit03R", "Unit03L", + "Unit04R", "Unit04L", + "Unit05R", "Unit05L", + "Unit06R", "Unit06L", + "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +// ------------- Other global variables ----------------------------------- +// ---> STS medium (for every volume except silicon) +TGeoMedium* gStsMedium = NULL; // will be set later +// ---> TGeoManager (too lazy to write out 'Manager' all the time +TGeoManager* gGeoMan = NULL; // will be set later +// ---------------------------------------------------------------------------- + + + + +// ============================================================================ +// ====== Main function ===== +// ============================================================================ + +void create_stsgeo_v19o(const char* geoTag="v19o") +{ + + // ------- Geometry file name (output) ---------------------------------- + TString geoFileName = "sts_"; + geoFileName = geoFileName + geoTag + ".geo.root"; + // -------------------------------------------------------------------------- + + + // ------- Open info file ----------------------------------------------- + TString infoFileName = geoFileName; + infoFileName.ReplaceAll("root", "info"); + fstream infoFile; + infoFile.open(infoFileName.Data(), fstream::out); + infoFile << "STS geometry created with create_stsgeo_v19o.C" << endl; + infoFile << gVersionHighlight << endl; + infoFile << "Global variables: " << endl; + infoFile << "Sensor thickness = " << gkSensorThickness << " cm" << endl; + infoFile << "Vertical gap in sensor chain = " + << gkChainGapY << " cm" << endl; + infoFile << "Vertical overlap of sensors = " + << gkSectorOverlapY << " cm" << endl; + infoFile << "Gap in z between neighbour sensors = " + << gkSectorGapZ << " cm" << endl; + infoFile << "Horizontal overlap of sensors = " + << gkLadderOverlapX << " cm" << endl; + infoFile << "Gap in z between neighbour ladders = " + << gkLadderGapZ << " cm" << endl; + if ( gkConstructCables ) + infoFile << "Cable thickness = " << gkCableThickness << " cm" << endl; + else + infoFile << "No cables" << endl; + infoFile << endl; + infoFile << "Beam pipe: R1 = " << gkPipeR1 << " cm at z = " + << gkPipeZ1 << " cm" << endl; + infoFile << "Beam pipe: R2 = " << gkPipeR2 << " cm at z = " + << gkPipeZ2 << " cm" << endl; + infoFile << "Beam pipe: R3 = " << gkPipeR3 << " cm at z = " + << gkPipeZ3 << " cm" << endl; + // -------------------------------------------------------------------------- + + + // ------- Load media from media file ----------------------------------- + FairGeoLoader* geoLoad = new FairGeoLoader("TGeo","FairGeoLoader"); + FairGeoInterface* geoFace = geoLoad->getGeoInterface(); + TString geoPath = gSystem->Getenv("VMCWORKDIR"); + TString medFile = geoPath + "/geometry/media.geo"; + geoFace->setMediaFile(medFile); + geoFace->readMedia(); + gGeoMan = gGeoManager; + // -------------------------------------------------------------------------- + + + // ----------------- Get and create the required media ----------------- + FairGeoMedia* geoMedia = geoFace->getMedia(); + FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder(); + + // ---> air + FairGeoMedium* mAir = geoMedia->getMedium("air"); + if ( ! mAir ) Fatal("Main", "FairMedium air not found"); + geoBuild->createMedium(mAir); + TGeoMedium* air = gGeoMan->GetMedium("air"); + if ( ! air ) Fatal("Main", "Medium air not found"); + + // ---> silicon + FairGeoMedium* mSilicon = geoMedia->getMedium("silicon"); + if ( ! mSilicon ) Fatal("Main", "FairMedium silicon not found"); + geoBuild->createMedium(mSilicon); + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + if ( ! silicon ) Fatal("Main", "Medium silicon not found"); + + // ---> carbon + FairGeoMedium* mCarbon = geoMedia->getMedium("carbon"); + if ( ! mCarbon ) Fatal("Main", "FairMedium carbon not found"); + geoBuild->createMedium(mCarbon); + TGeoMedium* carbon = gGeoMan->GetMedium("carbon"); + if ( ! carbon ) Fatal("Main", "Medium carbon not found"); + + // ---> STSBoxCarbonFoam + FairGeoMedium* mSTSBoxCarbonFoam = geoMedia->getMedium("STSBoxCarbonFoam"); + if ( ! mSTSBoxCarbonFoam ) Fatal("Main", "FairMedium STSBoxCarbonFoam not found"); + geoBuild->createMedium(mSTSBoxCarbonFoam); + TGeoMedium* STSBoxCarbonFoam = gGeoMan->GetMedium("STSBoxCarbonFoam"); + if ( ! STSBoxCarbonFoam ) Fatal("Main", "Medium STSBoxCarbonFoam not found"); + + // ---> STSBoxCarbonFibre + FairGeoMedium* mSTSBoxCarbonFibre = geoMedia->getMedium("STSBoxCarbonFibre"); + if ( ! mSTSBoxCarbonFibre ) Fatal("Main", "FairMedium STSBoxCarbonFibre not found"); + geoBuild->createMedium(mSTSBoxCarbonFibre); + TGeoMedium* STSBoxCarbonFibre = gGeoMan->GetMedium("STSBoxCarbonFibre"); + if ( ! STSBoxCarbonFibre ) Fatal("Main", "Medium STSBoxCarbonFibre not found"); + + // ---> STScable + FairGeoMedium* mSTScable = geoMedia->getMedium("STScable"); + if ( ! mSTScable ) Fatal("Main", "FairMedium STScable not found"); + geoBuild->createMedium(mSTScable); + TGeoMedium* STScable = gGeoMan->GetMedium("STScable"); + if ( ! STScable ) Fatal("Main", "Medium STScable not found"); + + // ---> Aluminium + FairGeoMedium* mAluminium = geoMedia->getMedium("aluminium"); + if ( ! mAluminium ) Fatal("Main", "FairMedium aluminium not found"); + geoBuild->createMedium(mAluminium); + TGeoMedium* aluminium = gGeoMan->GetMedium("aluminium"); + if ( ! aluminium ) Fatal("Main", "Medium aluminium not found"); + + // --- + gStsMedium = air; + // -------------------------------------------------------------------------- + + + // -------------- Create geometry and top volume ------------------------- + gGeoMan = (TGeoManager*)gROOT->FindObject("FAIRGeom"); +// gGeoMan->SetName("STSgeom"); + TGeoVolume* top = new TGeoVolumeAssembly("top"); +// TGeoBBox* topbox= new TGeoBBox("", 120., 120., 120.); +// TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air")); + gGeoMan->SetTopVolume(top); + // -------------------------------------------------------------------------- + + + // -------------- Create media ------------------------------------------ + /* + cout << endl; + cout << "===> Creating media...."; + cout << CreateMedia(); + cout << " media created" << endl; + TList* media = gGeoMan->GetListOfMedia(); + for (Int_t iMedium = 0; iMedium < media->GetSize(); iMedium++ ) { + cout << "Medium " << iMedium << ": " + << ((TGeoMedium*) media->At(iMedium))->GetName() << endl; + } + gStsMedium = gGeoMan->GetMedium("air"); + if ( ! gStsMedium ) Fatal("Main", "medium sts_air not found"); + */ + // -------------------------------------------------------------------------- + + + // --------------- Create sensors --------------------------------------- + cout << endl << endl; + cout << "===> Creating sensors...." << endl << endl; + infoFile << endl << "Sensors: " << endl; + Int_t nSensors = CreateSensors(); + for (Int_t iSensor = 1; iSensor <= nSensors; iSensor++) { + TString name = Form("Sensor%02d",iSensor); + TGeoVolume* sensor = gGeoMan->GetVolume(name); + + // add color to sensors + if (iSensor == 1) + sensor->SetLineColor(kRed); + if (iSensor == 2) + sensor->SetLineColor(kGreen); + if (iSensor == 3) + sensor->SetLineColor(kBlue); + if (iSensor == 4) + sensor->SetLineColor(kAzure); + if (iSensor == 5) + sensor->SetLineColor(kYellow); + if (iSensor == 6) + sensor->SetLineColor(kYellow); + if (iSensor == 7) + sensor->SetLineColor(kYellow); + + CheckVolume(sensor); + CheckVolume(sensor, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create sectors -------------------------------------- + cout << endl << endl; + cout << "===> Creating sectors...." << endl; + // infoFile << endl << "Sectors: " << endl; + Int_t nSectors = CreateSectors(); + for (Int_t iSector = 1; iSector <= nSectors; iSector++) { + // cout << endl; + TString name = Form("Sector%02d", iSector); + TGeoVolume* sector = gGeoMan->GetVolume(name); + CheckVolume(sector); + // CheckVolume(sector, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create ladders -------------------------------------- + cout << endl << endl; + cout << "===> Creating ladders...." << endl; + infoFile << endl << "Ladders:" << endl; + + TString name = ""; + TGeoVolume* ladder; + + + Int_t nLadders = CreateLadders(); + + for (Int_t iLadder = 1; iLadder <= nLadders; iLadder++) { + cout << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType0%02d", iLadder); // v19b + name = Form("LadderType00%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF1: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType1%02d", iLadder); // v19b + name = Form("LadderType01%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF2: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType10%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF3: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType11%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF4: ladder name: " << name << endl << endl; + } + // -------------------------------------------------------------------------- + + + // ---------------- Create cones ---------------------------------------- + Double_t coneDz = 1.64; + TGeoVolume* coneSmallVolum = ConstructSmallCone(coneDz); + if (!coneSmallVolum) Fatal("ConstructSmallCone", "Volume Cone not found"); + TGeoVolume* coneBigVolum = ConstructBigCone(coneDz); + if (!coneBigVolum) Fatal("ConstructBigCone", "Volume Cone not found"); + // -------------------------------------------------------------------------- + + + // ---------------- Create stations ------------------------------------- + cout << endl << endl; + cout << "===> Creating stations...." << endl; + infoFile << endl << "Stations: " << endl; + Int_t angle = 0; + nLadders = 0; + Int_t ladderTypes[16]; // there are max 16 ladders in one layer + TGeoTranslation* statTrans = NULL; + + TGeoVolume *myunit[32]; // units + +// Int_t statPos[8] = { 30, 40, 50, 60, 70, 80, 90, 100 }; // z positions of stations +// Int_t statPos[16] = { 28, 32, 38, 42, 48, 52, 58, 62, +// 68, 72, 78, 82, 88, 92, 98,102 }; // z positions of units +// Int_t statPos[16] = { 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units +// Int_t statPos18[18] = { 30, 30, // expanded for placement of Unit00 +// 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units + // v19h + Double_t statPos[16] = { 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of units + Double_t statPos18[18] = { 26.0, 26.0, // expanded for placement of Unit00 + 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of unit + +// // v19d +// Double_t statPos[16] = { 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units +// Double_t statPos18[18] = { 30.0, 30.0, // expanded for placement of Unit00 +// 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units + +////Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.9 , 3.7 , 3.7 , 4.2 , 4.2 }; // size of cutouts in stations +// Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.43, 3.04, 3.35, 3.96, 4.2 }; // size of cutouts in stations, derived from gapXYZ[x][1]/2 + + Int_t cone_size[8] = { 0, 0, 0, 1, 1, 1, 1, 1 }; // size of cones: 0 = small, 1 = large + + Double_t cone_offset[2] = { 0.305, 0.285 }; + +// Int_t allLadderTypes[8][16]= +// { { -1, -1, -1, -1, 10, 109, 9, 101, 1, 109, 9, 110, -1, -1, -1, -1 }, // station 1 +// { -1, -1, 111, 10, 110, 9, 109, 2, 102, 9, 109, 10, 110, 11, -1, -1 }, // station 2 +// { -1, -1, 14, 113, 12, 112, 12, 103, 3, 112, 12, 112, 13, 114, -1, -1 }, // station 3 +// { -1, 15, 114, 13, 112, 12, 112, 4, 104, 12, 112, 12, 113, 14, 115, -1 }, // station 4 +// { -1, 119, 18, 117, 17, 116, 16, 105, 5, 116, 16, 117, 17, 118, 19, -1 }, // station 5 +// { -1, 19, 118, 17, 117, 16, 116, 6, 106, 16, 116, 17, 117, 18, 119, -1 }, // station 6 +// { 21, 119, 18, 120, 20, 120, 20, 107, 7, 120, 20, 120, 20, 118, 19, 121 }, // station 7 +// { 119, 17, 123, 22, 122, 22, 122, 8, 108, 22, 122, 22, 122, 23, 117, 19 } }; // station 8 + +//============================================================================================== + +// explanation: type xyzz +// where x = carbon ladder orientation +// where y = FEB box orientation +// where zz = sensor arrangement on ladder +// with FEB orientation - v19b + Int_t allUnitTypes[16][16]= + { { -1, -1, -1, -1, 10, 0, 9, 0, 101, 0, 109, 0, -1, -1, -1, -1 }, // unit00D Station01 00 + { -1, -1, -1, -1, 0, 1109, 0, 1101, 0, 1009, 0, 1010, -1, -1, -1, -1 }, // unit01U Station01 01 + + { -1, -1, 0, 10, 0, 9, 0, 2, 0, 109, 0, 110, 0, 111, -1, -1 }, // unit01D Station02 02 + { -1, -1, 1111, 0, 1110, 0, 1109, 0, 1002, 0, 1009, 0, 1010, 0, -1, -1 }, // unit02U Station02 03 + + { -1, -1, 14, 0, 12, 0, 12, 0, 103, 0, 112, 0, 113, 0, -1, -1 }, // unit02D Station03 04 + { -1, -1, 0, 1113, 0, 1112, 0, 1103, 0, 1012, 0, 1012, 0, 1014, -1, -1 }, // unit03U Station03 05 + + { -1, 15, 0, 13, 0, 12, 0, 4, 0, 112, 0, 112, 0, 114, 0, -1 }, // unit03D Station04 06 + { -1, 0, 1114, 0, 1112, 0, 1112, 0, 1004, 0, 1012, 0, 1013, 0, 1015, -1 }, // unit04U Station04 07 + + { -1, 0, 18, 0, 17, 0, 16, 0, 105, 0, 116, 0, 117, 0, 119, -1 }, // unit04D Station05 08 + { -1, 1119, 0, 1117, 0, 1116, 0, 1105, 0, 1016, 0, 1017, 0, 1018, 0, -1 }, // unit05U Station05 09 + + { -1, 19, 0, 17, 0, 16, 0, 6, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05D Station06 10 + { -1, 0, 1118, 0, 1117, 0, 1116, 0, 1006, 0, 1016, 0, 1017, 0, 1019, -1 }, // unit06U Station06 11 + + { 21, 0, 25, 0, 20, 0, 20, 0, 107, 0, 120, 0, 120, 0, 127, 0 }, // unit06D Station07 12 + { 0, 1127, 0, 1120, 0, 1120, 0, 1107, 0, 1020, 0, 1020, 0, 1025, 0, 1021 }, // unit07U Station07 13 + + { 0, 24, 0, 22, 0, 22, 0, 8, 0, 122, 0, 122, 0, 123, 0, 126 }, // unit07D Station08 14 + { 1126, 0, 1123, 0, 1122, 0, 1122, 0, 1008, 0, 1022, 0, 1022, 0, 1024, 0 } }; // unit08U Station08 15 + +//============================================================================================== + +// without FEB orientation - v19a +// v19a Int_t allUnitTypes[16][16]= +// v19a { { -1, -1, -1, -1, 10, 0, 9, 0, 1, 0, 9, 0, -1, -1, -1, -1 }, // unit00D Station01 00 +// v19a { -1, -1, -1, -1, 0, 109, 0, 101, 0, 109, 0, 110, -1, -1, -1, -1 }, // unit01U Station01 01 +// v19a { -1, -1, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, -1, -1 }, // unit01D Station02 02 +// v19a { -1, -1, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, -1, -1 }, // unit02U Station02 03 +// v19a { -1, -1, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, -1, -1 }, // unit02D Station03 04 +// v19a { -1, -1, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, -1, -1 }, // unit03U Station03 05 +// v19a { -1, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, -1 }, // unit03D Station04 06 +// v19a { -1, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, -1 }, // unit04U Station04 07 +// v19a { -1, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, -1 }, // unit04D Station05 08 +// v19a { -1, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05U Station05 09 +// v19a { -1, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, -1 }, // unit05D Station06 10 +// v19a { -1, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, -1 }, // unit06U Station06 11 +// v19a { 21, 0, 25, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 27, 0 }, // unit06D Station07 12 +// v19a { 0, 127, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 125, 0, 121 }, // unit07U Station07 13 +// v19a { 0, 24, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 26 }, // unit07D Station08 14 +// v19a { 126, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 124, 0 } }; // unit08U Station08 15 + + +// unitTypes[0] = { 0, 0, 0, 0, 10, 0, 9, 0, 1, 0, 9, 0, 0, 0, 0, 0 }; // unit 0D +// unitTypes[1] = { 0, 0, 0, 0, 0, 109, 0, 101, 0, 109, 0, 110, 0, 0, 0, 0 }; // unit 1U +// unitTypes[2] = { 0, 0, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, 0, 0 }; // unit 1D +// unitTypes[3] = { 0, 0, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, 0, 0 }; // unit 2U +// unitTypes[4] = { 0, 0, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, 0, 0 }; // unit 2D +// unitTypes[5] = { 0, 0, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, 0, 0 }; // unit 3U +// unitTypes[6] = { 0, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, 0 }; // unit 3D +// unitTypes[7] = { 0, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, 0 }; // unit 4U +// unitTypes[8] = { 0, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, 0 }; // unit 4D +// unitTypes[9] = { 0, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, 0 }; // unit 5U +// unitTypes[10] = { 0, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, 0 }; // unit 5D +// unitTypes[11] = { 0, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, 0 }; // unit 6U +// unitTypes[12] = { 21, 0, 18, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 19, 0 }; // unit 6D +// unitTypes[13] = { 0, 119, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 118, 0, 121 }; // unit 7U +// unitTypes[14] = { 0, 17, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 19 }; // unit 7D +// unitTypes[15] = { 119, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 117, 0 }; // unit 8U + + +// // generate unit +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) +// for (Int_t iLadder = 0; iLadder < 16; iLadder++) +// { +// allUnitTypes[iUnit][iLadder] = 0; +// if ((iUnit % 2 == 0) && (allLadderTypes[iUnit/2][iLadder] < 100)) // if carbon structure is oriented upstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// if ((iUnit % 2 == 1) && (allLadderTypes[iUnit/2][iLadder] >= 100)) // if carbon structure is oriented downstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// } + + + // dump unit + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << "DE unitTypes[" << iUnit << "] = { "; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + { + cout << allUnitTypes[iUnit][iLadder]; + if (iLadder < 15) + cout << ", "; + else + cout << " };"; + } + cout << endl; + } + + + // --- Units 01 - 16 + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << endl; + + nLadders = 0; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + if (allUnitTypes[iUnit][iLadder] >= 0) + { + ladderTypes[nLadders] = allUnitTypes[iUnit][iLadder]; + cout << "DE ladderTypes[" << nLadders << "] = " << allUnitTypes[iUnit][iLadder] << ";" << endl; + nLadders++; + } + myunit[iUnit*2+0] = ConstructUnit(0, iUnit*2+0, nLadders, ladderTypes, iUnit/2+1); + myunit[iUnit*2+1] = ConstructUnit(1, iUnit*2+1, nLadders, ladderTypes, iUnit/2+1); + +// if (gkConstructCones) { +// if (iUnit%2 == 0) +// angle = 90; +// else +// angle = -90; +// +// // upstream +// TGeoRotation* coneRot11 = new TGeoRotation; +// coneRot11->RotateZ(angle); +// coneRot11->RotateY(180); +// TGeoCombiTrans* conePosRot11 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-cone_offset[cone_size[iUnit]]-gkLadderGapZ/2., coneRot11); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 1, conePosRot11); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 1, conePosRot11); +// +// // downstream +// TGeoRotation* coneRot12 = new TGeoRotation; +// coneRot12->RotateZ(angle); +// TGeoCombiTrans* conePosRot12 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+cone_offset[cone_size[iUnit]]+gkLadderGapZ/2., coneRot12); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 2, conePosRot12); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 2, conePosRot12); +// +// myunit[iUnit]->GetShape()->ComputeBBox(); +// } + +// CheckVolume(myunit[iUnit]); +// CheckVolume(myunit[iUnit], infoFile); + if ((iUnit%2 == 0)||(iUnit == 15)) + { + CheckVolume(myunit[iUnit*2+0]); + CheckVolume(myunit[iUnit*2+0], infoFile); + CheckVolume(myunit[iUnit*2+1]); + CheckVolume(myunit[iUnit*2+1], infoFile); + } + infoFile << "Position z = " << statPos[iUnit] << endl; + } + // -------------------------------------------------------------------------- + + + // --------------- Create STS volume ------------------------------------ + cout << endl << endl; + cout << "===> Creating STS...." << endl; + +// // --- Determine size of STS box +// Double_t stsX = 0.; +// Double_t stsY = 0.; +// Double_t stsZ = 0.; +// Double_t stsBorder = 2*5.; // 5 cm space for carbon ladders on each side +// for (Int_t iStation = 1; iStation<=8; iStation++) { +// TString statName = Form("Station%02d", iStation); +// TGeoVolume* station = gGeoMan->GetVolume(statName); +// TGeoBBox* shape = (TGeoBBox*) station->GetShape(); +// stsX = TMath::Max(stsX, 2.* shape->GetDX() ); +// stsY = TMath::Max(stsY, 2.* shape->GetDY() ); +// cout << "Station " << iStation << ": Y " << stsY << endl; +// } +// // --- Some border around the stations +// stsX += stsBorder; +// stsY += stsBorder; +// stsZ = ( statPos[7] - statPos[0] ) + stsBorder; +// +// // --- Create box around the stations +// new TGeoBBox("stsBox", stsX/2., stsY/2., stsZ/2.); +// cout << "size of STS box: x " << stsX << " - y " << stsY << " - z " << stsZ << endl; +// +// // --- Create cone hosting the beam pipe +// // --- One straight section with constant radius followed by a cone +// Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +// Double_t z2 = gkPipeZ2; +// Double_t z3 = statPos[7] + 0.5 * stsBorder; // end of STS box +// Double_t r1 = BeamPipeRadius(z1); +// Double_t r2 = BeamPipeRadius(z2); +// Double_t r3 = BeamPipeRadius(z3); +// r1 += 0.01; // safety margin +// r2 += 0.01; // safety margin +// r3 += 0.01; // safety margin +// +// cout << endl; +// cout << z1 << " " << r1 << endl; +// cout << z2 << " " << r2 << endl; +// cout << z3 << " " << r3 << endl; +// +// cout << endl; +// cout << "station1 : " << BeamPipeRadius(statPos[0]) << endl; +// cout << "station2 : " << BeamPipeRadius(statPos[1]) << endl; +// cout << "station3 : " << BeamPipeRadius(statPos[2]) << endl; +// cout << "station4 : " << BeamPipeRadius(statPos[3]) << endl; +// cout << "station5 : " << BeamPipeRadius(statPos[4]) << endl; +// cout << "station6 : " << BeamPipeRadius(statPos[5]) << endl; +// cout << "station7 : " << BeamPipeRadius(statPos[6]) << endl; +// cout << "station8 : " << BeamPipeRadius(statPos[7]) << endl; +// +// // TGeoPcon* cutout = new TGeoPcon("stsCone", 0., 360., 3); // 2.*TMath::Pi(), 3); +// // cutout->DefineSection(0, z1, 0., r1); +// // cutout->DefineSection(1, z2, 0., r2); +// // cutout->DefineSection(2, z3, 0., r3); +// new TGeoTrd2("stsCone1", r1, r2, r1, r2, (z2-z1)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans1 = new TGeoTranslation("trans1", 0., 0., -(z3-z1)/2.+(z2-z1)/2.); +// trans1->RegisterYourself(); +// new TGeoTrd2("stsCone2", r2, r3, r2, r3, (z3-z2)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans2 = new TGeoTranslation("trans2", 0., 0., +(z3-z1)/2.-(z3-z2)/2.); +// trans2->RegisterYourself(); +// +////DE Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +////DE Double_t z2 = statPos[7] + 0.5 * stsBorder; // end of STS box +////DE Double_t slope = (gkPipeR2 - gkPipeR1) / (gkPipeZ2 - gkPipeZ1); +////DE Double_t r1 = gkPipeR1 + slope * (z1 - gkPipeZ1); // at start of STS +////DE Double_t r2 = gkPipeR1 + slope * (z2 - gkPipeZ1); // at end of STS +////DE r1 += 0.1; // safety margin +////DE r2 += 0.1; // safety margin +////DE // new TGeoCone("stsCone", stsZ/2., 0., r1, 0., r2); +////DE new TGeoTrd2("stsCone", r1, r2, r1, r2, stsZ/2.); + + + // // Create holding/cooling plates + // static std::vector< std::vector<Double_t> > plateSizes = { + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // }; + + // // 8-vertex cut-outs { minWidth, maxWidth, minHeight, maxHeight } + // static std::vector< std::vector<Double_t> > plateCutOuts = { + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 17.6, 47.6 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 49.0, 79.0 }, + // { 85.5,115.5, 51.5, 82.8 }, + // { 85.5,115.5, 59.0, 91.4 }, + // { 85.5,115.5, 68.0, 99.0 }, + // }; + + // for (Int_t iPlate = 0; iPlate < 9; iPlate++) { + // Int_t iUnit = iPlate * 2; + // TGeoBBox* outerPlate = new TGeoBBox(Form("outerPlate%02d",iPlate), + // plateSizes[iPlate][0], plateSizes[iPlate][1], plateSizes[iPlate][2]); + + // TGeoBBox* unitShapeR = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+0])->GetShape(); + // TGeoBBox* unitShapeL = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+1])->GetShape(); + + // Double_t maxDx = (unitShapeR->GetDX() + unitShapeL->GetDX()) / 2.; + // Double_t maxDy = TMath::Max(unitShapeR->GetDY(), unitShapeL->GetDY()); + // cout << maxDy << endl; + + // Double_t* cutOutX = new Double_t[8]; + // Double_t* cutOutY = new Double_t[8]; + + // cutOutX[0] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[0] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[1] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[1] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[2] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[2] = 1/2. * plateCutOuts[iPlate][2]; + // cutOutX[3] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[3] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[4] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[4] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[5] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[5] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[6] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[6] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[7] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[7] = 1/2. * plateCutOuts[iPlate][2]; + + // TGeoXtru* cutOutShape = new TGeoXtru(2); + // cutOutShape->SetName(Form("innerPlate%02d", iPlate)); + // cutOutShape->DefinePolygon(8, cutOutX, cutOutY); + // cutOutShape->DefineSection(0, -1*plateSizes[iPlate][2]-1e-7); + // cutOutShape->DefineSection(1, +1*plateSizes[iPlate][2]+1e-7); + + // TGeoShape* plateShape = new TGeoCompositeShape(Form("PlateShape%02d",iPlate), Form("outerPlate%02d-innerPlate%02d",iPlate,iPlate)); + // TGeoVolume* plate = new TGeoVolume(Form("Plate%02d", iPlate), plateShape, gGeoManager->GetMedium("aluminium")); + // plate->SetLineColor(kRed); + // plate->SetTransparency(65); + // plate->GetShape()->ComputeBBox(); + // } + + // --- Create STS volume + TString stsName = "sts_"; + stsName += geoTag; + +// TGeoShape* stsShape = new TGeoCompositeShape("stsShape", +// "stsBox-stsCone1:trans1-stsCone2:trans2"); +// TGeoVolume* sts = new TGeoVolume(stsName.Data(), stsShape, gStsMedium); + + Double_t stsBorder = 2 * 5.; + + TGeoVolume* sts = new TGeoVolumeAssembly(stsName.Data()); + + // --- Place stations in the STS + Double_t stsPosZ = 0.5 * ( statPos[15] + statPos[0] ); // todo units: update statPos[7] + // cout << "stsPosZ " << stsPosZ << " " << statPos[15] << " " << statPos[0] << "*****" << endl; + +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) { + for (Int_t iUnit = 0; iUnit < 18; iUnit++) { +// for (Int_t iUnit = 0; iUnit < 32; iUnit++) { + TGeoVolume* station = gGeoMan->GetVolume(unitName18[iUnit]); +// Double_t posZ = statPos[iUnit] - stsPosZ; + Double_t posZ = statPos18[iUnit] - stsPosZ; +// Double_t posZ = statPos[iUnit/2] - stsPosZ; + TGeoTranslation* trans = new TGeoTranslation(0., 0., posZ); + sts->AddNode(station, iUnit+1, trans); + sts->GetShape()->ComputeBBox(); + } + + // --- Import passive elements from GDML file + if (gkImportPassive) { + ImportPassive(sts, geoTag, infoFile); + } + + cout << endl; + CheckVolume(sts); + // -------------------------------------------------------------------------- + + + // --------------- Finish ----------------------------------------------- + TGeoTranslation* stsTrans = new TGeoTranslation(0., 0., stsPosZ); + top->AddNode(sts, 1, stsTrans); + top->GetShape()->ComputeBBox(); + cout << endl << endl; + + CheckVolume(top); + cout << endl << endl; + gGeoMan->CloseGeometry(); + gGeoMan->CheckOverlaps(0.0001); + gGeoMan->PrintOverlaps(); + gGeoMan->CheckOverlaps(0.0001, "s"); + gGeoMan->PrintOverlaps(); + gGeoMan->Test(); + + TFile* geoFile = new TFile(geoFileName, "RECREATE"); + top->Write(); + cout << endl; + cout << "Geometry " << top->GetName() << " written to " + << geoFileName << endl; + geoFile->Close(); + + TString geoFileName_ = "sts_"; + geoFileName_ = geoFileName_ + geoTag + "_geo.root"; + + geoFile = new TFile(geoFileName_, "RECREATE"); + gGeoMan->Write(); // use this is you want GeoManager format in the output + geoFile->Close(); + + TString geoFileName__ = "sts_"; + geoFileName_ = geoFileName__ + geoTag + "-geo.root"; + sts->Export(geoFileName_); + + geoFile = new TFile(geoFileName_, "UPDATE"); + stsTrans->Write(); + geoFile->Close(); + + // gGeoManager->FindVolumeFast("LadderType10_CarbonElement")->Draw("ogl"); + top->Draw("ogl"); + gGeoManager->SetVisLevel(8); + + infoFile.close(); + +} +// ============================================================================ +// ====== End of main function ===== +// ============================================================================ + + + + + +// **************************************************************************** +// ***** Definition of media, sensors, sectors and ladders ***** +// ***** ***** +// ***** Decoupled from main function for better readability ***** +// **************************************************************************** + + +/** =========================================================================== + ** Create media + ** + ** Currently created: air, active silicon, passive silion + ** + ** Not used for the time being + **/ +Int_t CreateMedia() { + + Int_t nMedia = 0; + Double_t density = 0.; + + // --- Material air + density = 1.205e-3; // [g/cm^3] + TGeoMixture* matAir = new TGeoMixture("sts_air", 3, density); + matAir->AddElement(14.0067, 7, 0.755); // Nitrogen + matAir->AddElement(15.999, 8, 0.231); // Oxygen + matAir->AddElement(39.948, 18, 0.014); // Argon + + // --- Material silicon + density = 2.33; // [g/cm^3] + TGeoElement* elSi = gGeoMan->GetElementTable()->GetElement(14); + TGeoMaterial* matSi = new TGeoMaterial("matSi", elSi, density); + + + // --- Air (passive) + TGeoMedium* medAir = new TGeoMedium("air", nMedia++, matAir); + medAir->SetParam(0, 0.); // is passive + medAir->SetParam(1, 1.); // is in magnetic field + medAir->SetParam(2, 20.); // max. field [kG] + medAir->SetParam(6, 0.001); // boundary crossing precision [cm] + + + // --- Active silicon for sensors + TGeoMedium* medSiAct = new TGeoMedium("silicon", + nMedia++, matSi); + medSiAct->SetParam(0, 1.); // is active + medSiAct->SetParam(1, 1.); // is in magnetic field + medSiAct->SetParam(2, 20.); // max. field [kG] + medSiAct->SetParam(6, 0.001); // boundary crossing precisison [cm] + + // --- Passive silicon for cables + TGeoMedium* medSiPas = new TGeoMedium("carbon", + nMedia++, matSi); + medSiPas->SetParam(0, 0.); // is passive + medSiPas->SetParam(1, 1.); // is in magnetic field + medSiPas->SetParam(2, 20.); // max. field [kG] + medSiPas->SetParam(6, 0.001); // boundary crossing precisison [cm] + + return nMedia; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sensors + ** + ** Sensors are created as volumes with box shape and active silicon as medium. + ** Four kinds of sensors: 3.2x2.2, 6.2x2.2, 6.2x4.2, 6.2x6.2 + **/ +Int_t CreateSensors() { + + Int_t nSensors = 0; + + Double_t xSize = 0.; + Double_t ySize = 0.; + Double_t zSize = gkSensorThickness; + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + + + // --- Sensor type 01: Small sensor (6.2 cm x 2.2 cm) + xSize = gkSensorSizeX; + ySize = 2.2; + TGeoBBox* shape_sensor01 = new TGeoBBox("sensor01", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor01", shape_sensor01, silicon); + nSensors++; + + + // --- Sensor type 02: Medium sensor (6.2 cm x 4.2 cm) + xSize = gkSensorSizeX; + ySize = 4.2; + TGeoBBox* shape_sensor02 = new TGeoBBox("sensor02", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor02", shape_sensor02, silicon); + nSensors++; + + + // --- Sensor type 03: Big sensor (6.2 cm x 6.2 cm) + xSize = gkSensorSizeX; + ySize = 6.2; + TGeoBBox* shape_sensor03 = new TGeoBBox("sensor03", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor03", shape_sensor03, silicon); + nSensors++; + + + // --- Sensor type 04: Big sensor (6.2 cm x 12.4 cm) + xSize = gkSensorSizeX; + ySize = 12.4; + TGeoBBox* shape_sensor04 = new TGeoBBox("sensor04", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor04", shape_sensor04, silicon); + nSensors++; + + + // below are extra small sensors, those are not available in the CAD model + + // --- Sensor Type 05: Half small sensor (4 cm x 2.5 cm) + xSize = 4.0; + ySize = 2.5; + TGeoBBox* shape_sensor05 = new TGeoBBox("sensor05", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor05", shape_sensor05, silicon); + nSensors++; + + + // --- Sensor type 06: Additional "in hole" sensor (3.1 cm x 4.2 cm) + xSize = 3.1; + ySize = 4.2; + TGeoBBox* shape_sensor06 = new TGeoBBox("sensor06", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor06", shape_sensor06, silicon); + nSensors++; + + + // --- Sensor type 07: Mini Medium sensor (1.5 cm x 4.2 cm) + xSize = 1.5; + ySize = 4.2; + TGeoBBox* shape_sensor07 = new TGeoBBox("sensor07", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor07", shape_sensor07, silicon); + nSensors++; + + + return nSensors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sectors + ** + ** A sector is either a single sensor or several chained sensors. + ** It is implemented as TGeoVolumeAssembly. + ** Currently available: + ** - single sensors of type 1 - 4 + ** - two chained sensors of type 4 + ** - three chained sensors of type 4 + **/ +Int_t CreateSectors() { + + Int_t nSectors = 0; + + TGeoVolume* sensor01 = gGeoMan->GetVolume("Sensor01"); + TGeoVolume* sensor02 = gGeoMan->GetVolume("Sensor02"); + TGeoVolume* sensor03 = gGeoMan->GetVolume("Sensor03"); + TGeoVolume* sensor04 = gGeoMan->GetVolume("Sensor04"); + TGeoVolume* sensor05 = gGeoMan->GetVolume("Sensor05"); + TGeoVolume* sensor06 = gGeoMan->GetVolume("Sensor06"); + TGeoVolume* sensor07 = gGeoMan->GetVolume("Sensor07"); + // TGeoBBox* box4 = (TGeoBBox*) sensor04->GetShape(); + + // --- Sector type 1: single sensor of type 1 + TGeoVolumeAssembly* sector01 = new TGeoVolumeAssembly("Sector01"); + sector01->AddNode(sensor01, 1); + sector01->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 2: single sensor of type 2 + TGeoVolumeAssembly* sector02 = new TGeoVolumeAssembly("Sector02"); + sector02->AddNode(sensor02, 1); + sector02->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 3: single sensor of type 3 + TGeoVolumeAssembly* sector03 = new TGeoVolumeAssembly("Sector03"); + sector03->AddNode(sensor03, 1); + sector03->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 4: single sensor of type 4 + TGeoVolumeAssembly* sector04 = new TGeoVolumeAssembly("Sector04"); + sector04->AddNode(sensor04, 1); + sector04->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 5: single sensor of type 5 + TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); + sector05->AddNode(sensor05, 1); + sector05->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 6: single sensor of type 6 + TGeoVolumeAssembly* sector06 = new TGeoVolumeAssembly("Sector06"); + sector06->AddNode(sensor06, 1); + sector06->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 7: single sensor of type 7 + TGeoVolumeAssembly* sector07 = new TGeoVolumeAssembly("Sector07"); + sector07->AddNode(sensor07, 1); + sector07->GetShape()->ComputeBBox(); + nSectors++; + +// // --- Sector type 5: two sensors of type 4 +// TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); +// Double_t shift5 = 0.5 * gkChainGapY + box4->GetDY(); +// TGeoTranslation* transD5 = +// new TGeoTranslation("td", 0., -1. * shift5, 0.); +// TGeoTranslation* transU5 = +// new TGeoTranslation("tu", 0., shift5, 0.); +// sector05->AddNode(sensor04, 1, transD5); +// sector05->AddNode(sensor04, 2, transU5); +// sector05->GetShape()->ComputeBBox(); +// nSectors++; + + return nSectors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create ladders + ** + ** Ladders are the building blocks of the stations. They contain + ** several modules placed one after the other along the z axis + ** such that the sectors are arranged vertically (with overlap). + ** + ** A ladder is constructed out of two half ladders, the second of which + ** is rotated in the x-y plane by 180 degrees and displaced + ** in z direction. + **/ +Int_t CreateLadders() { + + Int_t nLadders = 0; + + // --- Some variables + Int_t nSectors = 0; + Int_t sectorTypes[10]; + TGeoBBox* shape = NULL; + TString s0name; + TString hlname; + char align; + TGeoVolume* s0vol = NULL; + TGeoVolume* halfLadderU = NULL; + TGeoVolume* halfLadderD = NULL; + + // --- Ladders 01-23 + Int_t allSectorTypes[27][6] = { { 1, 2, 3, 3, 0, -1 }, // ladder 01 - 5 - last column defines alignment of small sensors + { 1, 2, 3, 3, 0, 0 }, // ladder 02 - 5 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, -1 }, // ladder 03 - 6 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 04 - 6 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, -1 }, // ladder 05 - 7 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 06 - 7 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 07 - last column defines alignment of small sensors + { 3, 4, 4, 4, 0, 0 }, // ladder 08 - last column defines alignment of small sensors + + { 1, 1, 2, 3, 3, 0 }, // ladder 09 - last column defines alignment of small sensors + { 1, 1, 2, 2, 3, 0 }, // ladder 10 - last column defines alignment of small sensors + { 2, 2, 0, 0, 0, 0 }, // ladder 11 - last column defines alignment of small sensors + { 2, 2, 2, 3, 4, 0 }, // ladder 12 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 13 - last column defines alignment of small sensors + + { 2, 3, 4, 0, 0, 0 }, // ladder 14 - last column defines alignment of small sensors + { 3, 3, 0, 0, 0, 0 }, // ladder 15 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 16 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 17 - last column defines alignment of small sensors + { 3, 4, 4, 0, 0, 0 }, // ladder 18 - last column defines alignment of small sensors + + { 4, 4, 0, 0, 0, 0 }, // ladder 19 - last column defines alignment of small sensors + { 1, 2, 4, 4, 4, 0 }, // ladder 20 - last column defines alignment of small sensors + { 4, 0, 0, 0, 0, 0 }, // ladder 21 - last column defines alignment of small sensors + { 2, 3, 4, 4, 4, 0 }, // ladder 22 - last column defines alignment of small sensors + { 2, 3, 3, 4, 4, 0 }, // ladder 23 - last column defines alignment of small sensors + + { 2, 3, 4, 4, 0, 0 }, // ladder 24 - copy of 17 with different total length + { 3, 4, 4, 0, 0, 0 }, // ladder 25 - copy of 18 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 26 - copy of 19 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 27 - copy of 19 with different total length + }; + +// Issue #405 +// Counting from the most upstream ladder, the gaps between sensors are as follows: +// 01 (most upstream): 41.3mm +// 02: 41.3mm +// 03: 42.0mm +// 04: 48.6mm +// 05: 60.8mm +// 06: 67.0mm +// 07: 79.2mm +// 08 (most downstream): 88.0mm + + Double_t gapXYZ[27][3] = { + { 0., 4.13, 0. }, // ladder 01 + { 0., 4.13, 0. }, // ladder 02 + { 0., 4.20, 0. }, // ladder 03 + { 0., 4.86, 0. }, // ladder 04 + { 0., 6.08, 0. }, // ladder 05 + { 0., 6.70, 0. }, // ladder 06 + { 0., 7.92, 0. }, // ladder 07 + { 0., 8.80, 0. }, // ladder 08 + { 0., -gkSectorOverlapY, 0. }, // ladder 09 + { 0., -gkSectorOverlapY, 0. }, // ladder 10 + { 0., -gkSectorOverlapY, 0. }, // ladder 11 + { 0., -gkSectorOverlapY, 0. }, // ladder 12 + { 0., -gkSectorOverlapY, 0. }, // ladder 13 + { 0., -gkSectorOverlapY, 0. }, // ladder 14 + { 0., -gkSectorOverlapY, 0. }, // ladder 15 + { 0., -gkSectorOverlapY, 0. }, // ladder 16 + { 0., -gkSectorOverlapY, 0. }, // ladder 17 + { 0., -gkSectorOverlapY, 0. }, // ladder 18 + { 0., -gkSectorOverlapY, 0. }, // ladder 19 + { 0., -gkSectorOverlapY, 0. }, // ladder 20 + { 0., -gkSectorOverlapY, 0. }, // ladder 21 + { 0., -gkSectorOverlapY, 0. }, // ladder 22 + { 0., -gkSectorOverlapY, 0. }, // ladder 23 + + { 0., -gkSectorOverlapY, 0. }, // ladder 24 - copy of 17 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 25 - copy of 18 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 26 - copy of 19 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 27 - copy of 19 with different total length + }; + + Double_t ladderLength[27] = { + 48.0, // ladder 01 + 48.0, // ladder 02 + 64.0, // ladder 03 + 64.0, // ladder 04 + 80.0, // ladder 05 + 80.0, // ladder 06 + 92.0, // ladder 07 + 96.0, // ladder 08 + 48.0, // ladder 09 + 48.0, // ladder 10 + 48.0, // ladder 11 + 64.0, // ladder 12 + 64.0, // ladder 13 + 64.0, // ladder 14 + 64.0, // ladder 15 + 80.0, // ladder 16 + 80.0, // ladder 17 + 80.0, // ladder 18 + 80.0, // ladder 19 + 92.0, // ladder 20 + 92.0, // ladder 21 + 96.0, // ladder 22 + 96.0, // ladder 23 + + 96.0, // ladder 24 - copy of 17 with different total length + 92.0, // ladder 25 - copy of 18 with different total length + 96.0, // ladder 26 - copy of 19 with different total length + 92.0, // ladder 27 - copy of 19 with different total length + }; +// ======================================================================== + + // calculate Z shift for ladders with and without gaps in the center + s0name = Form("Sector%02d", allSectorTypes[0][0]); + s0vol = gGeoMan->GetVolume(s0name); + shape = (TGeoBBox*) s0vol->GetShape(); + + for (Int_t iLadder = 0; iLadder < 27; iLadder++) + { + if (iLadder+1 <= 8) // for the 2 inner ladders of each station with gap for beampipe + gapXYZ[iLadder][2] = 0; // there is no offset in z for halfladders on ladders with a beampipe hole + else + gapXYZ[iLadder][2] = 2. * shape->GetDZ() + gkSectorGapZ; // set displacement in z for overlapping half ladders + } + +// ======================================================================== + + for (Int_t iLadder = 0; iLadder < 27; iLadder++) + { + cout << endl; + nSectors = 0; + for (Int_t i=0; i < 5; i++) + if (allSectorTypes[iLadder][i] != 0) + { + sectorTypes[nSectors] = allSectorTypes[iLadder][i]; // copy sectors for this ladder + cout << "DE iLadder " << iLadder+1 << " sectorTypes[" << nSectors << "] = " << allSectorTypes[iLadder][i] << ";" << endl; + nSectors++; // count how many sectors are in this ladder + } + + if (allSectorTypes[iLadder][5] == 0) + align = 'l'; + else + align = 'r'; + hlname = Form("HalfLadder%02du", iLadder+1); + // build upper half ladder + halfLadderU = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2.); // mirrored + + if (allSectorTypes[iLadder][5] == 0) + align = 'r'; + else + align = 'l'; + hlname = Form("HalfLadder%02dd", iLadder+1); + // build lower half ladder + halfLadderD = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2.); // mirrored + + // at this point half ladders are constructed + + // build all 4 possible ladders types for this sensor arrangement + ConstructLadder( iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19a + ConstructLadder( 100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19b + + ConstructLadder(1000+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19k + ConstructLadder(1100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19k + + nLadders++; + } + + return nLadders; +} +/** ======================================================================= **/ + + + +// **************************************************************************** +// ***** ***** +// ***** Generic functions for the construction of STS elements ***** +// ***** ***** +// ***** module: volume (made of a sector and a cable) ***** +// ***** haf ladder: assembly (made of modules) ***** +// ***** ladder: assembly (made of two half ladders) ***** +// ***** station: volume (made of ladders) ***** +// ***** ***** +// **************************************************************************** + + + +/** =========================================================================== + ** Construct a module + ** + ** A module is a sector plus the readout cable extending from the + ** top of the sector. The cable is made from passive silicon. + ** The cable has the same x size as the sector. + ** Its thickness is given by the global variable gkCableThickness. + ** The cable length is a parameter. + ** The sensor(s) of the sector is/are placed directly in the module; + ** the sector is just auxiliary for the proper placement. + ** + ** Arguments: + ** name volume name + ** sector pointer to sector volume + ** cableLength length of cable + **/ +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength) { + + // --- Check sector volume + if ( ! sector ) Fatal("CreateModule", "Sector volume not found!"); + + // --- Get size of sector + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + + // --- Get size of cable + Double_t cableX = sectorX; + Double_t cableY = cableLength; + Double_t cableZ = gkCableThickness; + + // --- Create module volume + Double_t moduleX = TMath::Max(sectorX, cableX); + Double_t moduleY = sectorY + cableLength; + + Double_t moduleZ = TMath::Max(sectorZ, cableZ); + + TGeoVolume* module = gGeoManager->MakeBox(name, gStsMedium, + moduleX/2., + moduleY/2., + moduleZ/2.); + + // --- Position of sector in module + // --- Sector is centred in x and z and aligned to the bottom + Double_t sectorXpos = 0.; + Double_t sectorYpos = 0.5 * (sectorY - moduleY); + Double_t sectorZpos = 0.; + + + // --- Get sensor(s) from sector + Int_t nSensors = sector->GetNdaughters(); + for (Int_t iSensor = 0; iSensor < nSensors; iSensor++) { + TGeoNode* sensor = sector->GetNode(iSensor); + + // --- Calculate position of sensor in module + const Double_t* xSensTrans = sensor->GetMatrix()->GetTranslation(); + Double_t sensorXpos = 0.; + Double_t sensorYpos = sectorYpos + xSensTrans[1]; + Double_t sensorZpos = 0.; + TGeoTranslation* sensTrans = new TGeoTranslation("sensTrans", + sensorXpos, + sensorYpos, + sensorZpos); + + // --- Add sensor volume to module + TGeoVolume* sensVol = sensor->GetVolume(); + module->AddNode(sensor->GetVolume(), iSensor+1, sensTrans); + module->GetShape()->ComputeBBox(); + } + + + // --- Create cable volume, if necessary, and place it in module + // --- Cable is centred in x and z and aligned to the top + if ( gkConstructCables && cableLength > 0.0001 ) { + TString cableName = TString(name) + "_cable"; + TGeoMedium* cableMedium = gGeoMan->GetMedium("STScable"); + if ( ! cableMedium ) Fatal("CreateModule", "Medium STScable not found!"); + TGeoVolume* cable = gGeoManager->MakeBox(cableName.Data(), + cableMedium, + cableX / 2., + cableY / 2., + cableZ / 2.); + // add color to cables + cable->SetLineColor(kOrange); + cable->SetTransparency(60); + Double_t cableXpos = 0.; + Double_t cableYpos = sectorY + 0.5 * cableY - 0.5 * moduleY; + Double_t cableZpos = 0.; + TGeoTranslation* cableTrans = new TGeoTranslation("cableTrans", + cableXpos, + cableYpos, + cableZpos); + module->AddNode(cable, 1, cableTrans); + module->GetShape()->ComputeBBox(); + } + + return module; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a half ladder + ** + ** A half ladder is a virtual volume (TGeoVolumeAssembly) consisting + ** of several modules arranged on top of each other. The modules + ** have a given overlap in y and a displacement in z to allow for the + ** overlap. + ** + ** The typ of sectors / modules to be placed must be specified: + ** 1 = sensor01 + ** 2 = sensor02 + ** 3 = sensor03 + ** 4 = sensor04 + ** 5 = 2 x sensor04 (chained) + ** 6 = 3 x sensor04 (chained) + ** The cable is added automatically from the top of each sensor to + ** the top of the half ladder. + ** The alignment can be left (l) or right (r), which matters in the + ** case of different x sizes of sensors (e.g. SensorType01). + ** + ** Arguments: + ** name volume name + ** nSectors number of sectors + ** sectorTypes array with sector types + ** align horizontal alignment of sectors + * ladderLength full length of the ladder towards FEE + * offsetY gap in the beam-pipe region + **/ +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY) { + + // --- Create half ladder volume assembly + TGeoVolumeAssembly* halfLadder = new TGeoVolumeAssembly(name); + + // --- Determine size of ladder + Double_t ladderX = 0.; + Double_t ladderY = 0.; + Double_t ladderZ = 0.; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + if ( ! sector ) + Fatal("ConstructHalfLadder", Form("Volume %s not found", sectorName.Data())); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + // --- Ladder x size equals largest sector x size + ladderX = TMath::Max(ladderX, 2. * box->GetDX()); + // --- Ladder y size is sum of sector ysizes + ladderY += 2. * box->GetDY(); + // --- Ladder z size is sum of sector z sizes + ladderZ += 2. * box->GetDZ(); + } + // --- Subtract overlaps in y + ladderY -= Double_t(nSectors-1) * gkSectorOverlapY; + // --- Add gaps in z direction + ladderZ += Double_t(nSectors-1) * gkSectorGapZ; + + ladderY = TMath::Max(ladderLength - offsetY, ladderY); + + // --- Create and place modules + Double_t yPosSect = -0.5 * ladderY; + Double_t zPosMod = -0.5 * ladderZ; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + yPosSect += 0.5 * sectorY; // Position of sector in ladder + Double_t cableLength = 0.5 * ladderY - yPosSect - 0.5 * sectorY; + TString moduleName = name + "_" + Form("Module%02d", + sectorTypes[iSector]); + TGeoVolume* module = ConstructModule(moduleName.Data(), + sector, cableLength); + + TGeoBBox* shapeMod = (TGeoBBox*) module->GetShape(); + Double_t moduleX = 2. * shapeMod->GetDX(); + Double_t moduleY = 2. * shapeMod->GetDY(); + Double_t moduleZ = 2. * shapeMod->GetDZ(); + Double_t xPosMod = 0.; + if ( align == 'l' ) + xPosMod = 0.5 * (moduleX - ladderX); // left aligned + else if ( align == 'r' ) + xPosMod = 0.5 * (ladderX - moduleX); // right aligned + else + xPosMod = 0.; // centred in x + Double_t yPosMod = 0.5 * (ladderY - moduleY); // top aligned + zPosMod += 0.5 * moduleZ; + TGeoTranslation* trans = new TGeoTranslation("t", xPosMod, + yPosMod, zPosMod); + halfLadder->AddNode(module, iSector+1, trans); + halfLadder->GetShape()->ComputeBBox(); + yPosSect += 0.5 * sectorY - gkSectorOverlapY; + zPosMod += 0.5 * moduleZ + gkSectorGapZ; + } + + CheckVolume(halfLadder); + cout << endl; + + return halfLadder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Add a carbon support to a ladder + ** + ** Arguments: + ** LadderIndex ladder number + ** ladder pointer to ladder + ** xu size of halfladder + ** ladderY height of ladder along y + ** ladderZ thickness of ladder along z + **/ +void AddCarbonLadder(Int_t LadderIndex, + TGeoVolume* ladder, + Double_t xu, + Double_t ladderY, + Double_t ladderZ) { + + // --- Some variables + TString name = Form("LadderType%04d", LadderIndex); // v19k + Int_t i; + Double_t j; + + Int_t YnumOfFrameBoxes = round(ladderY / gkFrameStep); + + // cout << "DEXZ: lad " << LadderIndex << " inum " << YnumOfFrameBoxes << endl; + + Double_t ladderDZ = (xu/2. + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2)/2.; + cout << "DEFR: frame Z size " << 2 * ladderDZ << " cm" << endl; + + TGeoBBox* fullFrameShp = new TGeoBBox (name+"_CarbonElement_shp", xu/2., gkFrameStep/2., ladderDZ); + TGeoVolume* fullFrameBoxVol = new TGeoVolume(name+"_CarbonElement", fullFrameShp, gStsMedium); + + ConstructFrameElement("CarbonElement", fullFrameBoxVol, xu/2.); + TGeoRotation* fullFrameRot = new TGeoRotation; + fullFrameRot->RotateY(180); + + Int_t inum = YnumOfFrameBoxes; + for (i=1; i<=inum; i++) + { + j=-(inum-1)/2.+(i-1); + // -(10-1)/2. +0 +10-1 -> -4.5 .. +4.5 -> -0.5, +0.5 (= 2) + // -(11-1)/2. +0 +11-1 -> -5.0 .. +5.0 -> -1, 0, 1 (= 3) + // cout << "DE: i " << i << " j " << j << endl; + + if (LadderIndex % 100 <= 3) // central ladders in stations 1 to 3 + { + if ((j>=-1) && (j<=1)) // keep the inner 2 (even) or 3 (odd) elements free for the cone + continue; + } + else if (LadderIndex % 100 <= 8) // central ladders in stations 4 to 8 + { + if ((j>=-2) && (j<=2)) // keep the inner 4 elements free for the cone + continue; + } + + cout << "DELZ: ladderDZ " << ladderDZ << " cm " << -ladderZ/2. - ladderDZ << " cm " << endl; + ladder->AddNode(fullFrameBoxVol, i, new TGeoCombiTrans(name+"_CarbonElement_posrot", 0., j*gkFrameStep, -(ladderZ/2.+ladderDZ), fullFrameRot)); + } + + ladder->GetShape()->ComputeBBox(); + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Construct a ladder out of two half ladders with vertical gap + ** + ** The second half ladder will be rotated by 180 degrees + ** in the x-y plane. The two half ladders will be put on top of each + ** other with a vertical gap. + ** + ** Arguments: + ** name volume name + ** halfLadderU pointer to upper half ladder + ** halfLadderD pointer to lower half ladder + ** gapY vertical gap + ** shiftZ relative displacement along the z axis + **/ + + TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ) { + + // --- Some variables + TGeoBBox* shape = NULL; + + // --- Dimensions of half ladders + shape = (TGeoBBox*) halfLadderU->GetShape(); + Double_t xu = 2. * shape->GetDX(); + Double_t yu = 2. * shape->GetDY(); + Double_t zu = 2. * shape->GetDZ(); + + shape = (TGeoBBox*) halfLadderD->GetShape(); + Double_t xd = 2. * shape->GetDX(); + Double_t yd = 2. * shape->GetDY(); + Double_t zd = 2. * shape->GetDZ(); + + + // --- Create ladder volume assembly + +// TString name = Form("LadderType%02d", LadderIndex); // v19a +// TString name = Form("LadderType%03d", LadderIndex); // v19b + TString name = Form("LadderType%04d", LadderIndex); // v19k + TGeoVolumeAssembly* ladder = new TGeoVolumeAssembly(name); + Double_t ladderX = TMath::Max(xu, xd); + Double_t ladderY = yu + yd + gapY; + Double_t ladderZ = TMath::Max(zu, zd + shiftZ); + + // --- Place half ladders + Double_t xPosU = 0.; // centred in x + Double_t yPosU = 0.5 * ( ladderY - yu ); // top aligned + Double_t zPosU = 0.5 * ( ladderZ - zu ); // front aligned // mount upper half ladder last + if (LadderIndex >= 1000) zPosU = -zPosU; // back aligned // mount upper half ladder first + + TGeoTranslation* tu = new TGeoTranslation("tu", xPosU, yPosU, zPosU); + ladder->AddNode(halfLadderU, 1, tu); + + Double_t xPosD = 0.; // centred in x + Double_t yPosD = 0.5 * ( yd - ladderY ); // bottom aligned + Double_t zPosD = 0.5 * ( zd - ladderZ ); // back aligned // mount lower half ladder first + if (LadderIndex >= 1000) zPosD = -zPosD; // front aligned // mount lower half ladder last + + TGeoRotation* rd = new TGeoRotation(); + rd->RotateZ(180.); + TGeoCombiTrans* cd = new TGeoCombiTrans(xPosD, yPosD, zPosD, rd); + ladder->AddNode(halfLadderD, 2, cd); + + ladder->GetShape()->ComputeBBox(); + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD0ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + cout << "DDDD ladder" << LadderIndex << endl; + cout << "DDDD1ladder" << LadderIndex << " ladderX " << ladderX << " ladderY " << ladderY << " ladderZ " << ladderZ << endl; + + // ---------------- Create and place frame boxes ------------------------ + + if (gkConstructFrames) + AddCarbonLadder(LadderIndex, ladder, ladderX, ladderY, ladderZ); + + // -------------------------------------------------------------------------- + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD2ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + return ladder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a unit + ** + ** The unit volume is the minimal box comprising all ladders + ** minus a tube accomodating the beam pipe. + ** + ** The ladders are arranged horizontally from left to right with + ** a given overlap in x. + ** Every second ladder is slightly displaced upstream from the centre + ** z plane and facing downstream, the others are slightly displaced + ** downstream and facing upstream (rotated around the y axis). + ** + ** Arguments: + ** name volume name + ** nLadders number of ladders + ** ladderTypes array of ladder types + **/ + + TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation) { + + Bool_t isFirstPartOfHalfUnit = kFALSE; + + // TString name = Form("Unit%02d", iUnit); // 0,1,2,3,4,5,6,7 - Unit00 missing in output + // TString name = Form("Unit%02d", iUnit+1); // 1,2,3,4,5,6,7,8 + + TGeoVolume* unit = gGeoMan->GetVolume(unitName[iUnit]); + if ( ! unit ) // if it does not yet exist, create a new one + { + unit = new TGeoVolumeAssembly(unitName[iUnit]); + isFirstPartOfHalfUnit = kTRUE; + } + + // --- Some local variables + TGeoBBox* ladderShape = NULL; + TGeoVolume* ladder = NULL; + TString ladderName; + Double_t subtractedVal; + + // --- Determine size of unit from ladders + Double_t statX = 0.; + // Double_t statY = 0.; + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { +// Int_t ladderType = ladderTypes[iLadder]%100; // v19a +// Int_t ladderType = ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100; // v19b + Int_t ladderType = ladderTypes[iLadder]; // v19k + +// if (iSide == 0) cout << "DWER " << ladderTypes[iLadder] << " " << ladderType << endl; + + if (ladderType > 0) + { +// ladderName = Form("LadderType%02d", ladderType); // v19a +// ladderName = Form("LadderType%03d", ladderType); // v19b + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + if ( ! ladder ) Fatal("ConstructUnit", + Form("Volume %s not found", ladderName.Data())); + ladderShape = (TGeoBBox*) ladder->GetShape(); + statX += 2. * ladderShape->GetDX(); + // statY = TMath::Max(statY, 2. * ladderShape->GetDY()); + } + else + statX += gkSensorSizeX; // empty ladder in unit + } + statX -= Double_t(nLadders-1) * gkLadderOverlapX; + +// if (iSide == 0) cout << "DWER -" << endl; + + // --- Place ladders in unit + cout << "xPos0: " << statX << endl; + Double_t xPos = -0.5 * statX; + cout << "xPos1: " << xPos << endl; + Double_t yPos = 0.; + Double_t zPos = 0.; + + Double_t maxdz = 0.; + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { // find maximum dz in this unit +// Int_t ladderType = ladderTypes[iLadder]%100; // v19a +// Int_t ladderType = ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100; // v19b + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { +// ladderName = Form("LadderType%02d", ladderType); // v19a +// ladderName = Form("LadderType%03d", ladderType); // v19b + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + if (maxdz < ladderShape->GetDZ()) + maxdz = ladderShape->GetDZ(); + } + } + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { +// Int_t ladderType = ladderTypes[iLadder]%100; // v19a +// Int_t ladderType = ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100; // v19b + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { +// ladderName = Form("LadderType%02d", ladderType); // v19a +// ladderName = Form("LadderType%03d", ladderType); // v19b + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + xPos += ladderShape->GetDX(); + cout << "xPos2: " << xPos << endl; + yPos = 0.; // vertically centred + TGeoRotation* rot = new TGeoRotation(); + + if (gkConstructFrames) + subtractedVal = ladderShape->GetDX() + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2; + else + subtractedVal = 0.; + + zPos = 0.5 * gkLadderGapZ + (2*maxdz-ladderShape->GetDZ()-subtractedVal/2.); // z-aligned ladders + +// v19a cout << "DE ladder" << ladderTypes[iLadder]%100 +// v19b cout << "DE ladder" << ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100 +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " dx: " << ladderShape->GetDX() + << " dy: " << ladderShape->GetDY() + << " dz: " << ladderShape->GetDZ() + << " max dz: " << maxdz << endl; + +// v19a cout << "DE ladder" << ladderTypes[iLadder]%100 +// v19b cout << "DE ladder" << ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100 +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " fra: " << gkFrameThickness/2. + << " sub: " << subtractedVal + << " zpo: " << zPos << endl << endl; + +// v19a if (ladderTypes[iLadder]/100 == 1) // flip some of the ladders to reproduce the CAD layout + if (ladderTypes[iLadder]/1000 == 1) // flip some of the ladders to reproduce the CAD layout + rot->RotateY(180.); + else + zPos = -zPos; + + if (!isFirstPartOfHalfUnit) + // zPos += 10; + zPos += 10.5; // v19d +// zPos += 11.0; // v19e + + TGeoCombiTrans* trans = new TGeoCombiTrans(xPos, yPos, zPos, rot); +// start +// cout << "DEEE** iLadder " << iLadder << " " << nLadders/2 << " " << nLadders << endl; + + if (iSide == 0) + { + if (iLadder < nLadders/2) // right side - only half unit -x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + else + { + if (iLadder >= nLadders/2) // left side - only half unit +x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + unit->GetShape()->ComputeBBox(); +// stop + xPos += ladderShape->GetDX() - gkLadderOverlapX; + cout << "xPos3: " << xPos << endl; + } + else + xPos += gkSensorSizeX - gkLadderOverlapX; + } + + return unit; + } +/** ======================================================================= **/ + + +/** =========================================================================== + ** Import and add the passive materials to the STS volume + **/ +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile) +{ + TString passiveName = TString("sts_passive_") + geoTag; + TString basePath = gSystem->Getenv("VMCWORKDIR"); + TString relPath = "/geometry/sts/passive/" + passiveName + ".gdml"; + TString passiveFileName = basePath + relPath; + infoFile << std::endl << std::endl; + infoFile << "Importing STS passive materials from GDML file '" << relPath << "'." << std::endl; + + TGDMLParse parser; + TGeoVolume* gdmlVolume = parser.GDMLReadFile(passiveFileName); + PostProcessGdml(gdmlVolume); + gdmlVolume->SetName(passiveName); + + TGeoTranslation* passiveTrans = new TGeoTranslation(0., 0., 4.68); + infoFile << "Passive assembly is translated for Z=4.68 cm downstream with respect to parent volume" << std::endl << std::endl; + + gdmlVolume->GetShape()->ComputeBBox(); + CheckVolume(gdmlVolume, infoFile); + + infoFile << std::endl; + for (Int_t iNode = 0; iNode < gdmlVolume->GetNdaughters(); iNode++) { + CheckVolume(gdmlVolume->GetNode(iNode)->GetVolume(), infoFile, kFALSE); + } + + stsVolume->AddNode(gdmlVolume, stsVolume->GetNdaughters(), passiveTrans, ""); +} + +/** =========================================================================== + ** Assign visual properties to the imported gdml volumes + **/ +void PostProcessGdml(TGeoVolume* gdmlVolume) +{ + const UInt_t kPOBColor = kRed-6; + const UInt_t kPOBTransparency = 0;// 5; + + const UInt_t kFEBColor = kOrange-6; + const UInt_t kFEBTransparency = 0;// 5; + + const UInt_t kUnitColor = kCyan-10; + const UInt_t kUnitTransparency = 0;// 5; + + const UInt_t kCfColor = kGray+3; + const UInt_t kCfTransparency = 0;// 10; + + // name <Color, Transparency> + std::map<std::string, std::tuple<UInt_t,UInt_t> > props { + { "passive_POB", std::tuple<UInt_t,UInt_t> {kPOBColor, kPOBTransparency} }, + { "passive_FEB", std::tuple<UInt_t,UInt_t> {kFEBColor, kFEBTransparency} }, + { "passive_unit", std::tuple<UInt_t,UInt_t> {kUnitColor, kUnitTransparency} }, + { "passive_Box_Wall", std::tuple<UInt_t,UInt_t> {kCfColor, kCfTransparency} }, + { "passive_Box_Wall_Front_CF2", std::tuple<UInt_t,UInt_t> {kCfColor-3, kCfTransparency} }, + }; + + // Match volume name and apply visual properties + const TObjArray* volumes = gGeoManager->GetListOfVolumes(); + for (auto& entry : props) { + TIter next(volumes); + TGeoVolume *vol = nullptr; + while ((vol=(TGeoVolume*)next())) { + if (TString(vol->GetName()).Contains(entry.first.c_str())) { + vol->SetLineColor(std::get<0>(entry.second)); + vol->SetTransparency(std::get<1>(entry.second)); + } + } + } +} + +/** =========================================================================== + ** Volume information for debugging + **/ +void CheckVolume(TGeoVolume* volume) { + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + cout << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) cout << ", assembly"; + else { + if ( volume->GetMedium() ) + cout << ", medium " << volume->GetMedium()->GetName(); + else cout << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + cout << endl; + if ( volume->GetNdaughters() ) { + cout << "Daughters: " << endl; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) { + TGeoNode* node = volume->GetNode(iNode); + TGeoBBox* shape = (TGeoBBox*) node->GetVolume()->GetShape(); + cout << setw(15) << node->GetName() << ", size " + << fixed << setprecision(3) + << setw(6) << 2. * shape->GetDX() << " x " + << setw(6) << 2. * shape->GetDY() << " x " + << setw(6) << 2. * shape->GetDZ() << ", position ( "; + TGeoMatrix* matrix = node->GetMatrix(); + const Double_t* pos = matrix->GetTranslation(); + cout << setfill(' '); + cout << fixed << setw(8) << pos[0] << ", " + << setw(8) << pos[1] << ", " + << setw(8) << pos[2] << " )" << endl; + } + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Volume information for output to file + **/ +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren) { + if ( ! file ) return; + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + file << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) file << ", assembly"; + else { + if ( volume->GetMedium() ) + file << ", medium " << volume->GetMedium()->GetName(); + else file << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + file << endl; + if ( volume->GetNdaughters() && listChildren) { + file << "Contains: "; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) + file << volume->GetNode(iNode)->GetVolume()->GetName() << " "; + file << endl; + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Calculate beam pipe outer radius for a given z + **/ +Double_t BeamPipeRadius(Double_t z) { + if ( z < gkPipeZ2 ) return gkPipeR1; + Double_t slope = (gkPipeR3 - gkPipeR2 ) / (gkPipeZ3 - gkPipeZ2); + return gkPipeR2 + slope * (z - gkPipeZ2); +} +/** ======================================================================= **/ + + + +/** ======================================================================= **/ +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + TGeoBBox* frameVertPillarShp; + + Double_t t = gkFrameThickness/2.; + + // --- Main vertical pillars +// TGeoBBox* frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, gkFrameStep/2., t); // square crossection, along y +// TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); +// frameVertPillarVol->SetLineColor(kGreen); +// frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoTranslation(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2.)); +// frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoTranslation(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkCylindricalFrames) + // TGeoBBox* frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", 0, t, gkFrameStep/2.); // circle crossection, along z + frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", gkCylinderDiaInner/2., gkCylinderDiaOuter/2., gkFrameStep/2.); // circle crossection, along z + else + frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, t, gkFrameStep/2.); // square crossection, along z + TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); + frameVertPillarVol->SetLineColor(kGreen); + + TGeoRotation* xRot90 = new TGeoRotation; + xRot90->RotateX(90.); + frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoCombiTrans(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoCombiTrans(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + + // TGeoRotation* vertRot = new TGeoRotation(name + "_vertpillar_rot_1", 90., 45., -90.); + TGeoRotation* vertRot = new TGeoRotation; + vertRot->RotateX(90.); + vertRot->RotateY(45.); + frameBoxVol->AddNode(frameVertPillarVol, 3, new TGeoCombiTrans(name + "_vertpillar_pos_3", 0., 0., (x-sqrt(2.)*t)/2., vertRot)); + + // --- Small horizontal pillar + // TGeoBBox* frameHorPillarShp = new TGeoBBox(name + "_horpillar_shape", x-2.*t, gkThinFrameThickness/2., gkThinFrameThickness/2.); + // TGeoVolume* frameHorPillarVol = new TGeoVolume(name + "_horpillar", frameHorPillarShp, framesMaterial); + // frameHorPillarVol->SetLineColor(kCyan); + // frameBoxVol->AddNode(frameHorPillarVol, 1, new TGeoTranslation(name + "_horpillar_pos_1", 0., -gkFrameStep/2.+gkThinFrameThickness/2., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkConstructSmallFrames) { + + // --- Small sloping pillars + TGeoPara* frameSlopePillarShp = new TGeoPara(name + "_slopepillar_shape", + (x-2.*t)/TMath::Cos(31.4/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., 31.4, 0., 90.); + TGeoVolume* frameSlopePillarVol = new TGeoVolume(name + "_slopepillar", frameSlopePillarShp, framesMaterial); + frameSlopePillarVol->SetLineColor(kCyan); + TGeoRotation* slopeRot = new TGeoRotation(name + "_slopepillar_rot_1", 0., 0., 31.4); + TGeoRotation* slopeRot2 = new TGeoRotation(name + "_slopepillar_rot_2", 0., 0., -31.4); + TGeoCombiTrans* slopeTrRot = new TGeoCombiTrans(name + "_slopepillar_posrot_1", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot); + TGeoCombiTrans* slopeTrRot2 = new TGeoCombiTrans(name + "_slopepillar_posrot_2", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot2); + + frameBoxVol->AddNode(frameSlopePillarVol, 1, slopeTrRot); + frameBoxVol->AddNodeOverlap(frameSlopePillarVol, 2, slopeTrRot2); + + + Double_t angl = 23.; + // --- Small sub pillar + TGeoPara* frameSubPillarShp = new TGeoPara(name + "_subpillar_shape", + (sqrt(2)*(x/2.-t)-t/2.)/TMath::Cos(angl/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., angl, 0., 90.); + TGeoVolume* frameSubPillarVol = new TGeoVolume(name + "_subpillar", frameSubPillarShp, framesMaterial); + frameSubPillarVol->SetLineColor(kMagenta); + + Double_t posZ = t * (1. - 3. / ( 2.*sqrt(2.) )); + + // one side of X direction + TGeoRotation* subRot1 = new TGeoRotation(name + "_subpillar_rot_1", 90., 45., -90.+angl); + TGeoCombiTrans* subTrRot1 = new TGeoCombiTrans(name + "_subpillar_posrot_1", -(-x/2.+t-t/(2.*sqrt(2.))), 1., posZ, subRot1); + + TGeoRotation* subRot2 = new TGeoRotation(name + "_subpillar_rot_2", 90., -90.-45., -90.+angl); + TGeoCombiTrans* subTrRot2 = new TGeoCombiTrans(name + "_subpillar_posrot_2", -(-x/2.+t-t/(2.*sqrt(2.))), -1., posZ, subRot2); + + // other side of X direction + TGeoRotation* subRot3 = new TGeoRotation(name + "_subpillar_rot_3", 90., 90.+45., -90.+angl); + TGeoCombiTrans* subTrRot3 = new TGeoCombiTrans(name + "_subpillar_posrot_3", -x/2.+t-t/(2.*sqrt(2.)), 1., posZ, subRot3); + + TGeoRotation* subRot4 = new TGeoRotation(name + "_subpillar_rot_4", 90., -45., -90.+angl); + TGeoCombiTrans* subTrRot4 = new TGeoCombiTrans(name + "_subpillar_posrot_4", -x/2.+t-t/(2.*sqrt(2.)), -1., posZ, subRot4); + + frameBoxVol->AddNode(frameSubPillarVol, 1, subTrRot1); + frameBoxVol->AddNode(frameSubPillarVol, 2, subTrRot2); + frameBoxVol->AddNode(frameSubPillarVol, 3, subTrRot3); + frameBoxVol->AddNode(frameSubPillarVol, 4, subTrRot4); + // frameBoxVol->GetShape()->ComputeBBox(); + } + + return frameBoxVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructSmallCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 6., 7.6, 6., 6.04, 0., 180.); +// TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + Double_t radius = 3.0; + Double_t thickness = 0.04; // 0.4 mm +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 3., 3.2, 3., 3.2, 0., 180.); + TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, radius, radius+thickness, radius, radius+thickness, 0., 180.); + TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + TGeoCombiTrans* M = new TGeoCombiTrans ("M"); + M->RotateX (45.); + M->SetDy (-5.575); + M->SetDz (6.935); + M->RegisterYourself(); + + TGeoShape* coneShp = new TGeoCompositeShape ("Cone_shp", "A-B:M"); + TGeoVolume* coneVol = new TGeoVolume ("Cone", coneShp, framesMaterial); + coneVol->SetLineColor(kGreen); +// coneVol->RegisterYourself(); + +// // --- Inner cone +// Double_t thickness = 0.02; +// Double_t thickness2 = 0.022; +// // TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); +// TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 3.+thickness, 4.6-thickness2, 2.99+thickness, 3.05-thickness2, 0., 180.); +// +// TGeoCombiTrans* M2 = new TGeoCombiTrans ("M2"); +// M2->RotateX (45.); +// M2->SetDy (-5.575+thickness*sqrt(2.)); +// M2->SetDz (6.935); +// M2->RegisterYourself(); +// +// TGeoShape* coneShp2 = new TGeoCompositeShape ("Cone2_shp", "A2-B:M2"); +// TGeoVolume* coneVol2 = new TGeoVolume ("Cone2", coneShp2, gStsMedium); +// coneVol2->SetLineColor(kGreen); +//// coneVol2->RegisterYourself(); +// +// coneVol->AddNode(coneVol2, 1); + + return coneVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructBigCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone + TGeoConeSeg* bA = new TGeoConeSeg ("bA", coneDz, 6., 7.6, 6., 6.04, 0., 180.); + TGeoBBox* bB = new TGeoBBox ("bB", 8., 6., 10.); + + TGeoCombiTrans* bM = new TGeoCombiTrans ("bM"); + bM->RotateX (45.); + bM->SetDy (-5.575); + bM->SetDz (6.935); + bM->RegisterYourself(); + + TGeoShape* coneBigShp = new TGeoCompositeShape ("ConeBig_shp", "bA-bB:bM"); + TGeoVolume* coneBigVol = new TGeoVolume ("ConeBig", coneBigShp, framesMaterial); + coneBigVol->SetLineColor(kGreen); +// coneBigVol->RegisterYourself(); + + // --- Inner cone + Double_t thickness = 0.02; + Double_t thickness2 = 0.022; + TGeoConeSeg* bA2 = new TGeoConeSeg ("bA2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); + + TGeoCombiTrans* bM2 = new TGeoCombiTrans ("bM2"); + bM2->RotateX (45.); + bM2->SetDy (-5.575+thickness*sqrt(2.)); + bM2->SetDz (6.935); + bM2->RegisterYourself(); + + TGeoShape* coneBigShp2 = new TGeoCompositeShape ("ConeBig2_shp", "bA2-bB:bM2"); + TGeoVolume* coneBigVol2 = new TGeoVolume ("ConeBig2", coneBigShp2, gStsMedium); + coneBigVol2->SetLineColor(kGreen); +// coneBigVol2->RegisterYourself(); + + coneBigVol->AddNode(coneBigVol2, 1); + + return coneBigVol; +} + +/** ======================================================================= **/ diff --git a/macro/sts/geometry/create_stsgeo_v19p.C b/macro/sts/geometry/create_stsgeo_v19p.C new file mode 100644 index 0000000000000000000000000000000000000000..487473d1ec841b12168f106d66a8e18d55ae0679 --- /dev/null +++ b/macro/sts/geometry/create_stsgeo_v19p.C @@ -0,0 +1,2376 @@ +/****************************************************************************** + ** Creation of STS geometry in ROOT format (TGeo). + ** + ** @file create_stsgeo_v19p.C + ** @author Volker Friese <v.friese@gsi.de> + ** @since 15 June 2012 + ** @date 09.05.2014 + ** @author Tomas Balog <T.Balog@gsi.de> + ** + ** v19p: based on v19k - parameters : delta Z prime = 0.70 cm - delta Z pitch = 0.20 cm + ** v19o: based on v19k - parameters : delta Z prime = 0.30 cm - delta Z pitch = 0.20 cm + ** v19n: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.20 cm (bug fix of v19m) + ** v19m: based on v19k - parameters : delta Z prime = 0.55 cm - delta Z pitch = 0.20 cm (bug) + ** v19l: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.15 cm + ** v19k: ladders on upstream side of units get upper half ladders installed first, + ** ladders on downstream side of units get lower half ladders installed first, + ** this saves 1.5 mm space in z per station, 12 mm in total (LadderType went from 3 to 4 digits) + ** parameters : delta Z prime = 1.00 cm - delta Z pitch = 0.15 cm + ** v19j: use overlap and distance parameters from CAD model + ** v19h: put STS stations from v19d at z-positions = 260; 365; 470; 575; 680; 785; 890; 995 mm + ** v19g: place a box with services around v19e + ** v19f: place a box with services around v19d + ** v19e: increase spacing between stations by +10 mm from 100 mm + ** v19d: increase spacing between stations by + 5 mm from 100 mm + ** v19c: drop station 8 and increase spacing between remaining 7 stations from 10 cm to 12 c + ** v19b: introduce FEB orientation in ladder numbering (LadderType went from 2 to 3 digits) + ** v19a: import passive materials from gdml file + ** extend CF ladder structures and cables towards FEE plane + ** change CF ladder frame shape + ** v18d: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu (based on v18b) + ** v18c: fixed cut-out windows in cooling plates, improve the box shape/materials + ** v18b: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu + ** v18a: adds 9 cooling/holding plates and a box around the setup + ** v16g: v16g is the new standard geometry from November 2017 + ** v16g: switch from stations to units - left / right ("Unit01L", "Unit01R") + ** v16f: switch from stations to units + ** - split in upstream / downstream and left / right parts + ** - named Unit0xUR, Unit0xUL, Unit0xDR, Unit0xDL + ** v16e: switch from stations to units - upstream / downstream ("Unit01U", "Unit01D") + ** v16d: skip keeping volumes of sts and stations + ** v16c: like v16b, but senors of ladders beampipe next to beampipe + ** shifted closer to the pipe, like in the CAD model + ** v16b: like v16a, but yellow sensors removed + ** v16a: derived from v15c (no cones), but with sensor types renamed: + ** 2 -> 1, 3 -> 2, 4 -> 3, 5 -> 4, 1 -> 5 + ** + ** v15c: as v15b without cones + ** v15b: introduce modified carbon ladders from v13z + ** v15a: with flipped ladder orientation for stations 0,2,4,6 to match CAD design + ** + ** TODO: + ** + ** DONE: + ** v15b - use carbon macaroni as ladder support + ** v15b - introduce a small gap between lowest sensor and carbon ladder + ** v15b - build small cones for the first 2 stations + ** v15b - within a station the ladders of adjacent units should not touch eachother - set gkLadderGapZ to 10 mm + ** v15b - for all ladders set an even number of ladder elements + ** v15b - z offset of cones to ladders should not be 0.3 by default, but 0.26 + ** v15b - within a station the ladders should be aligned in z, defined either by the unit or the ladder with most sensors + ** v15b - get rid of cone overlap in stations 7 and 8 - done by adapting rHole size + ** + ** The geometry hierarachy is: + ** + ** 1. Sensors (see function CreateSensors) + ** The sensors are the active volumes and the lowest geometry level. + ** They are built as TGeoVolumes, shape box, material silicon. + ** x size is determined by strip pitch 58 mu and 1024 strips + ** plus guard ring of 1.3 mm at each border -> 6.1992 cm. + ** Sensor type 1 is half of that (3.0792 cm). + ** y size is determined by strip length (2.2 / 4.2 / 6.3 cm) plus + ** guard ring of 1.3 mm at top and bottom -> 2.46 / 4.46 / 6.46 cm. + ** z size is a parameter, to be set by gkSensorThickness. + ** + ** 2. Sectors (see function CreateSectors) + ** Sectors consist of several chained sensors. These are arranged + ** vertically on top of each other with a gap to be set by + ** gkChainGapY. Sectors are constructed as TGeoVolumeAssembly. + ** The sectors are auxiliary volumes used for proper placement + ** of the sensor(s) in the module. They do not show up in the + ** final geometry. + ** + ** 3. Modules (see function ConstructModule) + ** A module is a readout unit, consisting of one sensor or + ** a chain of sensors (see sector) and a cable. + ** The cable extends from the top of the sector vertically to the + ** top of the halfladder the module is placed in. The cable and module + ** volume thus depend on the vertical position of the sector in + ** the halfladder. The cables consist of silicon with a thickness to be + ** set by gkCableThickness. + ** Modules are constructed as TGeoVolume, shape box, medium gStsMedium. + ** The module construction can be switched off (gkConstructCables) + ** to reproduce older geometries. + ** + ** 4. Halfladders (see function ConstructHalfLadder) + ** A halfladder is a vertical assembly of several modules. The modules + ** are placed vertically such that their sectors overlap by + ** gkSectorOverlapY. They are displaced in z direction to allow for the + ** overlap in y by gkSectorGapZ. + ** The horizontal placement of modules in the halfladder can be choosen + ** to left aligned or right aligned, which only matters if sensors of + ** different x size are involved. + ** Halfladders are constructed as TGeoVolumeAssembly. + ** + ** 5. Ladders (see function CreateLadders and ConstructLadder) + ** A ladder is a vertical assembly of two halfladders, and is such the + ** vertical building block of a station. The second (bottom) half ladder + ** is rotated upside down. The vertical arrangement is such that the + ** inner sectors of the two halfladders have the overlap gkSectorOverlapY + ** (function CreateLadder) or that there is a vertical gap for the beam + ** hole (function CreateLadderWithGap). + ** Ladders are constructed as TGeoVolumeAssembly. + ** + ** 6. Stations (see function ConstructStation) + ** A station represents one layer of the STS geometry: one measurement + ** at (approximately) a given z position. It consist of several ladders + ** arranged horizontally to cover the acceptance. + ** The ladders are arranged such that there is a horizontal overlap + ** between neighbouring ladders (gkLadderOverLapX) and a vertical gap + ** to allow for this overlap (gkLadderGapZ). Each second ladder is + ** rotated around its y axis to face away from or into the beam. + ** Stations are constructed as TGeoVolumes, shape box minus tube (for + ** the beam hole), material gStsMedium. + ** + ** 7. STS + ** The STS is a volume hosting the entire detectors system. It consists + ** of several stations located at different z positions. + ** The STS is constructed as TGeoVolume, shape box minus cone (for the + ** beam pipe), material gStsMedium. The size of the box is computed to + ** enclose all stations. + *****************************************************************************/ + + +// Remark: With the proper steering variables, this should exactly reproduce +// the geometry version v11b of A. Kotynia's described in the ASCII format. +// The only exception is a minimal difference in the z position of the +// sectors/sensors. This is because of ladder types 2 and 4 containing the half +// sensors around the beam hole (stations 1,2 and 3). In v11b, the two ladders +// covering the beam hole cannot be transformed into each other by rotations, +// but only by a reflection. This means they are constructionally different. +// To avoid introducing another two ladder types, the difference in z position +// was accepted. + + +// Differences to v12: +// gkChainGap reduced from 1 mm to 0 +// gkCableThickness increased from 100 mum to 200 mum (2 cables per module) +// gkSectorOverlapY reduced from 3 mm to 2.4 mm +// New sensor types 05 and 06 +// New sector types 07 and 08 +// Re-definiton of ladders (17 types instead of 8) +// Re-definiton of station from new ladders + + +#include <iomanip> +#include <iostream> +#include "TGeoManager.h" + +#include "TGeoTube.h" +#include "TGeoPara.h" +#include "TGeoCone.h" +#include "TGeoTrd2.h" +#include "TGeoCompositeShape.h" +#include "TGeoXtru.h" +#include "TGeoPhysicalNode.h" + +// forward declarations +Int_t CreateSensors(); +Int_t CreateSectors(); +Int_t CreateLadders(); +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength); +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY); +TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ); +TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation); +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile); +void PostProcessGdml(TGeoVolume* gdmlTop); +void CheckVolume(TGeoVolume* volume); +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren = kTRUE); +Double_t BeamPipeRadius(Double_t z); +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x); +TGeoVolume* ConstructSmallCone(Double_t coneDz); +TGeoVolume* ConstructBigCone(Double_t coneDz); + +// ------------- Version highlight ----------------------------------- + +const std::string gVersionHighlight = R"( +Summary: + This version adds passive materials imported from GDML model to the STS geometry: + * Taken from and largely correspond to mechanical CAD drawings of the detector + * Thermal insulation box: + - made out of carbon sandwitch panel (2mm carbon fiber sheet + layer of carbon foam + 2mm carbon fiber sheet) + - front window of complex shape with interface to MVD / target chamber + - back window with large aperture (2000 x 1200 mm) square cut into carbon foam + * Structural units: + - made of 2 complex shape aluminum C-Frames, 15mm thick + - placed at 25, 35, ... ,105 cm absolute Z + - contain front-end and power distribution boxes with equivalent X_0 values + + Scripted geometry tweaks: + * Ladders and cables are extended towards the read-out planes having same lengths in respective rows + * Adjusted form and shape of carbon ladder structures from L-type to X-type + * Reduced verbosity of this file + + Sensor arrangement is the same as in version v16g + + !! Important for this version is the discrepancy from the mechanical CAD w.r.t. front wall. + The square window was replaced by a round one to avoid overlaps with present beam pipe designs, e.g. pipe_v16b_1e +)"; + +// ------------- Steering variables ----------------------------------- + +// ---> Horizontal width of sensors [cm] +const Double_t gkSensorSizeX = 6.2; // was 6.2092; // 6.2 - Oleg CAD 15/05/2020 + +// ---> Thickness of sensors [cm] +const Double_t gkSensorThickness = 0.03; + +// ---> Vertical gap between chained sensors [cm] +const Double_t gkChainGapY = 0.00; + +// ---> Thickness of cables [cm] +const Double_t gkCableThickness = 0.02; + +// ---> Horizontal overlap of neighbouring ladders [cm] +const Double_t gkLadderOverlapX = 0.25; // delta X - Oleg CAD 14/05/2020 + +// ---> Vertical overlap of neighbouring sectors in a ladder [cm] +const Double_t gkSectorOverlapY = 0.46; // delta Y - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring sectors in a ladder [cm] +const Double_t gkSectorGapZ = 0.17; // gap + thickness = pitch // delta Z pitch = 0.20 - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring ladders [cm] +const Double_t gkLadderGapZ = 0.70 - 0.20; // for asym // 0.5 for sym // delta Z prime + +// ---> Gap in z between lowest sector to carbon support structure [cm] +const Double_t gkSectorGapZFrame = 0.280 - 0.025; // Oleg CAD 05/05/2020 // there is a 2.8 mm gap between the bottom side of the sensor and the top ledge of the carbon ladder + +// ---> Switch to construct / not to construct readout cables +const Bool_t gkConstructCables = kTRUE; + +// ---> Switch to construct / not to construct frames +const Bool_t gkConstructCones = kFALSE; // kTRUE; // switch this false by default for v15c and v16x +const Bool_t gkConstructFrames = kTRUE; // kFALSE; // switch this true by default for v15c and v16x +const Bool_t gkConstructSmallFrames = kTRUE; // kFALSE; +const Bool_t gkCylindricalFrames = kTRUE; // kFALSE; + +// ---> Size of the frame +const Double_t gkFrameThickness = 0.2; +const Double_t gkThinFrameThickness = 0.05; +const Double_t gkFrameStep = 4.0; // size of frame cell along y direction + +const Double_t gkCylinderDiaInner = 0.07; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) +const Double_t gkCylinderDiaOuter = 0.15; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) + +// ---> Switch to import / not to import the Passive materials from GDML file +//const Bool_t gkImportPassive = kTRUE; +const Bool_t gkImportPassive = kFALSE; + +// ---------------------------------------------------------------------------- + + +// -------------- Parameters of beam pipe in the STS region -------------- +// ---> Needed to compute stations and STS such as to avoid overlaps +const Double_t gkPipeZ1 = 22.0; +const Double_t gkPipeR1 = 1.8; +const Double_t gkPipeZ2 = 50.0; +const Double_t gkPipeR2 = 1.8; +const Double_t gkPipeZ3 = 125.0; +const Double_t gkPipeR3 = 5.5; + +//DE const Double_t gkPipeZ1 = 27.0; +//DE const Double_t gkPipeR1 = 1.05; +//DE const Double_t gkPipeZ2 = 160.0; +//DE const Double_t gkPipeR2 = 3.25; +// ---------------------------------------------------------------------------- + +//TString unitName[16] = // names of units for v16e +// { "Unit00D", +// "Unit01U", "Unit01D", +// "Unit02U", "Unit02D", +// "Unit03U", "Unit03D", +// "Unit04U", "Unit04D", +// "Unit05U", "Unit05D", +// "Unit06U", "Unit06D", +// "Unit07U", "Unit07D", +// "Unit08U" }; + +//TString unitName[32] = // names of units for v16f +// { "Unit00DR", "Unit00DL", +// "Unit01UR", "Unit01UL", "Unit01DR", "Unit01DL", +// "Unit02UR", "Unit02UL", "Unit02DR", "Unit02DL", +// "Unit03UR", "Unit03UL", "Unit03DR", "Unit03DL", +// "Unit04UR", "Unit04UL", "Unit04DR", "Unit04DL", +// "Unit05UR", "Unit05UL", "Unit05DR", "Unit05DL", +// "Unit06UR", "Unit06UL", "Unit06DR", "Unit06DL", +// "Unit07UR", "Unit07UL", "Unit07DR", "Unit07DL", +// "Unit08UR", "Unit08UL" }; + +TString unitName[32] = // names of units for v16g - while merging D and U parts + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", "Unit01R", "Unit01L", + "Unit02R", "Unit02L", "Unit02R", "Unit02L", + "Unit03R", "Unit03L", "Unit03R", "Unit03L", + "Unit04R", "Unit04L", "Unit04R", "Unit04L", + "Unit05R", "Unit05L", "Unit05R", "Unit05L", + "Unit06R", "Unit06L", "Unit06R", "Unit06L", + "Unit07R", "Unit07L", "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +TString unitName18[18] = // names of units for v16g + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", + "Unit02R", "Unit02L", + "Unit03R", "Unit03L", + "Unit04R", "Unit04L", + "Unit05R", "Unit05L", + "Unit06R", "Unit06L", + "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +// ------------- Other global variables ----------------------------------- +// ---> STS medium (for every volume except silicon) +TGeoMedium* gStsMedium = NULL; // will be set later +// ---> TGeoManager (too lazy to write out 'Manager' all the time +TGeoManager* gGeoMan = NULL; // will be set later +// ---------------------------------------------------------------------------- + + + + +// ============================================================================ +// ====== Main function ===== +// ============================================================================ + +void create_stsgeo_v19p(const char* geoTag="v19p") +{ + + // ------- Geometry file name (output) ---------------------------------- + TString geoFileName = "sts_"; + geoFileName = geoFileName + geoTag + ".geo.root"; + // -------------------------------------------------------------------------- + + + // ------- Open info file ----------------------------------------------- + TString infoFileName = geoFileName; + infoFileName.ReplaceAll("root", "info"); + fstream infoFile; + infoFile.open(infoFileName.Data(), fstream::out); + infoFile << "STS geometry created with create_stsgeo_v19p.C" << endl; + infoFile << gVersionHighlight << endl; + infoFile << "Global variables: " << endl; + infoFile << "Sensor thickness = " << gkSensorThickness << " cm" << endl; + infoFile << "Vertical gap in sensor chain = " + << gkChainGapY << " cm" << endl; + infoFile << "Vertical overlap of sensors = " + << gkSectorOverlapY << " cm" << endl; + infoFile << "Gap in z between neighbour sensors = " + << gkSectorGapZ << " cm" << endl; + infoFile << "Horizontal overlap of sensors = " + << gkLadderOverlapX << " cm" << endl; + infoFile << "Gap in z between neighbour ladders = " + << gkLadderGapZ << " cm" << endl; + if ( gkConstructCables ) + infoFile << "Cable thickness = " << gkCableThickness << " cm" << endl; + else + infoFile << "No cables" << endl; + infoFile << endl; + infoFile << "Beam pipe: R1 = " << gkPipeR1 << " cm at z = " + << gkPipeZ1 << " cm" << endl; + infoFile << "Beam pipe: R2 = " << gkPipeR2 << " cm at z = " + << gkPipeZ2 << " cm" << endl; + infoFile << "Beam pipe: R3 = " << gkPipeR3 << " cm at z = " + << gkPipeZ3 << " cm" << endl; + // -------------------------------------------------------------------------- + + + // ------- Load media from media file ----------------------------------- + FairGeoLoader* geoLoad = new FairGeoLoader("TGeo","FairGeoLoader"); + FairGeoInterface* geoFace = geoLoad->getGeoInterface(); + TString geoPath = gSystem->Getenv("VMCWORKDIR"); + TString medFile = geoPath + "/geometry/media.geo"; + geoFace->setMediaFile(medFile); + geoFace->readMedia(); + gGeoMan = gGeoManager; + // -------------------------------------------------------------------------- + + + // ----------------- Get and create the required media ----------------- + FairGeoMedia* geoMedia = geoFace->getMedia(); + FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder(); + + // ---> air + FairGeoMedium* mAir = geoMedia->getMedium("air"); + if ( ! mAir ) Fatal("Main", "FairMedium air not found"); + geoBuild->createMedium(mAir); + TGeoMedium* air = gGeoMan->GetMedium("air"); + if ( ! air ) Fatal("Main", "Medium air not found"); + + // ---> silicon + FairGeoMedium* mSilicon = geoMedia->getMedium("silicon"); + if ( ! mSilicon ) Fatal("Main", "FairMedium silicon not found"); + geoBuild->createMedium(mSilicon); + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + if ( ! silicon ) Fatal("Main", "Medium silicon not found"); + + // ---> carbon + FairGeoMedium* mCarbon = geoMedia->getMedium("carbon"); + if ( ! mCarbon ) Fatal("Main", "FairMedium carbon not found"); + geoBuild->createMedium(mCarbon); + TGeoMedium* carbon = gGeoMan->GetMedium("carbon"); + if ( ! carbon ) Fatal("Main", "Medium carbon not found"); + + // ---> STSBoxCarbonFoam + FairGeoMedium* mSTSBoxCarbonFoam = geoMedia->getMedium("STSBoxCarbonFoam"); + if ( ! mSTSBoxCarbonFoam ) Fatal("Main", "FairMedium STSBoxCarbonFoam not found"); + geoBuild->createMedium(mSTSBoxCarbonFoam); + TGeoMedium* STSBoxCarbonFoam = gGeoMan->GetMedium("STSBoxCarbonFoam"); + if ( ! STSBoxCarbonFoam ) Fatal("Main", "Medium STSBoxCarbonFoam not found"); + + // ---> STSBoxCarbonFibre + FairGeoMedium* mSTSBoxCarbonFibre = geoMedia->getMedium("STSBoxCarbonFibre"); + if ( ! mSTSBoxCarbonFibre ) Fatal("Main", "FairMedium STSBoxCarbonFibre not found"); + geoBuild->createMedium(mSTSBoxCarbonFibre); + TGeoMedium* STSBoxCarbonFibre = gGeoMan->GetMedium("STSBoxCarbonFibre"); + if ( ! STSBoxCarbonFibre ) Fatal("Main", "Medium STSBoxCarbonFibre not found"); + + // ---> STScable + FairGeoMedium* mSTScable = geoMedia->getMedium("STScable"); + if ( ! mSTScable ) Fatal("Main", "FairMedium STScable not found"); + geoBuild->createMedium(mSTScable); + TGeoMedium* STScable = gGeoMan->GetMedium("STScable"); + if ( ! STScable ) Fatal("Main", "Medium STScable not found"); + + // ---> Aluminium + FairGeoMedium* mAluminium = geoMedia->getMedium("aluminium"); + if ( ! mAluminium ) Fatal("Main", "FairMedium aluminium not found"); + geoBuild->createMedium(mAluminium); + TGeoMedium* aluminium = gGeoMan->GetMedium("aluminium"); + if ( ! aluminium ) Fatal("Main", "Medium aluminium not found"); + + // --- + gStsMedium = air; + // -------------------------------------------------------------------------- + + + // -------------- Create geometry and top volume ------------------------- + gGeoMan = (TGeoManager*)gROOT->FindObject("FAIRGeom"); +// gGeoMan->SetName("STSgeom"); + TGeoVolume* top = new TGeoVolumeAssembly("top"); +// TGeoBBox* topbox= new TGeoBBox("", 120., 120., 120.); +// TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air")); + gGeoMan->SetTopVolume(top); + // -------------------------------------------------------------------------- + + + // -------------- Create media ------------------------------------------ + /* + cout << endl; + cout << "===> Creating media...."; + cout << CreateMedia(); + cout << " media created" << endl; + TList* media = gGeoMan->GetListOfMedia(); + for (Int_t iMedium = 0; iMedium < media->GetSize(); iMedium++ ) { + cout << "Medium " << iMedium << ": " + << ((TGeoMedium*) media->At(iMedium))->GetName() << endl; + } + gStsMedium = gGeoMan->GetMedium("air"); + if ( ! gStsMedium ) Fatal("Main", "medium sts_air not found"); + */ + // -------------------------------------------------------------------------- + + + // --------------- Create sensors --------------------------------------- + cout << endl << endl; + cout << "===> Creating sensors...." << endl << endl; + infoFile << endl << "Sensors: " << endl; + Int_t nSensors = CreateSensors(); + for (Int_t iSensor = 1; iSensor <= nSensors; iSensor++) { + TString name = Form("Sensor%02d",iSensor); + TGeoVolume* sensor = gGeoMan->GetVolume(name); + + // add color to sensors + if (iSensor == 1) + sensor->SetLineColor(kRed); + if (iSensor == 2) + sensor->SetLineColor(kGreen); + if (iSensor == 3) + sensor->SetLineColor(kBlue); + if (iSensor == 4) + sensor->SetLineColor(kAzure); + if (iSensor == 5) + sensor->SetLineColor(kYellow); + if (iSensor == 6) + sensor->SetLineColor(kYellow); + if (iSensor == 7) + sensor->SetLineColor(kYellow); + + CheckVolume(sensor); + CheckVolume(sensor, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create sectors -------------------------------------- + cout << endl << endl; + cout << "===> Creating sectors...." << endl; + // infoFile << endl << "Sectors: " << endl; + Int_t nSectors = CreateSectors(); + for (Int_t iSector = 1; iSector <= nSectors; iSector++) { + // cout << endl; + TString name = Form("Sector%02d", iSector); + TGeoVolume* sector = gGeoMan->GetVolume(name); + CheckVolume(sector); + // CheckVolume(sector, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create ladders -------------------------------------- + cout << endl << endl; + cout << "===> Creating ladders...." << endl; + infoFile << endl << "Ladders:" << endl; + + TString name = ""; + TGeoVolume* ladder; + + + Int_t nLadders = CreateLadders(); + + for (Int_t iLadder = 1; iLadder <= nLadders; iLadder++) { + cout << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType0%02d", iLadder); // v19b + name = Form("LadderType00%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF1: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType1%02d", iLadder); // v19b + name = Form("LadderType01%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF2: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType10%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF3: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType11%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF4: ladder name: " << name << endl << endl; + } + // -------------------------------------------------------------------------- + + + // ---------------- Create cones ---------------------------------------- + Double_t coneDz = 1.64; + TGeoVolume* coneSmallVolum = ConstructSmallCone(coneDz); + if (!coneSmallVolum) Fatal("ConstructSmallCone", "Volume Cone not found"); + TGeoVolume* coneBigVolum = ConstructBigCone(coneDz); + if (!coneBigVolum) Fatal("ConstructBigCone", "Volume Cone not found"); + // -------------------------------------------------------------------------- + + + // ---------------- Create stations ------------------------------------- + cout << endl << endl; + cout << "===> Creating stations...." << endl; + infoFile << endl << "Stations: " << endl; + Int_t angle = 0; + nLadders = 0; + Int_t ladderTypes[16]; // there are max 16 ladders in one layer + TGeoTranslation* statTrans = NULL; + + TGeoVolume *myunit[32]; // units + +// Int_t statPos[8] = { 30, 40, 50, 60, 70, 80, 90, 100 }; // z positions of stations +// Int_t statPos[16] = { 28, 32, 38, 42, 48, 52, 58, 62, +// 68, 72, 78, 82, 88, 92, 98,102 }; // z positions of units +// Int_t statPos[16] = { 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units +// Int_t statPos18[18] = { 30, 30, // expanded for placement of Unit00 +// 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units + // v19h + Double_t statPos[16] = { 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of units + Double_t statPos18[18] = { 26.0, 26.0, // expanded for placement of Unit00 + 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of unit + +// // v19d +// Double_t statPos[16] = { 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units +// Double_t statPos18[18] = { 30.0, 30.0, // expanded for placement of Unit00 +// 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units + +////Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.9 , 3.7 , 3.7 , 4.2 , 4.2 }; // size of cutouts in stations +// Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.43, 3.04, 3.35, 3.96, 4.2 }; // size of cutouts in stations, derived from gapXYZ[x][1]/2 + + Int_t cone_size[8] = { 0, 0, 0, 1, 1, 1, 1, 1 }; // size of cones: 0 = small, 1 = large + + Double_t cone_offset[2] = { 0.305, 0.285 }; + +// Int_t allLadderTypes[8][16]= +// { { -1, -1, -1, -1, 10, 109, 9, 101, 1, 109, 9, 110, -1, -1, -1, -1 }, // station 1 +// { -1, -1, 111, 10, 110, 9, 109, 2, 102, 9, 109, 10, 110, 11, -1, -1 }, // station 2 +// { -1, -1, 14, 113, 12, 112, 12, 103, 3, 112, 12, 112, 13, 114, -1, -1 }, // station 3 +// { -1, 15, 114, 13, 112, 12, 112, 4, 104, 12, 112, 12, 113, 14, 115, -1 }, // station 4 +// { -1, 119, 18, 117, 17, 116, 16, 105, 5, 116, 16, 117, 17, 118, 19, -1 }, // station 5 +// { -1, 19, 118, 17, 117, 16, 116, 6, 106, 16, 116, 17, 117, 18, 119, -1 }, // station 6 +// { 21, 119, 18, 120, 20, 120, 20, 107, 7, 120, 20, 120, 20, 118, 19, 121 }, // station 7 +// { 119, 17, 123, 22, 122, 22, 122, 8, 108, 22, 122, 22, 122, 23, 117, 19 } }; // station 8 + +//============================================================================================== + +// explanation: type xyzz +// where x = carbon ladder orientation +// where y = FEB box orientation +// where zz = sensor arrangement on ladder +// with FEB orientation - v19b + Int_t allUnitTypes[16][16]= + { { -1, -1, -1, -1, 10, 0, 9, 0, 101, 0, 109, 0, -1, -1, -1, -1 }, // unit00D Station01 00 + { -1, -1, -1, -1, 0, 1109, 0, 1101, 0, 1009, 0, 1010, -1, -1, -1, -1 }, // unit01U Station01 01 + + { -1, -1, 0, 10, 0, 9, 0, 2, 0, 109, 0, 110, 0, 111, -1, -1 }, // unit01D Station02 02 + { -1, -1, 1111, 0, 1110, 0, 1109, 0, 1002, 0, 1009, 0, 1010, 0, -1, -1 }, // unit02U Station02 03 + + { -1, -1, 14, 0, 12, 0, 12, 0, 103, 0, 112, 0, 113, 0, -1, -1 }, // unit02D Station03 04 + { -1, -1, 0, 1113, 0, 1112, 0, 1103, 0, 1012, 0, 1012, 0, 1014, -1, -1 }, // unit03U Station03 05 + + { -1, 15, 0, 13, 0, 12, 0, 4, 0, 112, 0, 112, 0, 114, 0, -1 }, // unit03D Station04 06 + { -1, 0, 1114, 0, 1112, 0, 1112, 0, 1004, 0, 1012, 0, 1013, 0, 1015, -1 }, // unit04U Station04 07 + + { -1, 0, 18, 0, 17, 0, 16, 0, 105, 0, 116, 0, 117, 0, 119, -1 }, // unit04D Station05 08 + { -1, 1119, 0, 1117, 0, 1116, 0, 1105, 0, 1016, 0, 1017, 0, 1018, 0, -1 }, // unit05U Station05 09 + + { -1, 19, 0, 17, 0, 16, 0, 6, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05D Station06 10 + { -1, 0, 1118, 0, 1117, 0, 1116, 0, 1006, 0, 1016, 0, 1017, 0, 1019, -1 }, // unit06U Station06 11 + + { 21, 0, 25, 0, 20, 0, 20, 0, 107, 0, 120, 0, 120, 0, 127, 0 }, // unit06D Station07 12 + { 0, 1127, 0, 1120, 0, 1120, 0, 1107, 0, 1020, 0, 1020, 0, 1025, 0, 1021 }, // unit07U Station07 13 + + { 0, 24, 0, 22, 0, 22, 0, 8, 0, 122, 0, 122, 0, 123, 0, 126 }, // unit07D Station08 14 + { 1126, 0, 1123, 0, 1122, 0, 1122, 0, 1008, 0, 1022, 0, 1022, 0, 1024, 0 } }; // unit08U Station08 15 + +//============================================================================================== + +// without FEB orientation - v19a +// v19a Int_t allUnitTypes[16][16]= +// v19a { { -1, -1, -1, -1, 10, 0, 9, 0, 1, 0, 9, 0, -1, -1, -1, -1 }, // unit00D Station01 00 +// v19a { -1, -1, -1, -1, 0, 109, 0, 101, 0, 109, 0, 110, -1, -1, -1, -1 }, // unit01U Station01 01 +// v19a { -1, -1, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, -1, -1 }, // unit01D Station02 02 +// v19a { -1, -1, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, -1, -1 }, // unit02U Station02 03 +// v19a { -1, -1, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, -1, -1 }, // unit02D Station03 04 +// v19a { -1, -1, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, -1, -1 }, // unit03U Station03 05 +// v19a { -1, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, -1 }, // unit03D Station04 06 +// v19a { -1, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, -1 }, // unit04U Station04 07 +// v19a { -1, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, -1 }, // unit04D Station05 08 +// v19a { -1, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05U Station05 09 +// v19a { -1, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, -1 }, // unit05D Station06 10 +// v19a { -1, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, -1 }, // unit06U Station06 11 +// v19a { 21, 0, 25, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 27, 0 }, // unit06D Station07 12 +// v19a { 0, 127, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 125, 0, 121 }, // unit07U Station07 13 +// v19a { 0, 24, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 26 }, // unit07D Station08 14 +// v19a { 126, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 124, 0 } }; // unit08U Station08 15 + + +// unitTypes[0] = { 0, 0, 0, 0, 10, 0, 9, 0, 1, 0, 9, 0, 0, 0, 0, 0 }; // unit 0D +// unitTypes[1] = { 0, 0, 0, 0, 0, 109, 0, 101, 0, 109, 0, 110, 0, 0, 0, 0 }; // unit 1U +// unitTypes[2] = { 0, 0, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, 0, 0 }; // unit 1D +// unitTypes[3] = { 0, 0, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, 0, 0 }; // unit 2U +// unitTypes[4] = { 0, 0, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, 0, 0 }; // unit 2D +// unitTypes[5] = { 0, 0, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, 0, 0 }; // unit 3U +// unitTypes[6] = { 0, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, 0 }; // unit 3D +// unitTypes[7] = { 0, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, 0 }; // unit 4U +// unitTypes[8] = { 0, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, 0 }; // unit 4D +// unitTypes[9] = { 0, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, 0 }; // unit 5U +// unitTypes[10] = { 0, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, 0 }; // unit 5D +// unitTypes[11] = { 0, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, 0 }; // unit 6U +// unitTypes[12] = { 21, 0, 18, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 19, 0 }; // unit 6D +// unitTypes[13] = { 0, 119, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 118, 0, 121 }; // unit 7U +// unitTypes[14] = { 0, 17, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 19 }; // unit 7D +// unitTypes[15] = { 119, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 117, 0 }; // unit 8U + + +// // generate unit +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) +// for (Int_t iLadder = 0; iLadder < 16; iLadder++) +// { +// allUnitTypes[iUnit][iLadder] = 0; +// if ((iUnit % 2 == 0) && (allLadderTypes[iUnit/2][iLadder] < 100)) // if carbon structure is oriented upstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// if ((iUnit % 2 == 1) && (allLadderTypes[iUnit/2][iLadder] >= 100)) // if carbon structure is oriented downstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// } + + + // dump unit + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << "DE unitTypes[" << iUnit << "] = { "; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + { + cout << allUnitTypes[iUnit][iLadder]; + if (iLadder < 15) + cout << ", "; + else + cout << " };"; + } + cout << endl; + } + + + // --- Units 01 - 16 + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << endl; + + nLadders = 0; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + if (allUnitTypes[iUnit][iLadder] >= 0) + { + ladderTypes[nLadders] = allUnitTypes[iUnit][iLadder]; + cout << "DE ladderTypes[" << nLadders << "] = " << allUnitTypes[iUnit][iLadder] << ";" << endl; + nLadders++; + } + myunit[iUnit*2+0] = ConstructUnit(0, iUnit*2+0, nLadders, ladderTypes, iUnit/2+1); + myunit[iUnit*2+1] = ConstructUnit(1, iUnit*2+1, nLadders, ladderTypes, iUnit/2+1); + +// if (gkConstructCones) { +// if (iUnit%2 == 0) +// angle = 90; +// else +// angle = -90; +// +// // upstream +// TGeoRotation* coneRot11 = new TGeoRotation; +// coneRot11->RotateZ(angle); +// coneRot11->RotateY(180); +// TGeoCombiTrans* conePosRot11 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-cone_offset[cone_size[iUnit]]-gkLadderGapZ/2., coneRot11); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 1, conePosRot11); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 1, conePosRot11); +// +// // downstream +// TGeoRotation* coneRot12 = new TGeoRotation; +// coneRot12->RotateZ(angle); +// TGeoCombiTrans* conePosRot12 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+cone_offset[cone_size[iUnit]]+gkLadderGapZ/2., coneRot12); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 2, conePosRot12); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 2, conePosRot12); +// +// myunit[iUnit]->GetShape()->ComputeBBox(); +// } + +// CheckVolume(myunit[iUnit]); +// CheckVolume(myunit[iUnit], infoFile); + if ((iUnit%2 == 0)||(iUnit == 15)) + { + CheckVolume(myunit[iUnit*2+0]); + CheckVolume(myunit[iUnit*2+0], infoFile); + CheckVolume(myunit[iUnit*2+1]); + CheckVolume(myunit[iUnit*2+1], infoFile); + } + infoFile << "Position z = " << statPos[iUnit] << endl; + } + // -------------------------------------------------------------------------- + + + // --------------- Create STS volume ------------------------------------ + cout << endl << endl; + cout << "===> Creating STS...." << endl; + +// // --- Determine size of STS box +// Double_t stsX = 0.; +// Double_t stsY = 0.; +// Double_t stsZ = 0.; +// Double_t stsBorder = 2*5.; // 5 cm space for carbon ladders on each side +// for (Int_t iStation = 1; iStation<=8; iStation++) { +// TString statName = Form("Station%02d", iStation); +// TGeoVolume* station = gGeoMan->GetVolume(statName); +// TGeoBBox* shape = (TGeoBBox*) station->GetShape(); +// stsX = TMath::Max(stsX, 2.* shape->GetDX() ); +// stsY = TMath::Max(stsY, 2.* shape->GetDY() ); +// cout << "Station " << iStation << ": Y " << stsY << endl; +// } +// // --- Some border around the stations +// stsX += stsBorder; +// stsY += stsBorder; +// stsZ = ( statPos[7] - statPos[0] ) + stsBorder; +// +// // --- Create box around the stations +// new TGeoBBox("stsBox", stsX/2., stsY/2., stsZ/2.); +// cout << "size of STS box: x " << stsX << " - y " << stsY << " - z " << stsZ << endl; +// +// // --- Create cone hosting the beam pipe +// // --- One straight section with constant radius followed by a cone +// Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +// Double_t z2 = gkPipeZ2; +// Double_t z3 = statPos[7] + 0.5 * stsBorder; // end of STS box +// Double_t r1 = BeamPipeRadius(z1); +// Double_t r2 = BeamPipeRadius(z2); +// Double_t r3 = BeamPipeRadius(z3); +// r1 += 0.01; // safety margin +// r2 += 0.01; // safety margin +// r3 += 0.01; // safety margin +// +// cout << endl; +// cout << z1 << " " << r1 << endl; +// cout << z2 << " " << r2 << endl; +// cout << z3 << " " << r3 << endl; +// +// cout << endl; +// cout << "station1 : " << BeamPipeRadius(statPos[0]) << endl; +// cout << "station2 : " << BeamPipeRadius(statPos[1]) << endl; +// cout << "station3 : " << BeamPipeRadius(statPos[2]) << endl; +// cout << "station4 : " << BeamPipeRadius(statPos[3]) << endl; +// cout << "station5 : " << BeamPipeRadius(statPos[4]) << endl; +// cout << "station6 : " << BeamPipeRadius(statPos[5]) << endl; +// cout << "station7 : " << BeamPipeRadius(statPos[6]) << endl; +// cout << "station8 : " << BeamPipeRadius(statPos[7]) << endl; +// +// // TGeoPcon* cutout = new TGeoPcon("stsCone", 0., 360., 3); // 2.*TMath::Pi(), 3); +// // cutout->DefineSection(0, z1, 0., r1); +// // cutout->DefineSection(1, z2, 0., r2); +// // cutout->DefineSection(2, z3, 0., r3); +// new TGeoTrd2("stsCone1", r1, r2, r1, r2, (z2-z1)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans1 = new TGeoTranslation("trans1", 0., 0., -(z3-z1)/2.+(z2-z1)/2.); +// trans1->RegisterYourself(); +// new TGeoTrd2("stsCone2", r2, r3, r2, r3, (z3-z2)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans2 = new TGeoTranslation("trans2", 0., 0., +(z3-z1)/2.-(z3-z2)/2.); +// trans2->RegisterYourself(); +// +////DE Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +////DE Double_t z2 = statPos[7] + 0.5 * stsBorder; // end of STS box +////DE Double_t slope = (gkPipeR2 - gkPipeR1) / (gkPipeZ2 - gkPipeZ1); +////DE Double_t r1 = gkPipeR1 + slope * (z1 - gkPipeZ1); // at start of STS +////DE Double_t r2 = gkPipeR1 + slope * (z2 - gkPipeZ1); // at end of STS +////DE r1 += 0.1; // safety margin +////DE r2 += 0.1; // safety margin +////DE // new TGeoCone("stsCone", stsZ/2., 0., r1, 0., r2); +////DE new TGeoTrd2("stsCone", r1, r2, r1, r2, stsZ/2.); + + + // // Create holding/cooling plates + // static std::vector< std::vector<Double_t> > plateSizes = { + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // }; + + // // 8-vertex cut-outs { minWidth, maxWidth, minHeight, maxHeight } + // static std::vector< std::vector<Double_t> > plateCutOuts = { + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 17.6, 47.6 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 49.0, 79.0 }, + // { 85.5,115.5, 51.5, 82.8 }, + // { 85.5,115.5, 59.0, 91.4 }, + // { 85.5,115.5, 68.0, 99.0 }, + // }; + + // for (Int_t iPlate = 0; iPlate < 9; iPlate++) { + // Int_t iUnit = iPlate * 2; + // TGeoBBox* outerPlate = new TGeoBBox(Form("outerPlate%02d",iPlate), + // plateSizes[iPlate][0], plateSizes[iPlate][1], plateSizes[iPlate][2]); + + // TGeoBBox* unitShapeR = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+0])->GetShape(); + // TGeoBBox* unitShapeL = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+1])->GetShape(); + + // Double_t maxDx = (unitShapeR->GetDX() + unitShapeL->GetDX()) / 2.; + // Double_t maxDy = TMath::Max(unitShapeR->GetDY(), unitShapeL->GetDY()); + // cout << maxDy << endl; + + // Double_t* cutOutX = new Double_t[8]; + // Double_t* cutOutY = new Double_t[8]; + + // cutOutX[0] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[0] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[1] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[1] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[2] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[2] = 1/2. * plateCutOuts[iPlate][2]; + // cutOutX[3] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[3] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[4] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[4] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[5] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[5] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[6] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[6] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[7] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[7] = 1/2. * plateCutOuts[iPlate][2]; + + // TGeoXtru* cutOutShape = new TGeoXtru(2); + // cutOutShape->SetName(Form("innerPlate%02d", iPlate)); + // cutOutShape->DefinePolygon(8, cutOutX, cutOutY); + // cutOutShape->DefineSection(0, -1*plateSizes[iPlate][2]-1e-7); + // cutOutShape->DefineSection(1, +1*plateSizes[iPlate][2]+1e-7); + + // TGeoShape* plateShape = new TGeoCompositeShape(Form("PlateShape%02d",iPlate), Form("outerPlate%02d-innerPlate%02d",iPlate,iPlate)); + // TGeoVolume* plate = new TGeoVolume(Form("Plate%02d", iPlate), plateShape, gGeoManager->GetMedium("aluminium")); + // plate->SetLineColor(kRed); + // plate->SetTransparency(65); + // plate->GetShape()->ComputeBBox(); + // } + + // --- Create STS volume + TString stsName = "sts_"; + stsName += geoTag; + +// TGeoShape* stsShape = new TGeoCompositeShape("stsShape", +// "stsBox-stsCone1:trans1-stsCone2:trans2"); +// TGeoVolume* sts = new TGeoVolume(stsName.Data(), stsShape, gStsMedium); + + Double_t stsBorder = 2 * 5.; + + TGeoVolume* sts = new TGeoVolumeAssembly(stsName.Data()); + + // --- Place stations in the STS + Double_t stsPosZ = 0.5 * ( statPos[15] + statPos[0] ); // todo units: update statPos[7] + // cout << "stsPosZ " << stsPosZ << " " << statPos[15] << " " << statPos[0] << "*****" << endl; + +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) { + for (Int_t iUnit = 0; iUnit < 18; iUnit++) { +// for (Int_t iUnit = 0; iUnit < 32; iUnit++) { + TGeoVolume* station = gGeoMan->GetVolume(unitName18[iUnit]); +// Double_t posZ = statPos[iUnit] - stsPosZ; + Double_t posZ = statPos18[iUnit] - stsPosZ; +// Double_t posZ = statPos[iUnit/2] - stsPosZ; + TGeoTranslation* trans = new TGeoTranslation(0., 0., posZ); + sts->AddNode(station, iUnit+1, trans); + sts->GetShape()->ComputeBBox(); + } + + // --- Import passive elements from GDML file + if (gkImportPassive) { + ImportPassive(sts, geoTag, infoFile); + } + + cout << endl; + CheckVolume(sts); + // -------------------------------------------------------------------------- + + + // --------------- Finish ----------------------------------------------- + TGeoTranslation* stsTrans = new TGeoTranslation(0., 0., stsPosZ); + top->AddNode(sts, 1, stsTrans); + top->GetShape()->ComputeBBox(); + cout << endl << endl; + + CheckVolume(top); + cout << endl << endl; + gGeoMan->CloseGeometry(); + gGeoMan->CheckOverlaps(0.0001); + gGeoMan->PrintOverlaps(); + gGeoMan->CheckOverlaps(0.0001, "s"); + gGeoMan->PrintOverlaps(); + gGeoMan->Test(); + + TFile* geoFile = new TFile(geoFileName, "RECREATE"); + top->Write(); + cout << endl; + cout << "Geometry " << top->GetName() << " written to " + << geoFileName << endl; + geoFile->Close(); + + TString geoFileName_ = "sts_"; + geoFileName_ = geoFileName_ + geoTag + "_geo.root"; + + geoFile = new TFile(geoFileName_, "RECREATE"); + gGeoMan->Write(); // use this is you want GeoManager format in the output + geoFile->Close(); + + TString geoFileName__ = "sts_"; + geoFileName_ = geoFileName__ + geoTag + "-geo.root"; + sts->Export(geoFileName_); + + geoFile = new TFile(geoFileName_, "UPDATE"); + stsTrans->Write(); + geoFile->Close(); + + // gGeoManager->FindVolumeFast("LadderType10_CarbonElement")->Draw("ogl"); + top->Draw("ogl"); + gGeoManager->SetVisLevel(8); + + infoFile.close(); + +} +// ============================================================================ +// ====== End of main function ===== +// ============================================================================ + + + + + +// **************************************************************************** +// ***** Definition of media, sensors, sectors and ladders ***** +// ***** ***** +// ***** Decoupled from main function for better readability ***** +// **************************************************************************** + + +/** =========================================================================== + ** Create media + ** + ** Currently created: air, active silicon, passive silion + ** + ** Not used for the time being + **/ +Int_t CreateMedia() { + + Int_t nMedia = 0; + Double_t density = 0.; + + // --- Material air + density = 1.205e-3; // [g/cm^3] + TGeoMixture* matAir = new TGeoMixture("sts_air", 3, density); + matAir->AddElement(14.0067, 7, 0.755); // Nitrogen + matAir->AddElement(15.999, 8, 0.231); // Oxygen + matAir->AddElement(39.948, 18, 0.014); // Argon + + // --- Material silicon + density = 2.33; // [g/cm^3] + TGeoElement* elSi = gGeoMan->GetElementTable()->GetElement(14); + TGeoMaterial* matSi = new TGeoMaterial("matSi", elSi, density); + + + // --- Air (passive) + TGeoMedium* medAir = new TGeoMedium("air", nMedia++, matAir); + medAir->SetParam(0, 0.); // is passive + medAir->SetParam(1, 1.); // is in magnetic field + medAir->SetParam(2, 20.); // max. field [kG] + medAir->SetParam(6, 0.001); // boundary crossing precision [cm] + + + // --- Active silicon for sensors + TGeoMedium* medSiAct = new TGeoMedium("silicon", + nMedia++, matSi); + medSiAct->SetParam(0, 1.); // is active + medSiAct->SetParam(1, 1.); // is in magnetic field + medSiAct->SetParam(2, 20.); // max. field [kG] + medSiAct->SetParam(6, 0.001); // boundary crossing precisison [cm] + + // --- Passive silicon for cables + TGeoMedium* medSiPas = new TGeoMedium("carbon", + nMedia++, matSi); + medSiPas->SetParam(0, 0.); // is passive + medSiPas->SetParam(1, 1.); // is in magnetic field + medSiPas->SetParam(2, 20.); // max. field [kG] + medSiPas->SetParam(6, 0.001); // boundary crossing precisison [cm] + + return nMedia; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sensors + ** + ** Sensors are created as volumes with box shape and active silicon as medium. + ** Four kinds of sensors: 3.2x2.2, 6.2x2.2, 6.2x4.2, 6.2x6.2 + **/ +Int_t CreateSensors() { + + Int_t nSensors = 0; + + Double_t xSize = 0.; + Double_t ySize = 0.; + Double_t zSize = gkSensorThickness; + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + + + // --- Sensor type 01: Small sensor (6.2 cm x 2.2 cm) + xSize = gkSensorSizeX; + ySize = 2.2; + TGeoBBox* shape_sensor01 = new TGeoBBox("sensor01", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor01", shape_sensor01, silicon); + nSensors++; + + + // --- Sensor type 02: Medium sensor (6.2 cm x 4.2 cm) + xSize = gkSensorSizeX; + ySize = 4.2; + TGeoBBox* shape_sensor02 = new TGeoBBox("sensor02", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor02", shape_sensor02, silicon); + nSensors++; + + + // --- Sensor type 03: Big sensor (6.2 cm x 6.2 cm) + xSize = gkSensorSizeX; + ySize = 6.2; + TGeoBBox* shape_sensor03 = new TGeoBBox("sensor03", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor03", shape_sensor03, silicon); + nSensors++; + + + // --- Sensor type 04: Big sensor (6.2 cm x 12.4 cm) + xSize = gkSensorSizeX; + ySize = 12.4; + TGeoBBox* shape_sensor04 = new TGeoBBox("sensor04", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor04", shape_sensor04, silicon); + nSensors++; + + + // below are extra small sensors, those are not available in the CAD model + + // --- Sensor Type 05: Half small sensor (4 cm x 2.5 cm) + xSize = 4.0; + ySize = 2.5; + TGeoBBox* shape_sensor05 = new TGeoBBox("sensor05", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor05", shape_sensor05, silicon); + nSensors++; + + + // --- Sensor type 06: Additional "in hole" sensor (3.1 cm x 4.2 cm) + xSize = 3.1; + ySize = 4.2; + TGeoBBox* shape_sensor06 = new TGeoBBox("sensor06", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor06", shape_sensor06, silicon); + nSensors++; + + + // --- Sensor type 07: Mini Medium sensor (1.5 cm x 4.2 cm) + xSize = 1.5; + ySize = 4.2; + TGeoBBox* shape_sensor07 = new TGeoBBox("sensor07", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor07", shape_sensor07, silicon); + nSensors++; + + + return nSensors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sectors + ** + ** A sector is either a single sensor or several chained sensors. + ** It is implemented as TGeoVolumeAssembly. + ** Currently available: + ** - single sensors of type 1 - 4 + ** - two chained sensors of type 4 + ** - three chained sensors of type 4 + **/ +Int_t CreateSectors() { + + Int_t nSectors = 0; + + TGeoVolume* sensor01 = gGeoMan->GetVolume("Sensor01"); + TGeoVolume* sensor02 = gGeoMan->GetVolume("Sensor02"); + TGeoVolume* sensor03 = gGeoMan->GetVolume("Sensor03"); + TGeoVolume* sensor04 = gGeoMan->GetVolume("Sensor04"); + TGeoVolume* sensor05 = gGeoMan->GetVolume("Sensor05"); + TGeoVolume* sensor06 = gGeoMan->GetVolume("Sensor06"); + TGeoVolume* sensor07 = gGeoMan->GetVolume("Sensor07"); + // TGeoBBox* box4 = (TGeoBBox*) sensor04->GetShape(); + + // --- Sector type 1: single sensor of type 1 + TGeoVolumeAssembly* sector01 = new TGeoVolumeAssembly("Sector01"); + sector01->AddNode(sensor01, 1); + sector01->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 2: single sensor of type 2 + TGeoVolumeAssembly* sector02 = new TGeoVolumeAssembly("Sector02"); + sector02->AddNode(sensor02, 1); + sector02->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 3: single sensor of type 3 + TGeoVolumeAssembly* sector03 = new TGeoVolumeAssembly("Sector03"); + sector03->AddNode(sensor03, 1); + sector03->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 4: single sensor of type 4 + TGeoVolumeAssembly* sector04 = new TGeoVolumeAssembly("Sector04"); + sector04->AddNode(sensor04, 1); + sector04->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 5: single sensor of type 5 + TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); + sector05->AddNode(sensor05, 1); + sector05->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 6: single sensor of type 6 + TGeoVolumeAssembly* sector06 = new TGeoVolumeAssembly("Sector06"); + sector06->AddNode(sensor06, 1); + sector06->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 7: single sensor of type 7 + TGeoVolumeAssembly* sector07 = new TGeoVolumeAssembly("Sector07"); + sector07->AddNode(sensor07, 1); + sector07->GetShape()->ComputeBBox(); + nSectors++; + +// // --- Sector type 5: two sensors of type 4 +// TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); +// Double_t shift5 = 0.5 * gkChainGapY + box4->GetDY(); +// TGeoTranslation* transD5 = +// new TGeoTranslation("td", 0., -1. * shift5, 0.); +// TGeoTranslation* transU5 = +// new TGeoTranslation("tu", 0., shift5, 0.); +// sector05->AddNode(sensor04, 1, transD5); +// sector05->AddNode(sensor04, 2, transU5); +// sector05->GetShape()->ComputeBBox(); +// nSectors++; + + return nSectors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create ladders + ** + ** Ladders are the building blocks of the stations. They contain + ** several modules placed one after the other along the z axis + ** such that the sectors are arranged vertically (with overlap). + ** + ** A ladder is constructed out of two half ladders, the second of which + ** is rotated in the x-y plane by 180 degrees and displaced + ** in z direction. + **/ +Int_t CreateLadders() { + + Int_t nLadders = 0; + + // --- Some variables + Int_t nSectors = 0; + Int_t sectorTypes[10]; + TGeoBBox* shape = NULL; + TString s0name; + TString hlname; + char align; + TGeoVolume* s0vol = NULL; + TGeoVolume* halfLadderU = NULL; + TGeoVolume* halfLadderD = NULL; + + // --- Ladders 01-23 + Int_t allSectorTypes[27][6] = { { 1, 2, 3, 3, 0, -1 }, // ladder 01 - 5 - last column defines alignment of small sensors + { 1, 2, 3, 3, 0, 0 }, // ladder 02 - 5 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, -1 }, // ladder 03 - 6 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 04 - 6 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, -1 }, // ladder 05 - 7 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 06 - 7 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 07 - last column defines alignment of small sensors + { 3, 4, 4, 4, 0, 0 }, // ladder 08 - last column defines alignment of small sensors + + { 1, 1, 2, 3, 3, 0 }, // ladder 09 - last column defines alignment of small sensors + { 1, 1, 2, 2, 3, 0 }, // ladder 10 - last column defines alignment of small sensors + { 2, 2, 0, 0, 0, 0 }, // ladder 11 - last column defines alignment of small sensors + { 2, 2, 2, 3, 4, 0 }, // ladder 12 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 13 - last column defines alignment of small sensors + + { 2, 3, 4, 0, 0, 0 }, // ladder 14 - last column defines alignment of small sensors + { 3, 3, 0, 0, 0, 0 }, // ladder 15 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 16 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 17 - last column defines alignment of small sensors + { 3, 4, 4, 0, 0, 0 }, // ladder 18 - last column defines alignment of small sensors + + { 4, 4, 0, 0, 0, 0 }, // ladder 19 - last column defines alignment of small sensors + { 1, 2, 4, 4, 4, 0 }, // ladder 20 - last column defines alignment of small sensors + { 4, 0, 0, 0, 0, 0 }, // ladder 21 - last column defines alignment of small sensors + { 2, 3, 4, 4, 4, 0 }, // ladder 22 - last column defines alignment of small sensors + { 2, 3, 3, 4, 4, 0 }, // ladder 23 - last column defines alignment of small sensors + + { 2, 3, 4, 4, 0, 0 }, // ladder 24 - copy of 17 with different total length + { 3, 4, 4, 0, 0, 0 }, // ladder 25 - copy of 18 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 26 - copy of 19 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 27 - copy of 19 with different total length + }; + +// Issue #405 +// Counting from the most upstream ladder, the gaps between sensors are as follows: +// 01 (most upstream): 41.3mm +// 02: 41.3mm +// 03: 42.0mm +// 04: 48.6mm +// 05: 60.8mm +// 06: 67.0mm +// 07: 79.2mm +// 08 (most downstream): 88.0mm + + Double_t gapXYZ[27][3] = { + { 0., 4.13, 0. }, // ladder 01 + { 0., 4.13, 0. }, // ladder 02 + { 0., 4.20, 0. }, // ladder 03 + { 0., 4.86, 0. }, // ladder 04 + { 0., 6.08, 0. }, // ladder 05 + { 0., 6.70, 0. }, // ladder 06 + { 0., 7.92, 0. }, // ladder 07 + { 0., 8.80, 0. }, // ladder 08 + { 0., -gkSectorOverlapY, 0. }, // ladder 09 + { 0., -gkSectorOverlapY, 0. }, // ladder 10 + { 0., -gkSectorOverlapY, 0. }, // ladder 11 + { 0., -gkSectorOverlapY, 0. }, // ladder 12 + { 0., -gkSectorOverlapY, 0. }, // ladder 13 + { 0., -gkSectorOverlapY, 0. }, // ladder 14 + { 0., -gkSectorOverlapY, 0. }, // ladder 15 + { 0., -gkSectorOverlapY, 0. }, // ladder 16 + { 0., -gkSectorOverlapY, 0. }, // ladder 17 + { 0., -gkSectorOverlapY, 0. }, // ladder 18 + { 0., -gkSectorOverlapY, 0. }, // ladder 19 + { 0., -gkSectorOverlapY, 0. }, // ladder 20 + { 0., -gkSectorOverlapY, 0. }, // ladder 21 + { 0., -gkSectorOverlapY, 0. }, // ladder 22 + { 0., -gkSectorOverlapY, 0. }, // ladder 23 + + { 0., -gkSectorOverlapY, 0. }, // ladder 24 - copy of 17 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 25 - copy of 18 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 26 - copy of 19 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 27 - copy of 19 with different total length + }; + + Double_t ladderLength[27] = { + 48.0, // ladder 01 + 48.0, // ladder 02 + 64.0, // ladder 03 + 64.0, // ladder 04 + 80.0, // ladder 05 + 80.0, // ladder 06 + 92.0, // ladder 07 + 96.0, // ladder 08 + 48.0, // ladder 09 + 48.0, // ladder 10 + 48.0, // ladder 11 + 64.0, // ladder 12 + 64.0, // ladder 13 + 64.0, // ladder 14 + 64.0, // ladder 15 + 80.0, // ladder 16 + 80.0, // ladder 17 + 80.0, // ladder 18 + 80.0, // ladder 19 + 92.0, // ladder 20 + 92.0, // ladder 21 + 96.0, // ladder 22 + 96.0, // ladder 23 + + 96.0, // ladder 24 - copy of 17 with different total length + 92.0, // ladder 25 - copy of 18 with different total length + 96.0, // ladder 26 - copy of 19 with different total length + 92.0, // ladder 27 - copy of 19 with different total length + }; +// ======================================================================== + + // calculate Z shift for ladders with and without gaps in the center + s0name = Form("Sector%02d", allSectorTypes[0][0]); + s0vol = gGeoMan->GetVolume(s0name); + shape = (TGeoBBox*) s0vol->GetShape(); + + for (Int_t iLadder = 0; iLadder < 27; iLadder++) + { + if (iLadder+1 <= 8) // for the 2 inner ladders of each station with gap for beampipe + gapXYZ[iLadder][2] = 0; // there is no offset in z for halfladders on ladders with a beampipe hole + else + gapXYZ[iLadder][2] = 2. * shape->GetDZ() + gkSectorGapZ; // set displacement in z for overlapping half ladders + } + +// ======================================================================== + + for (Int_t iLadder = 0; iLadder < 27; iLadder++) + { + cout << endl; + nSectors = 0; + for (Int_t i=0; i < 5; i++) + if (allSectorTypes[iLadder][i] != 0) + { + sectorTypes[nSectors] = allSectorTypes[iLadder][i]; // copy sectors for this ladder + cout << "DE iLadder " << iLadder+1 << " sectorTypes[" << nSectors << "] = " << allSectorTypes[iLadder][i] << ";" << endl; + nSectors++; // count how many sectors are in this ladder + } + + if (allSectorTypes[iLadder][5] == 0) + align = 'l'; + else + align = 'r'; + hlname = Form("HalfLadder%02du", iLadder+1); + // build upper half ladder + halfLadderU = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2.); // mirrored + + if (allSectorTypes[iLadder][5] == 0) + align = 'r'; + else + align = 'l'; + hlname = Form("HalfLadder%02dd", iLadder+1); + // build lower half ladder + halfLadderD = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2.); // mirrored + + // at this point half ladders are constructed + + // build all 4 possible ladders types for this sensor arrangement + ConstructLadder( iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19a + ConstructLadder( 100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19b + + ConstructLadder(1000+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19k + ConstructLadder(1100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]); // v19k + + nLadders++; + } + + return nLadders; +} +/** ======================================================================= **/ + + + +// **************************************************************************** +// ***** ***** +// ***** Generic functions for the construction of STS elements ***** +// ***** ***** +// ***** module: volume (made of a sector and a cable) ***** +// ***** haf ladder: assembly (made of modules) ***** +// ***** ladder: assembly (made of two half ladders) ***** +// ***** station: volume (made of ladders) ***** +// ***** ***** +// **************************************************************************** + + + +/** =========================================================================== + ** Construct a module + ** + ** A module is a sector plus the readout cable extending from the + ** top of the sector. The cable is made from passive silicon. + ** The cable has the same x size as the sector. + ** Its thickness is given by the global variable gkCableThickness. + ** The cable length is a parameter. + ** The sensor(s) of the sector is/are placed directly in the module; + ** the sector is just auxiliary for the proper placement. + ** + ** Arguments: + ** name volume name + ** sector pointer to sector volume + ** cableLength length of cable + **/ +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength) { + + // --- Check sector volume + if ( ! sector ) Fatal("CreateModule", "Sector volume not found!"); + + // --- Get size of sector + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + + // --- Get size of cable + Double_t cableX = sectorX; + Double_t cableY = cableLength; + Double_t cableZ = gkCableThickness; + + // --- Create module volume + Double_t moduleX = TMath::Max(sectorX, cableX); + Double_t moduleY = sectorY + cableLength; + + Double_t moduleZ = TMath::Max(sectorZ, cableZ); + + TGeoVolume* module = gGeoManager->MakeBox(name, gStsMedium, + moduleX/2., + moduleY/2., + moduleZ/2.); + + // --- Position of sector in module + // --- Sector is centred in x and z and aligned to the bottom + Double_t sectorXpos = 0.; + Double_t sectorYpos = 0.5 * (sectorY - moduleY); + Double_t sectorZpos = 0.; + + + // --- Get sensor(s) from sector + Int_t nSensors = sector->GetNdaughters(); + for (Int_t iSensor = 0; iSensor < nSensors; iSensor++) { + TGeoNode* sensor = sector->GetNode(iSensor); + + // --- Calculate position of sensor in module + const Double_t* xSensTrans = sensor->GetMatrix()->GetTranslation(); + Double_t sensorXpos = 0.; + Double_t sensorYpos = sectorYpos + xSensTrans[1]; + Double_t sensorZpos = 0.; + TGeoTranslation* sensTrans = new TGeoTranslation("sensTrans", + sensorXpos, + sensorYpos, + sensorZpos); + + // --- Add sensor volume to module + TGeoVolume* sensVol = sensor->GetVolume(); + module->AddNode(sensor->GetVolume(), iSensor+1, sensTrans); + module->GetShape()->ComputeBBox(); + } + + + // --- Create cable volume, if necessary, and place it in module + // --- Cable is centred in x and z and aligned to the top + if ( gkConstructCables && cableLength > 0.0001 ) { + TString cableName = TString(name) + "_cable"; + TGeoMedium* cableMedium = gGeoMan->GetMedium("STScable"); + if ( ! cableMedium ) Fatal("CreateModule", "Medium STScable not found!"); + TGeoVolume* cable = gGeoManager->MakeBox(cableName.Data(), + cableMedium, + cableX / 2., + cableY / 2., + cableZ / 2.); + // add color to cables + cable->SetLineColor(kOrange); + cable->SetTransparency(60); + Double_t cableXpos = 0.; + Double_t cableYpos = sectorY + 0.5 * cableY - 0.5 * moduleY; + Double_t cableZpos = 0.; + TGeoTranslation* cableTrans = new TGeoTranslation("cableTrans", + cableXpos, + cableYpos, + cableZpos); + module->AddNode(cable, 1, cableTrans); + module->GetShape()->ComputeBBox(); + } + + return module; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a half ladder + ** + ** A half ladder is a virtual volume (TGeoVolumeAssembly) consisting + ** of several modules arranged on top of each other. The modules + ** have a given overlap in y and a displacement in z to allow for the + ** overlap. + ** + ** The typ of sectors / modules to be placed must be specified: + ** 1 = sensor01 + ** 2 = sensor02 + ** 3 = sensor03 + ** 4 = sensor04 + ** 5 = 2 x sensor04 (chained) + ** 6 = 3 x sensor04 (chained) + ** The cable is added automatically from the top of each sensor to + ** the top of the half ladder. + ** The alignment can be left (l) or right (r), which matters in the + ** case of different x sizes of sensors (e.g. SensorType01). + ** + ** Arguments: + ** name volume name + ** nSectors number of sectors + ** sectorTypes array with sector types + ** align horizontal alignment of sectors + * ladderLength full length of the ladder towards FEE + * offsetY gap in the beam-pipe region + **/ +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY) { + + // --- Create half ladder volume assembly + TGeoVolumeAssembly* halfLadder = new TGeoVolumeAssembly(name); + + // --- Determine size of ladder + Double_t ladderX = 0.; + Double_t ladderY = 0.; + Double_t ladderZ = 0.; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + if ( ! sector ) + Fatal("ConstructHalfLadder", Form("Volume %s not found", sectorName.Data())); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + // --- Ladder x size equals largest sector x size + ladderX = TMath::Max(ladderX, 2. * box->GetDX()); + // --- Ladder y size is sum of sector ysizes + ladderY += 2. * box->GetDY(); + // --- Ladder z size is sum of sector z sizes + ladderZ += 2. * box->GetDZ(); + } + // --- Subtract overlaps in y + ladderY -= Double_t(nSectors-1) * gkSectorOverlapY; + // --- Add gaps in z direction + ladderZ += Double_t(nSectors-1) * gkSectorGapZ; + + ladderY = TMath::Max(ladderLength - offsetY, ladderY); + + // --- Create and place modules + Double_t yPosSect = -0.5 * ladderY; + Double_t zPosMod = -0.5 * ladderZ; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + yPosSect += 0.5 * sectorY; // Position of sector in ladder + Double_t cableLength = 0.5 * ladderY - yPosSect - 0.5 * sectorY; + TString moduleName = name + "_" + Form("Module%02d", + sectorTypes[iSector]); + TGeoVolume* module = ConstructModule(moduleName.Data(), + sector, cableLength); + + TGeoBBox* shapeMod = (TGeoBBox*) module->GetShape(); + Double_t moduleX = 2. * shapeMod->GetDX(); + Double_t moduleY = 2. * shapeMod->GetDY(); + Double_t moduleZ = 2. * shapeMod->GetDZ(); + Double_t xPosMod = 0.; + if ( align == 'l' ) + xPosMod = 0.5 * (moduleX - ladderX); // left aligned + else if ( align == 'r' ) + xPosMod = 0.5 * (ladderX - moduleX); // right aligned + else + xPosMod = 0.; // centred in x + Double_t yPosMod = 0.5 * (ladderY - moduleY); // top aligned + zPosMod += 0.5 * moduleZ; + TGeoTranslation* trans = new TGeoTranslation("t", xPosMod, + yPosMod, zPosMod); + halfLadder->AddNode(module, iSector+1, trans); + halfLadder->GetShape()->ComputeBBox(); + yPosSect += 0.5 * sectorY - gkSectorOverlapY; + zPosMod += 0.5 * moduleZ + gkSectorGapZ; + } + + CheckVolume(halfLadder); + cout << endl; + + return halfLadder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Add a carbon support to a ladder + ** + ** Arguments: + ** LadderIndex ladder number + ** ladder pointer to ladder + ** xu size of halfladder + ** ladderY height of ladder along y + ** ladderZ thickness of ladder along z + **/ +void AddCarbonLadder(Int_t LadderIndex, + TGeoVolume* ladder, + Double_t xu, + Double_t ladderY, + Double_t ladderZ) { + + // --- Some variables + TString name = Form("LadderType%04d", LadderIndex); // v19k + Int_t i; + Double_t j; + + Int_t YnumOfFrameBoxes = round(ladderY / gkFrameStep); + + // cout << "DEXZ: lad " << LadderIndex << " inum " << YnumOfFrameBoxes << endl; + + Double_t ladderDZ = (xu/2. + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2)/2.; + cout << "DEFR: frame Z size " << 2 * ladderDZ << " cm" << endl; + + TGeoBBox* fullFrameShp = new TGeoBBox (name+"_CarbonElement_shp", xu/2., gkFrameStep/2., ladderDZ); + TGeoVolume* fullFrameBoxVol = new TGeoVolume(name+"_CarbonElement", fullFrameShp, gStsMedium); + + ConstructFrameElement("CarbonElement", fullFrameBoxVol, xu/2.); + TGeoRotation* fullFrameRot = new TGeoRotation; + fullFrameRot->RotateY(180); + + Int_t inum = YnumOfFrameBoxes; + for (i=1; i<=inum; i++) + { + j=-(inum-1)/2.+(i-1); + // -(10-1)/2. +0 +10-1 -> -4.5 .. +4.5 -> -0.5, +0.5 (= 2) + // -(11-1)/2. +0 +11-1 -> -5.0 .. +5.0 -> -1, 0, 1 (= 3) + // cout << "DE: i " << i << " j " << j << endl; + + if (LadderIndex % 100 <= 3) // central ladders in stations 1 to 3 + { + if ((j>=-1) && (j<=1)) // keep the inner 2 (even) or 3 (odd) elements free for the cone + continue; + } + else if (LadderIndex % 100 <= 8) // central ladders in stations 4 to 8 + { + if ((j>=-2) && (j<=2)) // keep the inner 4 elements free for the cone + continue; + } + + cout << "DELZ: ladderDZ " << ladderDZ << " cm " << -ladderZ/2. - ladderDZ << " cm " << endl; + ladder->AddNode(fullFrameBoxVol, i, new TGeoCombiTrans(name+"_CarbonElement_posrot", 0., j*gkFrameStep, -(ladderZ/2.+ladderDZ), fullFrameRot)); + } + + ladder->GetShape()->ComputeBBox(); + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Construct a ladder out of two half ladders with vertical gap + ** + ** The second half ladder will be rotated by 180 degrees + ** in the x-y plane. The two half ladders will be put on top of each + ** other with a vertical gap. + ** + ** Arguments: + ** name volume name + ** halfLadderU pointer to upper half ladder + ** halfLadderD pointer to lower half ladder + ** gapY vertical gap + ** shiftZ relative displacement along the z axis + **/ + + TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ) { + + // --- Some variables + TGeoBBox* shape = NULL; + + // --- Dimensions of half ladders + shape = (TGeoBBox*) halfLadderU->GetShape(); + Double_t xu = 2. * shape->GetDX(); + Double_t yu = 2. * shape->GetDY(); + Double_t zu = 2. * shape->GetDZ(); + + shape = (TGeoBBox*) halfLadderD->GetShape(); + Double_t xd = 2. * shape->GetDX(); + Double_t yd = 2. * shape->GetDY(); + Double_t zd = 2. * shape->GetDZ(); + + + // --- Create ladder volume assembly + +// TString name = Form("LadderType%02d", LadderIndex); // v19a +// TString name = Form("LadderType%03d", LadderIndex); // v19b + TString name = Form("LadderType%04d", LadderIndex); // v19k + TGeoVolumeAssembly* ladder = new TGeoVolumeAssembly(name); + Double_t ladderX = TMath::Max(xu, xd); + Double_t ladderY = yu + yd + gapY; + Double_t ladderZ = TMath::Max(zu, zd + shiftZ); + + // --- Place half ladders + Double_t xPosU = 0.; // centred in x + Double_t yPosU = 0.5 * ( ladderY - yu ); // top aligned + Double_t zPosU = 0.5 * ( ladderZ - zu ); // front aligned // mount upper half ladder last + if (LadderIndex >= 1000) zPosU = -zPosU; // back aligned // mount upper half ladder first + + TGeoTranslation* tu = new TGeoTranslation("tu", xPosU, yPosU, zPosU); + ladder->AddNode(halfLadderU, 1, tu); + + Double_t xPosD = 0.; // centred in x + Double_t yPosD = 0.5 * ( yd - ladderY ); // bottom aligned + Double_t zPosD = 0.5 * ( zd - ladderZ ); // back aligned // mount lower half ladder first + if (LadderIndex >= 1000) zPosD = -zPosD; // front aligned // mount lower half ladder last + + TGeoRotation* rd = new TGeoRotation(); + rd->RotateZ(180.); + TGeoCombiTrans* cd = new TGeoCombiTrans(xPosD, yPosD, zPosD, rd); + ladder->AddNode(halfLadderD, 2, cd); + + ladder->GetShape()->ComputeBBox(); + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD0ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + cout << "DDDD ladder" << LadderIndex << endl; + cout << "DDDD1ladder" << LadderIndex << " ladderX " << ladderX << " ladderY " << ladderY << " ladderZ " << ladderZ << endl; + + // ---------------- Create and place frame boxes ------------------------ + + if (gkConstructFrames) + AddCarbonLadder(LadderIndex, ladder, ladderX, ladderY, ladderZ); + + // -------------------------------------------------------------------------- + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD2ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + return ladder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a unit + ** + ** The unit volume is the minimal box comprising all ladders + ** minus a tube accomodating the beam pipe. + ** + ** The ladders are arranged horizontally from left to right with + ** a given overlap in x. + ** Every second ladder is slightly displaced upstream from the centre + ** z plane and facing downstream, the others are slightly displaced + ** downstream and facing upstream (rotated around the y axis). + ** + ** Arguments: + ** name volume name + ** nLadders number of ladders + ** ladderTypes array of ladder types + **/ + + TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation) { + + Bool_t isFirstPartOfHalfUnit = kFALSE; + + // TString name = Form("Unit%02d", iUnit); // 0,1,2,3,4,5,6,7 - Unit00 missing in output + // TString name = Form("Unit%02d", iUnit+1); // 1,2,3,4,5,6,7,8 + + TGeoVolume* unit = gGeoMan->GetVolume(unitName[iUnit]); + if ( ! unit ) // if it does not yet exist, create a new one + { + unit = new TGeoVolumeAssembly(unitName[iUnit]); + isFirstPartOfHalfUnit = kTRUE; + } + + // --- Some local variables + TGeoBBox* ladderShape = NULL; + TGeoVolume* ladder = NULL; + TString ladderName; + Double_t subtractedVal; + + // --- Determine size of unit from ladders + Double_t statX = 0.; + // Double_t statY = 0.; + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { +// Int_t ladderType = ladderTypes[iLadder]%100; // v19a +// Int_t ladderType = ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100; // v19b + Int_t ladderType = ladderTypes[iLadder]; // v19k + +// if (iSide == 0) cout << "DWER " << ladderTypes[iLadder] << " " << ladderType << endl; + + if (ladderType > 0) + { +// ladderName = Form("LadderType%02d", ladderType); // v19a +// ladderName = Form("LadderType%03d", ladderType); // v19b + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + if ( ! ladder ) Fatal("ConstructUnit", + Form("Volume %s not found", ladderName.Data())); + ladderShape = (TGeoBBox*) ladder->GetShape(); + statX += 2. * ladderShape->GetDX(); + // statY = TMath::Max(statY, 2. * ladderShape->GetDY()); + } + else + statX += gkSensorSizeX; // empty ladder in unit + } + statX -= Double_t(nLadders-1) * gkLadderOverlapX; + +// if (iSide == 0) cout << "DWER -" << endl; + + // --- Place ladders in unit + cout << "xPos0: " << statX << endl; + Double_t xPos = -0.5 * statX; + cout << "xPos1: " << xPos << endl; + Double_t yPos = 0.; + Double_t zPos = 0.; + + Double_t maxdz = 0.; + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { // find maximum dz in this unit +// Int_t ladderType = ladderTypes[iLadder]%100; // v19a +// Int_t ladderType = ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100; // v19b + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { +// ladderName = Form("LadderType%02d", ladderType); // v19a +// ladderName = Form("LadderType%03d", ladderType); // v19b + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + if (maxdz < ladderShape->GetDZ()) + maxdz = ladderShape->GetDZ(); + } + } + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { +// Int_t ladderType = ladderTypes[iLadder]%100; // v19a +// Int_t ladderType = ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100; // v19b + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { +// ladderName = Form("LadderType%02d", ladderType); // v19a +// ladderName = Form("LadderType%03d", ladderType); // v19b + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + xPos += ladderShape->GetDX(); + cout << "xPos2: " << xPos << endl; + yPos = 0.; // vertically centred + TGeoRotation* rot = new TGeoRotation(); + + if (gkConstructFrames) + subtractedVal = ladderShape->GetDX() + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2; + else + subtractedVal = 0.; + + zPos = 0.5 * gkLadderGapZ + (2*maxdz-ladderShape->GetDZ()-subtractedVal/2.); // z-aligned ladders + +// v19a cout << "DE ladder" << ladderTypes[iLadder]%100 +// v19b cout << "DE ladder" << ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100 +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " dx: " << ladderShape->GetDX() + << " dy: " << ladderShape->GetDY() + << " dz: " << ladderShape->GetDZ() + << " max dz: " << maxdz << endl; + +// v19a cout << "DE ladder" << ladderTypes[iLadder]%100 +// v19b cout << "DE ladder" << ladderTypes[iLadder]/1000 * 100 + ladderTypes[iLadder]%100 +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " fra: " << gkFrameThickness/2. + << " sub: " << subtractedVal + << " zpo: " << zPos << endl << endl; + +// v19a if (ladderTypes[iLadder]/100 == 1) // flip some of the ladders to reproduce the CAD layout + if (ladderTypes[iLadder]/1000 == 1) // flip some of the ladders to reproduce the CAD layout + rot->RotateY(180.); + else + zPos = -zPos; + + if (!isFirstPartOfHalfUnit) + // zPos += 10; + zPos += 10.5; // v19d +// zPos += 11.0; // v19e + + TGeoCombiTrans* trans = new TGeoCombiTrans(xPos, yPos, zPos, rot); +// start +// cout << "DEEE** iLadder " << iLadder << " " << nLadders/2 << " " << nLadders << endl; + + if (iSide == 0) + { + if (iLadder < nLadders/2) // right side - only half unit -x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + else + { + if (iLadder >= nLadders/2) // left side - only half unit +x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + unit->GetShape()->ComputeBBox(); +// stop + xPos += ladderShape->GetDX() - gkLadderOverlapX; + cout << "xPos3: " << xPos << endl; + } + else + xPos += gkSensorSizeX - gkLadderOverlapX; + } + + return unit; + } +/** ======================================================================= **/ + + +/** =========================================================================== + ** Import and add the passive materials to the STS volume + **/ +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile) +{ + TString passiveName = TString("sts_passive_") + geoTag; + TString basePath = gSystem->Getenv("VMCWORKDIR"); + TString relPath = "/geometry/sts/passive/" + passiveName + ".gdml"; + TString passiveFileName = basePath + relPath; + infoFile << std::endl << std::endl; + infoFile << "Importing STS passive materials from GDML file '" << relPath << "'." << std::endl; + + TGDMLParse parser; + TGeoVolume* gdmlVolume = parser.GDMLReadFile(passiveFileName); + PostProcessGdml(gdmlVolume); + gdmlVolume->SetName(passiveName); + + TGeoTranslation* passiveTrans = new TGeoTranslation(0., 0., 4.68); + infoFile << "Passive assembly is translated for Z=4.68 cm downstream with respect to parent volume" << std::endl << std::endl; + + gdmlVolume->GetShape()->ComputeBBox(); + CheckVolume(gdmlVolume, infoFile); + + infoFile << std::endl; + for (Int_t iNode = 0; iNode < gdmlVolume->GetNdaughters(); iNode++) { + CheckVolume(gdmlVolume->GetNode(iNode)->GetVolume(), infoFile, kFALSE); + } + + stsVolume->AddNode(gdmlVolume, stsVolume->GetNdaughters(), passiveTrans, ""); +} + +/** =========================================================================== + ** Assign visual properties to the imported gdml volumes + **/ +void PostProcessGdml(TGeoVolume* gdmlVolume) +{ + const UInt_t kPOBColor = kRed-6; + const UInt_t kPOBTransparency = 0;// 5; + + const UInt_t kFEBColor = kOrange-6; + const UInt_t kFEBTransparency = 0;// 5; + + const UInt_t kUnitColor = kCyan-10; + const UInt_t kUnitTransparency = 0;// 5; + + const UInt_t kCfColor = kGray+3; + const UInt_t kCfTransparency = 0;// 10; + + // name <Color, Transparency> + std::map<std::string, std::tuple<UInt_t,UInt_t> > props { + { "passive_POB", std::tuple<UInt_t,UInt_t> {kPOBColor, kPOBTransparency} }, + { "passive_FEB", std::tuple<UInt_t,UInt_t> {kFEBColor, kFEBTransparency} }, + { "passive_unit", std::tuple<UInt_t,UInt_t> {kUnitColor, kUnitTransparency} }, + { "passive_Box_Wall", std::tuple<UInt_t,UInt_t> {kCfColor, kCfTransparency} }, + { "passive_Box_Wall_Front_CF2", std::tuple<UInt_t,UInt_t> {kCfColor-3, kCfTransparency} }, + }; + + // Match volume name and apply visual properties + const TObjArray* volumes = gGeoManager->GetListOfVolumes(); + for (auto& entry : props) { + TIter next(volumes); + TGeoVolume *vol = nullptr; + while ((vol=(TGeoVolume*)next())) { + if (TString(vol->GetName()).Contains(entry.first.c_str())) { + vol->SetLineColor(std::get<0>(entry.second)); + vol->SetTransparency(std::get<1>(entry.second)); + } + } + } +} + +/** =========================================================================== + ** Volume information for debugging + **/ +void CheckVolume(TGeoVolume* volume) { + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + cout << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) cout << ", assembly"; + else { + if ( volume->GetMedium() ) + cout << ", medium " << volume->GetMedium()->GetName(); + else cout << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + cout << endl; + if ( volume->GetNdaughters() ) { + cout << "Daughters: " << endl; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) { + TGeoNode* node = volume->GetNode(iNode); + TGeoBBox* shape = (TGeoBBox*) node->GetVolume()->GetShape(); + cout << setw(15) << node->GetName() << ", size " + << fixed << setprecision(3) + << setw(6) << 2. * shape->GetDX() << " x " + << setw(6) << 2. * shape->GetDY() << " x " + << setw(6) << 2. * shape->GetDZ() << ", position ( "; + TGeoMatrix* matrix = node->GetMatrix(); + const Double_t* pos = matrix->GetTranslation(); + cout << setfill(' '); + cout << fixed << setw(8) << pos[0] << ", " + << setw(8) << pos[1] << ", " + << setw(8) << pos[2] << " )" << endl; + } + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Volume information for output to file + **/ +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren) { + if ( ! file ) return; + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + file << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) file << ", assembly"; + else { + if ( volume->GetMedium() ) + file << ", medium " << volume->GetMedium()->GetName(); + else file << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + file << endl; + if ( volume->GetNdaughters() && listChildren) { + file << "Contains: "; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) + file << volume->GetNode(iNode)->GetVolume()->GetName() << " "; + file << endl; + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Calculate beam pipe outer radius for a given z + **/ +Double_t BeamPipeRadius(Double_t z) { + if ( z < gkPipeZ2 ) return gkPipeR1; + Double_t slope = (gkPipeR3 - gkPipeR2 ) / (gkPipeZ3 - gkPipeZ2); + return gkPipeR2 + slope * (z - gkPipeZ2); +} +/** ======================================================================= **/ + + + +/** ======================================================================= **/ +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + TGeoBBox* frameVertPillarShp; + + Double_t t = gkFrameThickness/2.; + + // --- Main vertical pillars +// TGeoBBox* frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, gkFrameStep/2., t); // square crossection, along y +// TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); +// frameVertPillarVol->SetLineColor(kGreen); +// frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoTranslation(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2.)); +// frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoTranslation(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkCylindricalFrames) + // TGeoBBox* frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", 0, t, gkFrameStep/2.); // circle crossection, along z + frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", gkCylinderDiaInner/2., gkCylinderDiaOuter/2., gkFrameStep/2.); // circle crossection, along z + else + frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, t, gkFrameStep/2.); // square crossection, along z + TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); + frameVertPillarVol->SetLineColor(kGreen); + + TGeoRotation* xRot90 = new TGeoRotation; + xRot90->RotateX(90.); + frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoCombiTrans(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoCombiTrans(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + + // TGeoRotation* vertRot = new TGeoRotation(name + "_vertpillar_rot_1", 90., 45., -90.); + TGeoRotation* vertRot = new TGeoRotation; + vertRot->RotateX(90.); + vertRot->RotateY(45.); + frameBoxVol->AddNode(frameVertPillarVol, 3, new TGeoCombiTrans(name + "_vertpillar_pos_3", 0., 0., (x-sqrt(2.)*t)/2., vertRot)); + + // --- Small horizontal pillar + // TGeoBBox* frameHorPillarShp = new TGeoBBox(name + "_horpillar_shape", x-2.*t, gkThinFrameThickness/2., gkThinFrameThickness/2.); + // TGeoVolume* frameHorPillarVol = new TGeoVolume(name + "_horpillar", frameHorPillarShp, framesMaterial); + // frameHorPillarVol->SetLineColor(kCyan); + // frameBoxVol->AddNode(frameHorPillarVol, 1, new TGeoTranslation(name + "_horpillar_pos_1", 0., -gkFrameStep/2.+gkThinFrameThickness/2., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkConstructSmallFrames) { + + // --- Small sloping pillars + TGeoPara* frameSlopePillarShp = new TGeoPara(name + "_slopepillar_shape", + (x-2.*t)/TMath::Cos(31.4/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., 31.4, 0., 90.); + TGeoVolume* frameSlopePillarVol = new TGeoVolume(name + "_slopepillar", frameSlopePillarShp, framesMaterial); + frameSlopePillarVol->SetLineColor(kCyan); + TGeoRotation* slopeRot = new TGeoRotation(name + "_slopepillar_rot_1", 0., 0., 31.4); + TGeoRotation* slopeRot2 = new TGeoRotation(name + "_slopepillar_rot_2", 0., 0., -31.4); + TGeoCombiTrans* slopeTrRot = new TGeoCombiTrans(name + "_slopepillar_posrot_1", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot); + TGeoCombiTrans* slopeTrRot2 = new TGeoCombiTrans(name + "_slopepillar_posrot_2", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot2); + + frameBoxVol->AddNode(frameSlopePillarVol, 1, slopeTrRot); + frameBoxVol->AddNodeOverlap(frameSlopePillarVol, 2, slopeTrRot2); + + + Double_t angl = 23.; + // --- Small sub pillar + TGeoPara* frameSubPillarShp = new TGeoPara(name + "_subpillar_shape", + (sqrt(2)*(x/2.-t)-t/2.)/TMath::Cos(angl/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., angl, 0., 90.); + TGeoVolume* frameSubPillarVol = new TGeoVolume(name + "_subpillar", frameSubPillarShp, framesMaterial); + frameSubPillarVol->SetLineColor(kMagenta); + + Double_t posZ = t * (1. - 3. / ( 2.*sqrt(2.) )); + + // one side of X direction + TGeoRotation* subRot1 = new TGeoRotation(name + "_subpillar_rot_1", 90., 45., -90.+angl); + TGeoCombiTrans* subTrRot1 = new TGeoCombiTrans(name + "_subpillar_posrot_1", -(-x/2.+t-t/(2.*sqrt(2.))), 1., posZ, subRot1); + + TGeoRotation* subRot2 = new TGeoRotation(name + "_subpillar_rot_2", 90., -90.-45., -90.+angl); + TGeoCombiTrans* subTrRot2 = new TGeoCombiTrans(name + "_subpillar_posrot_2", -(-x/2.+t-t/(2.*sqrt(2.))), -1., posZ, subRot2); + + // other side of X direction + TGeoRotation* subRot3 = new TGeoRotation(name + "_subpillar_rot_3", 90., 90.+45., -90.+angl); + TGeoCombiTrans* subTrRot3 = new TGeoCombiTrans(name + "_subpillar_posrot_3", -x/2.+t-t/(2.*sqrt(2.)), 1., posZ, subRot3); + + TGeoRotation* subRot4 = new TGeoRotation(name + "_subpillar_rot_4", 90., -45., -90.+angl); + TGeoCombiTrans* subTrRot4 = new TGeoCombiTrans(name + "_subpillar_posrot_4", -x/2.+t-t/(2.*sqrt(2.)), -1., posZ, subRot4); + + frameBoxVol->AddNode(frameSubPillarVol, 1, subTrRot1); + frameBoxVol->AddNode(frameSubPillarVol, 2, subTrRot2); + frameBoxVol->AddNode(frameSubPillarVol, 3, subTrRot3); + frameBoxVol->AddNode(frameSubPillarVol, 4, subTrRot4); + // frameBoxVol->GetShape()->ComputeBBox(); + } + + return frameBoxVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructSmallCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 6., 7.6, 6., 6.04, 0., 180.); +// TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + Double_t radius = 3.0; + Double_t thickness = 0.04; // 0.4 mm +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 3., 3.2, 3., 3.2, 0., 180.); + TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, radius, radius+thickness, radius, radius+thickness, 0., 180.); + TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + TGeoCombiTrans* M = new TGeoCombiTrans ("M"); + M->RotateX (45.); + M->SetDy (-5.575); + M->SetDz (6.935); + M->RegisterYourself(); + + TGeoShape* coneShp = new TGeoCompositeShape ("Cone_shp", "A-B:M"); + TGeoVolume* coneVol = new TGeoVolume ("Cone", coneShp, framesMaterial); + coneVol->SetLineColor(kGreen); +// coneVol->RegisterYourself(); + +// // --- Inner cone +// Double_t thickness = 0.02; +// Double_t thickness2 = 0.022; +// // TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); +// TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 3.+thickness, 4.6-thickness2, 2.99+thickness, 3.05-thickness2, 0., 180.); +// +// TGeoCombiTrans* M2 = new TGeoCombiTrans ("M2"); +// M2->RotateX (45.); +// M2->SetDy (-5.575+thickness*sqrt(2.)); +// M2->SetDz (6.935); +// M2->RegisterYourself(); +// +// TGeoShape* coneShp2 = new TGeoCompositeShape ("Cone2_shp", "A2-B:M2"); +// TGeoVolume* coneVol2 = new TGeoVolume ("Cone2", coneShp2, gStsMedium); +// coneVol2->SetLineColor(kGreen); +//// coneVol2->RegisterYourself(); +// +// coneVol->AddNode(coneVol2, 1); + + return coneVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructBigCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone + TGeoConeSeg* bA = new TGeoConeSeg ("bA", coneDz, 6., 7.6, 6., 6.04, 0., 180.); + TGeoBBox* bB = new TGeoBBox ("bB", 8., 6., 10.); + + TGeoCombiTrans* bM = new TGeoCombiTrans ("bM"); + bM->RotateX (45.); + bM->SetDy (-5.575); + bM->SetDz (6.935); + bM->RegisterYourself(); + + TGeoShape* coneBigShp = new TGeoCompositeShape ("ConeBig_shp", "bA-bB:bM"); + TGeoVolume* coneBigVol = new TGeoVolume ("ConeBig", coneBigShp, framesMaterial); + coneBigVol->SetLineColor(kGreen); +// coneBigVol->RegisterYourself(); + + // --- Inner cone + Double_t thickness = 0.02; + Double_t thickness2 = 0.022; + TGeoConeSeg* bA2 = new TGeoConeSeg ("bA2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); + + TGeoCombiTrans* bM2 = new TGeoCombiTrans ("bM2"); + bM2->RotateX (45.); + bM2->SetDy (-5.575+thickness*sqrt(2.)); + bM2->SetDz (6.935); + bM2->RegisterYourself(); + + TGeoShape* coneBigShp2 = new TGeoCompositeShape ("ConeBig2_shp", "bA2-bB:bM2"); + TGeoVolume* coneBigVol2 = new TGeoVolume ("ConeBig2", coneBigShp2, gStsMedium); + coneBigVol2->SetLineColor(kGreen); +// coneBigVol2->RegisterYourself(); + + coneBigVol->AddNode(coneBigVol2, 1); + + return coneBigVol; +} + +/** ======================================================================= **/ diff --git a/macro/sts/geometry/create_stsgeo_v19q.C b/macro/sts/geometry/create_stsgeo_v19q.C new file mode 100644 index 0000000000000000000000000000000000000000..c38f0657b5e93fb6f4b4362a4a8bfb9d5e135078 --- /dev/null +++ b/macro/sts/geometry/create_stsgeo_v19q.C @@ -0,0 +1,2363 @@ +/****************************************************************************** + ** Creation of STS geometry in ROOT format (TGeo). + ** + ** @file create_stsgeo_v19q.C + ** @author Volker Friese <v.friese@gsi.de> + ** @since 15 June 2012 + ** @date 09.05.2014 + ** @author Tomas Balog <T.Balog@gsi.de> + ** + ** v19q: based on v19l - align ladders to virtual plane in station center, closing the gaps in z + ** v19p: based on v19k - parameters : delta Z prime = 0.70 cm - delta Z pitch = 0.20 cm + ** v19o: based on v19k - parameters : delta Z prime = 0.30 cm - delta Z pitch = 0.20 cm + ** v19n: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.20 cm (bug fix of v19m) + ** v19m: based on v19k - parameters : delta Z prime = 0.55 cm - delta Z pitch = 0.20 cm (bug) + ** v19l: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.15 cm + ** v19k: ladders on upstream side of units get upper half ladders installed first, + ** ladders on downstream side of units get lower half ladders installed first, + ** this saves 1.5 mm space in z per station, 12 mm in total (LadderType went from 3 to 4 digits) + ** parameters : delta Z prime = 1.00 cm - delta Z pitch = 0.15 cm + ** v19j: use overlap and distance parameters from CAD model + ** v19h: put STS stations from v19d at z-positions = 260; 365; 470; 575; 680; 785; 890; 995 mm + ** v19g: place a box with services around v19e + ** v19f: place a box with services around v19d + ** v19e: increase spacing between stations by +10 mm from 100 mm + ** v19d: increase spacing between stations by + 5 mm from 100 mm + ** v19c: drop station 8 and increase spacing between remaining 7 stations from 10 cm to 12 c + ** v19b: introduce FEB orientation in ladder numbering (LadderType went from 2 to 3 digits) + ** v19a: import passive materials from gdml file + ** extend CF ladder structures and cables towards FEE plane + ** change CF ladder frame shape + ** v18d: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu (based on v18b) + ** v18c: fixed cut-out windows in cooling plates, improve the box shape/materials + ** v18b: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu + ** v18a: adds 9 cooling/holding plates and a box around the setup + ** v16g: v16g is the new standard geometry from November 2017 + ** v16g: switch from stations to units - left / right ("Unit01L", "Unit01R") + ** v16f: switch from stations to units + ** - split in upstream / downstream and left / right parts + ** - named Unit0xUR, Unit0xUL, Unit0xDR, Unit0xDL + ** v16e: switch from stations to units - upstream / downstream ("Unit01U", "Unit01D") + ** v16d: skip keeping volumes of sts and stations + ** v16c: like v16b, but senors of ladders beampipe next to beampipe + ** shifted closer to the pipe, like in the CAD model + ** v16b: like v16a, but yellow sensors removed + ** v16a: derived from v15c (no cones), but with sensor types renamed: + ** 2 -> 1, 3 -> 2, 4 -> 3, 5 -> 4, 1 -> 5 + ** + ** v15c: as v15b without cones + ** v15b: introduce modified carbon ladders from v13z + ** v15a: with flipped ladder orientation for stations 0,2,4,6 to match CAD design + ** + ** TODO: + ** + ** DONE: + ** v15b - use carbon macaroni as ladder support + ** v15b - introduce a small gap between lowest sensor and carbon ladder + ** v15b - build small cones for the first 2 stations + ** v15b - within a station the ladders of adjacent units should not touch eachother - set gkLadderGapZ to 10 mm + ** v15b - for all ladders set an even number of ladder elements + ** v15b - z offset of cones to ladders should not be 0.3 by default, but 0.26 + ** v15b - within a station the ladders should be aligned in z, defined either by the unit or the ladder with most sensors + ** v15b - get rid of cone overlap in stations 7 and 8 - done by adapting rHole size + ** + ** The geometry hierarachy is: + ** + ** 1. Sensors (see function CreateSensors) + ** The sensors are the active volumes and the lowest geometry level. + ** They are built as TGeoVolumes, shape box, material silicon. + ** x size is determined by strip pitch 58 mu and 1024 strips + ** plus guard ring of 1.3 mm at each border -> 6.1992 cm. + ** Sensor type 1 is half of that (3.0792 cm). + ** y size is determined by strip length (2.2 / 4.2 / 6.3 cm) plus + ** guard ring of 1.3 mm at top and bottom -> 2.46 / 4.46 / 6.46 cm. + ** z size is a parameter, to be set by gkSensorThickness. + ** + ** 2. Sectors (see function CreateSectors) + ** Sectors consist of several chained sensors. These are arranged + ** vertically on top of each other with a gap to be set by + ** gkChainGapY. Sectors are constructed as TGeoVolumeAssembly. + ** The sectors are auxiliary volumes used for proper placement + ** of the sensor(s) in the module. They do not show up in the + ** final geometry. + ** + ** 3. Modules (see function ConstructModule) + ** A module is a readout unit, consisting of one sensor or + ** a chain of sensors (see sector) and a cable. + ** The cable extends from the top of the sector vertically to the + ** top of the halfladder the module is placed in. The cable and module + ** volume thus depend on the vertical position of the sector in + ** the halfladder. The cables consist of silicon with a thickness to be + ** set by gkCableThickness. + ** Modules are constructed as TGeoVolume, shape box, medium gStsMedium. + ** The module construction can be switched off (gkConstructCables) + ** to reproduce older geometries. + ** + ** 4. Halfladders (see function ConstructHalfLadder) + ** A halfladder is a vertical assembly of several modules. The modules + ** are placed vertically such that their sectors overlap by + ** gkSectorOverlapY. They are displaced in z direction to allow for the + ** overlap in y by gkSectorGapZ. + ** The horizontal placement of modules in the halfladder can be choosen + ** to left aligned or right aligned, which only matters if sensors of + ** different x size are involved. + ** Halfladders are constructed as TGeoVolumeAssembly. + ** + ** 5. Ladders (see function CreateLadders and ConstructLadder) + ** A ladder is a vertical assembly of two halfladders, and is such the + ** vertical building block of a station. The second (bottom) half ladder + ** is rotated upside down. The vertical arrangement is such that the + ** inner sectors of the two halfladders have the overlap gkSectorOverlapY + ** (function CreateLadder) or that there is a vertical gap for the beam + ** hole (function CreateLadderWithGap). + ** Ladders are constructed as TGeoVolumeAssembly. + ** + ** 6. Stations (see function ConstructStation) + ** A station represents one layer of the STS geometry: one measurement + ** at (approximately) a given z position. It consist of several ladders + ** arranged horizontally to cover the acceptance. + ** The ladders are arranged such that there is a horizontal overlap + ** between neighbouring ladders (gkLadderOverLapX) and a vertical gap + ** to allow for this overlap (gkLadderGapZ). Each second ladder is + ** rotated around its y axis to face away from or into the beam. + ** Stations are constructed as TGeoVolumes, shape box minus tube (for + ** the beam hole), material gStsMedium. + ** + ** 7. STS + ** The STS is a volume hosting the entire detectors system. It consists + ** of several stations located at different z positions. + ** The STS is constructed as TGeoVolume, shape box minus cone (for the + ** beam pipe), material gStsMedium. The size of the box is computed to + ** enclose all stations. + *****************************************************************************/ + + +// Remark: With the proper steering variables, this should exactly reproduce +// the geometry version v11b of A. Kotynia's described in the ASCII format. +// The only exception is a minimal difference in the z position of the +// sectors/sensors. This is because of ladder types 2 and 4 containing the half +// sensors around the beam hole (stations 1,2 and 3). In v11b, the two ladders +// covering the beam hole cannot be transformed into each other by rotations, +// but only by a reflection. This means they are constructionally different. +// To avoid introducing another two ladder types, the difference in z position +// was accepted. + + +// Differences to v12: +// gkChainGap reduced from 1 mm to 0 +// gkCableThickness increased from 100 mum to 200 mum (2 cables per module) +// gkSectorOverlapY reduced from 3 mm to 2.4 mm +// New sensor types 05 and 06 +// New sector types 07 and 08 +// Re-definiton of ladders (17 types instead of 8) +// Re-definiton of station from new ladders + + +#include <iomanip> +#include <iostream> +#include "TGeoManager.h" + +#include "TGeoTube.h" +#include "TGeoPara.h" +#include "TGeoCone.h" +#include "TGeoTrd2.h" +#include "TGeoCompositeShape.h" +#include "TGeoXtru.h" +#include "TGeoPhysicalNode.h" + +// forward declarations +Int_t CreateSensors(); +Int_t CreateSectors(); +Int_t CreateLadders(); +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength); +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY); +TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ, + Double_t offsetZ); +TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation); +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile); +void PostProcessGdml(TGeoVolume* gdmlTop); +void CheckVolume(TGeoVolume* volume); +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren = kTRUE); +Double_t BeamPipeRadius(Double_t z); +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x); +TGeoVolume* ConstructSmallCone(Double_t coneDz); +TGeoVolume* ConstructBigCone(Double_t coneDz); + +// ------------- Version highlight ----------------------------------- + +const std::string gVersionHighlight = R"( +Summary: + This version adds passive materials imported from GDML model to the STS geometry: + * Taken from and largely correspond to mechanical CAD drawings of the detector + * Thermal insulation box: + - made out of carbon sandwitch panel (2mm carbon fiber sheet + layer of carbon foam + 2mm carbon fiber sheet) + - front window of complex shape with interface to MVD / target chamber + - back window with large aperture (2000 x 1200 mm) square cut into carbon foam + * Structural units: + - made of 2 complex shape aluminum C-Frames, 15mm thick + - placed at 25, 35, ... ,105 cm absolute Z + - contain front-end and power distribution boxes with equivalent X_0 values + + Scripted geometry tweaks: + * Ladders and cables are extended towards the read-out planes having same lengths in respective rows + * Adjusted form and shape of carbon ladder structures from L-type to X-type + * Reduced verbosity of this file + + Sensor arrangement is the same as in version v16g + + !! Important for this version is the discrepancy from the mechanical CAD w.r.t. front wall. + The square window was replaced by a round one to avoid overlaps with present beam pipe designs, e.g. pipe_v16b_1e +)"; + +// ------------- Steering variables ----------------------------------- + +// ---> Horizontal width of sensors [cm] +const Double_t gkSensorSizeX = 6.2; // was 6.2092; // 6.2 - Oleg CAD 15/05/2020 + +// ---> Thickness of sensors [cm] +const Double_t gkSensorThickness = 0.03; + +// ---> Vertical gap between chained sensors [cm] +const Double_t gkChainGapY = 0.00; + +// ---> Thickness of cables [cm] +const Double_t gkCableThickness = 0.02; + +// ---> Horizontal overlap of neighbouring ladders [cm] +const Double_t gkLadderOverlapX = 0.25; // delta X - Oleg CAD 14/05/2020 + +// ---> Vertical overlap of neighbouring sectors in a ladder [cm] +const Double_t gkSectorOverlapY = 0.46; // delta Y - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring sectors in a ladder [cm] +const Double_t gkSectorGapZ = 0.12; // gap + thickness = pitch // delta Z pitch = 0.15 - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring ladders [cm] +const Double_t gkLadderGapZ = 0.50 - 0.15; // for asym // 0.5 for sym // delta Z prime + +// ---> Gap in z between lowest sector to carbon support structure [cm] +const Double_t gkSectorGapZFrame = 0.280 - 0.025; // Oleg CAD 05/05/2020 // there is a 2.8 mm gap between the bottom side of the sensor and the top ledge of the carbon ladder + +// ---> Switch to construct / not to construct readout cables +const Bool_t gkConstructCables = kTRUE; + +// ---> Switch to construct / not to construct frames +const Bool_t gkConstructCones = kFALSE; // kTRUE; // switch this false by default for v15c and v16x +const Bool_t gkConstructFrames = kTRUE; // kFALSE; // switch this true by default for v15c and v16x +const Bool_t gkConstructSmallFrames = kTRUE; // kFALSE; +const Bool_t gkCylindricalFrames = kTRUE; // kFALSE; + +// ---> Size of the frame +const Double_t gkFrameThickness = 0.2; +const Double_t gkThinFrameThickness = 0.05; +const Double_t gkFrameStep = 4.0; // size of frame cell along y direction + +const Double_t gkCylinderDiaInner = 0.07; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) +const Double_t gkCylinderDiaOuter = 0.15; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) + +// ---> Switch to import / not to import the Passive materials from GDML file +//const Bool_t gkImportPassive = kTRUE; +const Bool_t gkImportPassive = kFALSE; + +// ---------------------------------------------------------------------------- + + +// -------------- Parameters of beam pipe in the STS region -------------- +// ---> Needed to compute stations and STS such as to avoid overlaps +const Double_t gkPipeZ1 = 22.0; +const Double_t gkPipeR1 = 1.8; +const Double_t gkPipeZ2 = 50.0; +const Double_t gkPipeR2 = 1.8; +const Double_t gkPipeZ3 = 125.0; +const Double_t gkPipeR3 = 5.5; + +//DE const Double_t gkPipeZ1 = 27.0; +//DE const Double_t gkPipeR1 = 1.05; +//DE const Double_t gkPipeZ2 = 160.0; +//DE const Double_t gkPipeR2 = 3.25; +// ---------------------------------------------------------------------------- + +//TString unitName[16] = // names of units for v16e +// { "Unit00D", +// "Unit01U", "Unit01D", +// "Unit02U", "Unit02D", +// "Unit03U", "Unit03D", +// "Unit04U", "Unit04D", +// "Unit05U", "Unit05D", +// "Unit06U", "Unit06D", +// "Unit07U", "Unit07D", +// "Unit08U" }; + +//TString unitName[32] = // names of units for v16f +// { "Unit00DR", "Unit00DL", +// "Unit01UR", "Unit01UL", "Unit01DR", "Unit01DL", +// "Unit02UR", "Unit02UL", "Unit02DR", "Unit02DL", +// "Unit03UR", "Unit03UL", "Unit03DR", "Unit03DL", +// "Unit04UR", "Unit04UL", "Unit04DR", "Unit04DL", +// "Unit05UR", "Unit05UL", "Unit05DR", "Unit05DL", +// "Unit06UR", "Unit06UL", "Unit06DR", "Unit06DL", +// "Unit07UR", "Unit07UL", "Unit07DR", "Unit07DL", +// "Unit08UR", "Unit08UL" }; + +TString unitName[32] = // names of units for v16g - while merging D and U parts + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", "Unit01R", "Unit01L", + "Unit02R", "Unit02L", "Unit02R", "Unit02L", + "Unit03R", "Unit03L", "Unit03R", "Unit03L", + "Unit04R", "Unit04L", "Unit04R", "Unit04L", + "Unit05R", "Unit05L", "Unit05R", "Unit05L", + "Unit06R", "Unit06L", "Unit06R", "Unit06L", + "Unit07R", "Unit07L", "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +TString unitName18[18] = // names of units for v16g + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", + "Unit02R", "Unit02L", + "Unit03R", "Unit03L", + "Unit04R", "Unit04L", + "Unit05R", "Unit05L", + "Unit06R", "Unit06L", + "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +// ------------- Other global variables ----------------------------------- +// ---> STS medium (for every volume except silicon) +TGeoMedium* gStsMedium = NULL; // will be set later +// ---> TGeoManager (too lazy to write out 'Manager' all the time +TGeoManager* gGeoMan = NULL; // will be set later +// ---------------------------------------------------------------------------- + + + + +// ============================================================================ +// ====== Main function ===== +// ============================================================================ + +void create_stsgeo_v19q(const char* geoTag="v19q") +{ + + // ------- Geometry file name (output) ---------------------------------- + TString geoFileName = "sts_"; + geoFileName = geoFileName + geoTag + ".geo.root"; + // -------------------------------------------------------------------------- + + + // ------- Open info file ----------------------------------------------- + TString infoFileName = geoFileName; + infoFileName.ReplaceAll("root", "info"); + fstream infoFile; + infoFile.open(infoFileName.Data(), fstream::out); + infoFile << "STS geometry created with create_stsgeo_v19q.C" << endl; + infoFile << gVersionHighlight << endl; + infoFile << "Global variables: " << endl; + infoFile << "Sensor thickness = " << gkSensorThickness << " cm" << endl; + infoFile << "Vertical gap in sensor chain = " + << gkChainGapY << " cm" << endl; + infoFile << "Vertical overlap of sensors = " + << gkSectorOverlapY << " cm" << endl; + infoFile << "Gap in z between neighbour sensors = " + << gkSectorGapZ << " cm" << endl; + infoFile << "Horizontal overlap of sensors = " + << gkLadderOverlapX << " cm" << endl; + infoFile << "Gap in z between neighbour ladders = " + << gkLadderGapZ << " cm" << endl; + if ( gkConstructCables ) + infoFile << "Cable thickness = " << gkCableThickness << " cm" << endl; + else + infoFile << "No cables" << endl; + infoFile << endl; + infoFile << "Beam pipe: R1 = " << gkPipeR1 << " cm at z = " + << gkPipeZ1 << " cm" << endl; + infoFile << "Beam pipe: R2 = " << gkPipeR2 << " cm at z = " + << gkPipeZ2 << " cm" << endl; + infoFile << "Beam pipe: R3 = " << gkPipeR3 << " cm at z = " + << gkPipeZ3 << " cm" << endl; + // -------------------------------------------------------------------------- + + + // ------- Load media from media file ----------------------------------- + FairGeoLoader* geoLoad = new FairGeoLoader("TGeo","FairGeoLoader"); + FairGeoInterface* geoFace = geoLoad->getGeoInterface(); + TString geoPath = gSystem->Getenv("VMCWORKDIR"); + TString medFile = geoPath + "/geometry/media.geo"; + geoFace->setMediaFile(medFile); + geoFace->readMedia(); + gGeoMan = gGeoManager; + // -------------------------------------------------------------------------- + + + // ----------------- Get and create the required media ----------------- + FairGeoMedia* geoMedia = geoFace->getMedia(); + FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder(); + + // ---> air + FairGeoMedium* mAir = geoMedia->getMedium("air"); + if ( ! mAir ) Fatal("Main", "FairMedium air not found"); + geoBuild->createMedium(mAir); + TGeoMedium* air = gGeoMan->GetMedium("air"); + if ( ! air ) Fatal("Main", "Medium air not found"); + + // ---> silicon + FairGeoMedium* mSilicon = geoMedia->getMedium("silicon"); + if ( ! mSilicon ) Fatal("Main", "FairMedium silicon not found"); + geoBuild->createMedium(mSilicon); + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + if ( ! silicon ) Fatal("Main", "Medium silicon not found"); + + // ---> carbon + FairGeoMedium* mCarbon = geoMedia->getMedium("carbon"); + if ( ! mCarbon ) Fatal("Main", "FairMedium carbon not found"); + geoBuild->createMedium(mCarbon); + TGeoMedium* carbon = gGeoMan->GetMedium("carbon"); + if ( ! carbon ) Fatal("Main", "Medium carbon not found"); + + // ---> STSBoxCarbonFoam + FairGeoMedium* mSTSBoxCarbonFoam = geoMedia->getMedium("STSBoxCarbonFoam"); + if ( ! mSTSBoxCarbonFoam ) Fatal("Main", "FairMedium STSBoxCarbonFoam not found"); + geoBuild->createMedium(mSTSBoxCarbonFoam); + TGeoMedium* STSBoxCarbonFoam = gGeoMan->GetMedium("STSBoxCarbonFoam"); + if ( ! STSBoxCarbonFoam ) Fatal("Main", "Medium STSBoxCarbonFoam not found"); + + // ---> STSBoxCarbonFibre + FairGeoMedium* mSTSBoxCarbonFibre = geoMedia->getMedium("STSBoxCarbonFibre"); + if ( ! mSTSBoxCarbonFibre ) Fatal("Main", "FairMedium STSBoxCarbonFibre not found"); + geoBuild->createMedium(mSTSBoxCarbonFibre); + TGeoMedium* STSBoxCarbonFibre = gGeoMan->GetMedium("STSBoxCarbonFibre"); + if ( ! STSBoxCarbonFibre ) Fatal("Main", "Medium STSBoxCarbonFibre not found"); + + // ---> STScable + FairGeoMedium* mSTScable = geoMedia->getMedium("STScable"); + if ( ! mSTScable ) Fatal("Main", "FairMedium STScable not found"); + geoBuild->createMedium(mSTScable); + TGeoMedium* STScable = gGeoMan->GetMedium("STScable"); + if ( ! STScable ) Fatal("Main", "Medium STScable not found"); + + // ---> Aluminium + FairGeoMedium* mAluminium = geoMedia->getMedium("aluminium"); + if ( ! mAluminium ) Fatal("Main", "FairMedium aluminium not found"); + geoBuild->createMedium(mAluminium); + TGeoMedium* aluminium = gGeoMan->GetMedium("aluminium"); + if ( ! aluminium ) Fatal("Main", "Medium aluminium not found"); + + // --- + gStsMedium = air; + // -------------------------------------------------------------------------- + + + // -------------- Create geometry and top volume ------------------------- + gGeoMan = (TGeoManager*)gROOT->FindObject("FAIRGeom"); +// gGeoMan->SetName("STSgeom"); + TGeoVolume* top = new TGeoVolumeAssembly("top"); +// TGeoBBox* topbox= new TGeoBBox("", 120., 120., 120.); +// TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air")); + gGeoMan->SetTopVolume(top); + // -------------------------------------------------------------------------- + + + // -------------- Create media ------------------------------------------ + /* + cout << endl; + cout << "===> Creating media...."; + cout << CreateMedia(); + cout << " media created" << endl; + TList* media = gGeoMan->GetListOfMedia(); + for (Int_t iMedium = 0; iMedium < media->GetSize(); iMedium++ ) { + cout << "Medium " << iMedium << ": " + << ((TGeoMedium*) media->At(iMedium))->GetName() << endl; + } + gStsMedium = gGeoMan->GetMedium("air"); + if ( ! gStsMedium ) Fatal("Main", "medium sts_air not found"); + */ + // -------------------------------------------------------------------------- + + + // --------------- Create sensors --------------------------------------- + cout << endl << endl; + cout << "===> Creating sensors...." << endl << endl; + infoFile << endl << "Sensors: " << endl; + Int_t nSensors = CreateSensors(); + for (Int_t iSensor = 1; iSensor <= nSensors; iSensor++) { + TString name = Form("Sensor%02d",iSensor); + TGeoVolume* sensor = gGeoMan->GetVolume(name); + + // add color to sensors + if (iSensor == 1) + sensor->SetLineColor(kRed); + if (iSensor == 2) + sensor->SetLineColor(kGreen); + if (iSensor == 3) + sensor->SetLineColor(kBlue); + if (iSensor == 4) + sensor->SetLineColor(kAzure); + if (iSensor == 5) + sensor->SetLineColor(kYellow); + if (iSensor == 6) + sensor->SetLineColor(kYellow); + if (iSensor == 7) + sensor->SetLineColor(kYellow); + + CheckVolume(sensor); + CheckVolume(sensor, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create sectors -------------------------------------- + cout << endl << endl; + cout << "===> Creating sectors...." << endl; + // infoFile << endl << "Sectors: " << endl; + Int_t nSectors = CreateSectors(); + for (Int_t iSector = 1; iSector <= nSectors; iSector++) { + // cout << endl; + TString name = Form("Sector%02d", iSector); + TGeoVolume* sector = gGeoMan->GetVolume(name); + CheckVolume(sector); + // CheckVolume(sector, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create ladders -------------------------------------- + cout << endl << endl; + cout << "===> Creating ladders...." << endl; + infoFile << endl << "Ladders:" << endl; + + TString name = ""; + TGeoVolume* ladder; + + + Int_t nLadders = CreateLadders(); + + for (Int_t iLadder = 1; iLadder <= nLadders; iLadder++) { + cout << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType0%02d", iLadder); // v19b + name = Form("LadderType00%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF1: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType1%02d", iLadder); // v19b + name = Form("LadderType01%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF2: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType10%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF3: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType11%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF4: ladder name: " << name << endl << endl; + } + // -------------------------------------------------------------------------- + + + // ---------------- Create cones ---------------------------------------- + Double_t coneDz = 1.64; + TGeoVolume* coneSmallVolum = ConstructSmallCone(coneDz); + if (!coneSmallVolum) Fatal("ConstructSmallCone", "Volume Cone not found"); + TGeoVolume* coneBigVolum = ConstructBigCone(coneDz); + if (!coneBigVolum) Fatal("ConstructBigCone", "Volume Cone not found"); + // -------------------------------------------------------------------------- + + + // ---------------- Create stations ------------------------------------- + cout << endl << endl; + cout << "===> Creating stations...." << endl; + infoFile << endl << "Stations: " << endl; + Int_t angle = 0; + nLadders = 0; + Int_t ladderTypes[16]; // there are max 16 ladders in one layer + TGeoTranslation* statTrans = NULL; + + TGeoVolume *myunit[32]; // units + +// Int_t statPos[8] = { 30, 40, 50, 60, 70, 80, 90, 100 }; // z positions of stations +// Int_t statPos[16] = { 28, 32, 38, 42, 48, 52, 58, 62, +// 68, 72, 78, 82, 88, 92, 98,102 }; // z positions of units +// Int_t statPos[16] = { 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units +// Int_t statPos18[18] = { 30, 30, // expanded for placement of Unit00 +// 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units + // v19h + Double_t statPos[16] = { 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of units + Double_t statPos18[18] = { 26.0, 26.0, // expanded for placement of Unit00 + 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of unit + +// // v19d +// Double_t statPos[16] = { 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units +// Double_t statPos18[18] = { 30.0, 30.0, // expanded for placement of Unit00 +// 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units + +////Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.9 , 3.7 , 3.7 , 4.2 , 4.2 }; // size of cutouts in stations +// Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.43, 3.04, 3.35, 3.96, 4.2 }; // size of cutouts in stations, derived from gapXYZ[x][1]/2 + + Int_t cone_size[8] = { 0, 0, 0, 1, 1, 1, 1, 1 }; // size of cones: 0 = small, 1 = large + + Double_t cone_offset[2] = { 0.305, 0.285 }; + +// Int_t allLadderTypes[8][16]= +// { { -1, -1, -1, -1, 10, 109, 9, 101, 1, 109, 9, 110, -1, -1, -1, -1 }, // station 1 +// { -1, -1, 111, 10, 110, 9, 109, 2, 102, 9, 109, 10, 110, 11, -1, -1 }, // station 2 +// { -1, -1, 14, 113, 12, 112, 12, 103, 3, 112, 12, 112, 13, 114, -1, -1 }, // station 3 +// { -1, 15, 114, 13, 112, 12, 112, 4, 104, 12, 112, 12, 113, 14, 115, -1 }, // station 4 +// { -1, 119, 18, 117, 17, 116, 16, 105, 5, 116, 16, 117, 17, 118, 19, -1 }, // station 5 +// { -1, 19, 118, 17, 117, 16, 116, 6, 106, 16, 116, 17, 117, 18, 119, -1 }, // station 6 +// { 21, 119, 18, 120, 20, 120, 20, 107, 7, 120, 20, 120, 20, 118, 19, 121 }, // station 7 +// { 119, 17, 123, 22, 122, 22, 122, 8, 108, 22, 122, 22, 122, 23, 117, 19 } }; // station 8 + +//============================================================================================== + +// explanation: type xyzz +// where x = carbon ladder orientation +// where y = FEB box orientation +// where zz = sensor arrangement on ladder +// with FEB orientation - v19b + Int_t allUnitTypes[16][16]= + { { -1, -1, -1, -1, 10, 0, 9, 0, 101, 0, 109, 0, -1, -1, -1, -1 }, // unit00D Station01 00 + { -1, -1, -1, -1, 0, 1109, 0, 1101, 0, 1009, 0, 1010, -1, -1, -1, -1 }, // unit01U Station01 01 + + { -1, -1, 0, 10, 0, 9, 0, 2, 0, 109, 0, 110, 0, 111, -1, -1 }, // unit01D Station02 02 + { -1, -1, 1111, 0, 1110, 0, 1109, 0, 1002, 0, 1009, 0, 1010, 0, -1, -1 }, // unit02U Station02 03 + + { -1, -1, 14, 0, 12, 0, 12, 0, 103, 0, 112, 0, 113, 0, -1, -1 }, // unit02D Station03 04 + { -1, -1, 0, 1113, 0, 1112, 0, 1103, 0, 1012, 0, 1012, 0, 1014, -1, -1 }, // unit03U Station03 05 + + { -1, 15, 0, 13, 0, 12, 0, 4, 0, 112, 0, 112, 0, 114, 0, -1 }, // unit03D Station04 06 + { -1, 0, 1114, 0, 1112, 0, 1112, 0, 1004, 0, 1012, 0, 1013, 0, 1015, -1 }, // unit04U Station04 07 + + { -1, 0, 18, 0, 17, 0, 16, 0, 105, 0, 116, 0, 117, 0, 119, -1 }, // unit04D Station05 08 + { -1, 1119, 0, 1117, 0, 1116, 0, 1105, 0, 1016, 0, 1017, 0, 1018, 0, -1 }, // unit05U Station05 09 + + { -1, 19, 0, 17, 0, 16, 0, 6, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05D Station06 10 + { -1, 0, 1118, 0, 1117, 0, 1116, 0, 1006, 0, 1016, 0, 1017, 0, 1019, -1 }, // unit06U Station06 11 + + { 21, 0, 25, 0, 20, 0, 20, 0, 107, 0, 120, 0, 120, 0, 127, 0 }, // unit06D Station07 12 + { 0, 1127, 0, 1120, 0, 1120, 0, 1107, 0, 1020, 0, 1020, 0, 1025, 0, 1021 }, // unit07U Station07 13 + + { 0, 24, 0, 22, 0, 22, 0, 8, 0, 122, 0, 122, 0, 123, 0, 126 }, // unit07D Station08 14 + { 1126, 0, 1123, 0, 1122, 0, 1122, 0, 1008, 0, 1022, 0, 1022, 0, 1024, 0 } }; // unit08U Station08 15 + +//============================================================================================== + +// without FEB orientation - v19a +// v19a Int_t allUnitTypes[16][16]= +// v19a { { -1, -1, -1, -1, 10, 0, 9, 0, 1, 0, 9, 0, -1, -1, -1, -1 }, // unit00D Station01 00 +// v19a { -1, -1, -1, -1, 0, 109, 0, 101, 0, 109, 0, 110, -1, -1, -1, -1 }, // unit01U Station01 01 +// v19a { -1, -1, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, -1, -1 }, // unit01D Station02 02 +// v19a { -1, -1, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, -1, -1 }, // unit02U Station02 03 +// v19a { -1, -1, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, -1, -1 }, // unit02D Station03 04 +// v19a { -1, -1, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, -1, -1 }, // unit03U Station03 05 +// v19a { -1, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, -1 }, // unit03D Station04 06 +// v19a { -1, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, -1 }, // unit04U Station04 07 +// v19a { -1, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, -1 }, // unit04D Station05 08 +// v19a { -1, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05U Station05 09 +// v19a { -1, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, -1 }, // unit05D Station06 10 +// v19a { -1, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, -1 }, // unit06U Station06 11 +// v19a { 21, 0, 25, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 27, 0 }, // unit06D Station07 12 +// v19a { 0, 127, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 125, 0, 121 }, // unit07U Station07 13 +// v19a { 0, 24, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 26 }, // unit07D Station08 14 +// v19a { 126, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 124, 0 } }; // unit08U Station08 15 + + +// unitTypes[0] = { 0, 0, 0, 0, 10, 0, 9, 0, 1, 0, 9, 0, 0, 0, 0, 0 }; // unit 0D +// unitTypes[1] = { 0, 0, 0, 0, 0, 109, 0, 101, 0, 109, 0, 110, 0, 0, 0, 0 }; // unit 1U +// unitTypes[2] = { 0, 0, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, 0, 0 }; // unit 1D +// unitTypes[3] = { 0, 0, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, 0, 0 }; // unit 2U +// unitTypes[4] = { 0, 0, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, 0, 0 }; // unit 2D +// unitTypes[5] = { 0, 0, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, 0, 0 }; // unit 3U +// unitTypes[6] = { 0, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, 0 }; // unit 3D +// unitTypes[7] = { 0, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, 0 }; // unit 4U +// unitTypes[8] = { 0, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, 0 }; // unit 4D +// unitTypes[9] = { 0, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, 0 }; // unit 5U +// unitTypes[10] = { 0, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, 0 }; // unit 5D +// unitTypes[11] = { 0, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, 0 }; // unit 6U +// unitTypes[12] = { 21, 0, 18, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 19, 0 }; // unit 6D +// unitTypes[13] = { 0, 119, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 118, 0, 121 }; // unit 7U +// unitTypes[14] = { 0, 17, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 19 }; // unit 7D +// unitTypes[15] = { 119, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 117, 0 }; // unit 8U + + +// // generate unit +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) +// for (Int_t iLadder = 0; iLadder < 16; iLadder++) +// { +// allUnitTypes[iUnit][iLadder] = 0; +// if ((iUnit % 2 == 0) && (allLadderTypes[iUnit/2][iLadder] < 100)) // if carbon structure is oriented upstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// if ((iUnit % 2 == 1) && (allLadderTypes[iUnit/2][iLadder] >= 100)) // if carbon structure is oriented downstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// } + + + // dump unit + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << "DE unitTypes[" << iUnit << "] = { "; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + { + cout << allUnitTypes[iUnit][iLadder]; + if (iLadder < 15) + cout << ", "; + else + cout << " };"; + } + cout << endl; + } + + + // --- Units 01 - 16 + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << endl; + + nLadders = 0; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + if (allUnitTypes[iUnit][iLadder] >= 0) + { + ladderTypes[nLadders] = allUnitTypes[iUnit][iLadder]; + cout << "DE ladderTypes[" << nLadders << "] = " << allUnitTypes[iUnit][iLadder] << ";" << endl; + nLadders++; + } + myunit[iUnit*2+0] = ConstructUnit(0, iUnit*2+0, nLadders, ladderTypes, iUnit/2+1); + myunit[iUnit*2+1] = ConstructUnit(1, iUnit*2+1, nLadders, ladderTypes, iUnit/2+1); + +// if (gkConstructCones) { +// if (iUnit%2 == 0) +// angle = 90; +// else +// angle = -90; +// +// // upstream +// TGeoRotation* coneRot11 = new TGeoRotation; +// coneRot11->RotateZ(angle); +// coneRot11->RotateY(180); +// TGeoCombiTrans* conePosRot11 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-cone_offset[cone_size[iUnit]]-gkLadderGapZ/2., coneRot11); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 1, conePosRot11); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 1, conePosRot11); +// +// // downstream +// TGeoRotation* coneRot12 = new TGeoRotation; +// coneRot12->RotateZ(angle); +// TGeoCombiTrans* conePosRot12 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+cone_offset[cone_size[iUnit]]+gkLadderGapZ/2., coneRot12); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 2, conePosRot12); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 2, conePosRot12); +// +// myunit[iUnit]->GetShape()->ComputeBBox(); +// } + +// CheckVolume(myunit[iUnit]); +// CheckVolume(myunit[iUnit], infoFile); + if ((iUnit%2 == 0)||(iUnit == 15)) + { + CheckVolume(myunit[iUnit*2+0]); + CheckVolume(myunit[iUnit*2+0], infoFile); + CheckVolume(myunit[iUnit*2+1]); + CheckVolume(myunit[iUnit*2+1], infoFile); + } + infoFile << "Position z = " << statPos[iUnit] << endl; + } + // -------------------------------------------------------------------------- + + + // --------------- Create STS volume ------------------------------------ + cout << endl << endl; + cout << "===> Creating STS...." << endl; + +// // --- Determine size of STS box +// Double_t stsX = 0.; +// Double_t stsY = 0.; +// Double_t stsZ = 0.; +// Double_t stsBorder = 2*5.; // 5 cm space for carbon ladders on each side +// for (Int_t iStation = 1; iStation<=8; iStation++) { +// TString statName = Form("Station%02d", iStation); +// TGeoVolume* station = gGeoMan->GetVolume(statName); +// TGeoBBox* shape = (TGeoBBox*) station->GetShape(); +// stsX = TMath::Max(stsX, 2.* shape->GetDX() ); +// stsY = TMath::Max(stsY, 2.* shape->GetDY() ); +// cout << "Station " << iStation << ": Y " << stsY << endl; +// } +// // --- Some border around the stations +// stsX += stsBorder; +// stsY += stsBorder; +// stsZ = ( statPos[7] - statPos[0] ) + stsBorder; +// +// // --- Create box around the stations +// new TGeoBBox("stsBox", stsX/2., stsY/2., stsZ/2.); +// cout << "size of STS box: x " << stsX << " - y " << stsY << " - z " << stsZ << endl; +// +// // --- Create cone hosting the beam pipe +// // --- One straight section with constant radius followed by a cone +// Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +// Double_t z2 = gkPipeZ2; +// Double_t z3 = statPos[7] + 0.5 * stsBorder; // end of STS box +// Double_t r1 = BeamPipeRadius(z1); +// Double_t r2 = BeamPipeRadius(z2); +// Double_t r3 = BeamPipeRadius(z3); +// r1 += 0.01; // safety margin +// r2 += 0.01; // safety margin +// r3 += 0.01; // safety margin +// +// cout << endl; +// cout << z1 << " " << r1 << endl; +// cout << z2 << " " << r2 << endl; +// cout << z3 << " " << r3 << endl; +// +// cout << endl; +// cout << "station1 : " << BeamPipeRadius(statPos[0]) << endl; +// cout << "station2 : " << BeamPipeRadius(statPos[1]) << endl; +// cout << "station3 : " << BeamPipeRadius(statPos[2]) << endl; +// cout << "station4 : " << BeamPipeRadius(statPos[3]) << endl; +// cout << "station5 : " << BeamPipeRadius(statPos[4]) << endl; +// cout << "station6 : " << BeamPipeRadius(statPos[5]) << endl; +// cout << "station7 : " << BeamPipeRadius(statPos[6]) << endl; +// cout << "station8 : " << BeamPipeRadius(statPos[7]) << endl; +// +// // TGeoPcon* cutout = new TGeoPcon("stsCone", 0., 360., 3); // 2.*TMath::Pi(), 3); +// // cutout->DefineSection(0, z1, 0., r1); +// // cutout->DefineSection(1, z2, 0., r2); +// // cutout->DefineSection(2, z3, 0., r3); +// new TGeoTrd2("stsCone1", r1, r2, r1, r2, (z2-z1)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans1 = new TGeoTranslation("trans1", 0., 0., -(z3-z1)/2.+(z2-z1)/2.); +// trans1->RegisterYourself(); +// new TGeoTrd2("stsCone2", r2, r3, r2, r3, (z3-z2)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans2 = new TGeoTranslation("trans2", 0., 0., +(z3-z1)/2.-(z3-z2)/2.); +// trans2->RegisterYourself(); +// +////DE Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +////DE Double_t z2 = statPos[7] + 0.5 * stsBorder; // end of STS box +////DE Double_t slope = (gkPipeR2 - gkPipeR1) / (gkPipeZ2 - gkPipeZ1); +////DE Double_t r1 = gkPipeR1 + slope * (z1 - gkPipeZ1); // at start of STS +////DE Double_t r2 = gkPipeR1 + slope * (z2 - gkPipeZ1); // at end of STS +////DE r1 += 0.1; // safety margin +////DE r2 += 0.1; // safety margin +////DE // new TGeoCone("stsCone", stsZ/2., 0., r1, 0., r2); +////DE new TGeoTrd2("stsCone", r1, r2, r1, r2, stsZ/2.); + + + // // Create holding/cooling plates + // static std::vector< std::vector<Double_t> > plateSizes = { + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // }; + + // // 8-vertex cut-outs { minWidth, maxWidth, minHeight, maxHeight } + // static std::vector< std::vector<Double_t> > plateCutOuts = { + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 17.6, 47.6 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 49.0, 79.0 }, + // { 85.5,115.5, 51.5, 82.8 }, + // { 85.5,115.5, 59.0, 91.4 }, + // { 85.5,115.5, 68.0, 99.0 }, + // }; + + // for (Int_t iPlate = 0; iPlate < 9; iPlate++) { + // Int_t iUnit = iPlate * 2; + // TGeoBBox* outerPlate = new TGeoBBox(Form("outerPlate%02d",iPlate), + // plateSizes[iPlate][0], plateSizes[iPlate][1], plateSizes[iPlate][2]); + + // TGeoBBox* unitShapeR = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+0])->GetShape(); + // TGeoBBox* unitShapeL = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+1])->GetShape(); + + // Double_t maxDx = (unitShapeR->GetDX() + unitShapeL->GetDX()) / 2.; + // Double_t maxDy = TMath::Max(unitShapeR->GetDY(), unitShapeL->GetDY()); + // cout << maxDy << endl; + + // Double_t* cutOutX = new Double_t[8]; + // Double_t* cutOutY = new Double_t[8]; + + // cutOutX[0] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[0] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[1] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[1] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[2] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[2] = 1/2. * plateCutOuts[iPlate][2]; + // cutOutX[3] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[3] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[4] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[4] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[5] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[5] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[6] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[6] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[7] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[7] = 1/2. * plateCutOuts[iPlate][2]; + + // TGeoXtru* cutOutShape = new TGeoXtru(2); + // cutOutShape->SetName(Form("innerPlate%02d", iPlate)); + // cutOutShape->DefinePolygon(8, cutOutX, cutOutY); + // cutOutShape->DefineSection(0, -1*plateSizes[iPlate][2]-1e-7); + // cutOutShape->DefineSection(1, +1*plateSizes[iPlate][2]+1e-7); + + // TGeoShape* plateShape = new TGeoCompositeShape(Form("PlateShape%02d",iPlate), Form("outerPlate%02d-innerPlate%02d",iPlate,iPlate)); + // TGeoVolume* plate = new TGeoVolume(Form("Plate%02d", iPlate), plateShape, gGeoManager->GetMedium("aluminium")); + // plate->SetLineColor(kRed); + // plate->SetTransparency(65); + // plate->GetShape()->ComputeBBox(); + // } + + // --- Create STS volume + TString stsName = "sts_"; + stsName += geoTag; + +// TGeoShape* stsShape = new TGeoCompositeShape("stsShape", +// "stsBox-stsCone1:trans1-stsCone2:trans2"); +// TGeoVolume* sts = new TGeoVolume(stsName.Data(), stsShape, gStsMedium); + + Double_t stsBorder = 2 * 5.; + + TGeoVolume* sts = new TGeoVolumeAssembly(stsName.Data()); + + // --- Place stations in the STS + Double_t stsPosZ = 0.5 * ( statPos[15] + statPos[0] ); // todo units: update statPos[7] + // cout << "stsPosZ " << stsPosZ << " " << statPos[15] << " " << statPos[0] << "*****" << endl; + +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) { + for (Int_t iUnit = 0; iUnit < 18; iUnit++) { +// for (Int_t iUnit = 0; iUnit < 32; iUnit++) { + TGeoVolume* station = gGeoMan->GetVolume(unitName18[iUnit]); +// Double_t posZ = statPos[iUnit] - stsPosZ; + Double_t posZ = statPos18[iUnit] - stsPosZ; +// Double_t posZ = statPos[iUnit/2] - stsPosZ; + TGeoTranslation* trans = new TGeoTranslation(0., 0., posZ); + sts->AddNode(station, iUnit+1, trans); + sts->GetShape()->ComputeBBox(); + } + + // --- Import passive elements from GDML file + if (gkImportPassive) { + ImportPassive(sts, geoTag, infoFile); + } + + cout << endl; + CheckVolume(sts); + // -------------------------------------------------------------------------- + + + // --------------- Finish ----------------------------------------------- + TGeoTranslation* stsTrans = new TGeoTranslation(0., 0., stsPosZ); + top->AddNode(sts, 1, stsTrans); + top->GetShape()->ComputeBBox(); + cout << endl << endl; + + CheckVolume(top); + cout << endl << endl; + gGeoMan->CloseGeometry(); + gGeoMan->CheckOverlaps(0.0001); + gGeoMan->PrintOverlaps(); + gGeoMan->CheckOverlaps(0.0001, "s"); + gGeoMan->PrintOverlaps(); + gGeoMan->Test(); + + TFile* geoFile = new TFile(geoFileName, "RECREATE"); + top->Write(); + cout << endl; + cout << "Geometry " << top->GetName() << " written to " + << geoFileName << endl; + geoFile->Close(); + + TString geoFileName_ = "sts_"; + geoFileName_ = geoFileName_ + geoTag + "_geo.root"; + + geoFile = new TFile(geoFileName_, "RECREATE"); + gGeoMan->Write(); // use this is you want GeoManager format in the output + geoFile->Close(); + + TString geoFileName__ = "sts_"; + geoFileName_ = geoFileName__ + geoTag + "-geo.root"; + sts->Export(geoFileName_); + + geoFile = new TFile(geoFileName_, "UPDATE"); + stsTrans->Write(); + geoFile->Close(); + + // gGeoManager->FindVolumeFast("LadderType10_CarbonElement")->Draw("ogl"); + top->Draw("ogl"); + gGeoManager->SetVisLevel(8); + + infoFile.close(); + +} +// ============================================================================ +// ====== End of main function ===== +// ============================================================================ + + + + + +// **************************************************************************** +// ***** Definition of media, sensors, sectors and ladders ***** +// ***** ***** +// ***** Decoupled from main function for better readability ***** +// **************************************************************************** + + +/** =========================================================================== + ** Create media + ** + ** Currently created: air, active silicon, passive silion + ** + ** Not used for the time being + **/ +Int_t CreateMedia() { + + Int_t nMedia = 0; + Double_t density = 0.; + + // --- Material air + density = 1.205e-3; // [g/cm^3] + TGeoMixture* matAir = new TGeoMixture("sts_air", 3, density); + matAir->AddElement(14.0067, 7, 0.755); // Nitrogen + matAir->AddElement(15.999, 8, 0.231); // Oxygen + matAir->AddElement(39.948, 18, 0.014); // Argon + + // --- Material silicon + density = 2.33; // [g/cm^3] + TGeoElement* elSi = gGeoMan->GetElementTable()->GetElement(14); + TGeoMaterial* matSi = new TGeoMaterial("matSi", elSi, density); + + + // --- Air (passive) + TGeoMedium* medAir = new TGeoMedium("air", nMedia++, matAir); + medAir->SetParam(0, 0.); // is passive + medAir->SetParam(1, 1.); // is in magnetic field + medAir->SetParam(2, 20.); // max. field [kG] + medAir->SetParam(6, 0.001); // boundary crossing precision [cm] + + + // --- Active silicon for sensors + TGeoMedium* medSiAct = new TGeoMedium("silicon", + nMedia++, matSi); + medSiAct->SetParam(0, 1.); // is active + medSiAct->SetParam(1, 1.); // is in magnetic field + medSiAct->SetParam(2, 20.); // max. field [kG] + medSiAct->SetParam(6, 0.001); // boundary crossing precisison [cm] + + // --- Passive silicon for cables + TGeoMedium* medSiPas = new TGeoMedium("carbon", + nMedia++, matSi); + medSiPas->SetParam(0, 0.); // is passive + medSiPas->SetParam(1, 1.); // is in magnetic field + medSiPas->SetParam(2, 20.); // max. field [kG] + medSiPas->SetParam(6, 0.001); // boundary crossing precisison [cm] + + return nMedia; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sensors + ** + ** Sensors are created as volumes with box shape and active silicon as medium. + ** Four kinds of sensors: 3.2x2.2, 6.2x2.2, 6.2x4.2, 6.2x6.2 + **/ +Int_t CreateSensors() { + + Int_t nSensors = 0; + + Double_t xSize = 0.; + Double_t ySize = 0.; + Double_t zSize = gkSensorThickness; + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + + + // --- Sensor type 01: Small sensor (6.2 cm x 2.2 cm) + xSize = gkSensorSizeX; + ySize = 2.2; + TGeoBBox* shape_sensor01 = new TGeoBBox("sensor01", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor01", shape_sensor01, silicon); + nSensors++; + + + // --- Sensor type 02: Medium sensor (6.2 cm x 4.2 cm) + xSize = gkSensorSizeX; + ySize = 4.2; + TGeoBBox* shape_sensor02 = new TGeoBBox("sensor02", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor02", shape_sensor02, silicon); + nSensors++; + + + // --- Sensor type 03: Big sensor (6.2 cm x 6.2 cm) + xSize = gkSensorSizeX; + ySize = 6.2; + TGeoBBox* shape_sensor03 = new TGeoBBox("sensor03", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor03", shape_sensor03, silicon); + nSensors++; + + + // --- Sensor type 04: Big sensor (6.2 cm x 12.4 cm) + xSize = gkSensorSizeX; + ySize = 12.4; + TGeoBBox* shape_sensor04 = new TGeoBBox("sensor04", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor04", shape_sensor04, silicon); + nSensors++; + + + // below are extra small sensors, those are not available in the CAD model + + // --- Sensor Type 05: Half small sensor (4 cm x 2.5 cm) + xSize = 4.0; + ySize = 2.5; + TGeoBBox* shape_sensor05 = new TGeoBBox("sensor05", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor05", shape_sensor05, silicon); + nSensors++; + + + // --- Sensor type 06: Additional "in hole" sensor (3.1 cm x 4.2 cm) + xSize = 3.1; + ySize = 4.2; + TGeoBBox* shape_sensor06 = new TGeoBBox("sensor06", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor06", shape_sensor06, silicon); + nSensors++; + + + // --- Sensor type 07: Mini Medium sensor (1.5 cm x 4.2 cm) + xSize = 1.5; + ySize = 4.2; + TGeoBBox* shape_sensor07 = new TGeoBBox("sensor07", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor07", shape_sensor07, silicon); + nSensors++; + + + return nSensors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sectors + ** + ** A sector is either a single sensor or several chained sensors. + ** It is implemented as TGeoVolumeAssembly. + ** Currently available: + ** - single sensors of type 1 - 4 + ** - two chained sensors of type 4 + ** - three chained sensors of type 4 + **/ +Int_t CreateSectors() { + + Int_t nSectors = 0; + + TGeoVolume* sensor01 = gGeoMan->GetVolume("Sensor01"); + TGeoVolume* sensor02 = gGeoMan->GetVolume("Sensor02"); + TGeoVolume* sensor03 = gGeoMan->GetVolume("Sensor03"); + TGeoVolume* sensor04 = gGeoMan->GetVolume("Sensor04"); + TGeoVolume* sensor05 = gGeoMan->GetVolume("Sensor05"); + TGeoVolume* sensor06 = gGeoMan->GetVolume("Sensor06"); + TGeoVolume* sensor07 = gGeoMan->GetVolume("Sensor07"); + // TGeoBBox* box4 = (TGeoBBox*) sensor04->GetShape(); + + // --- Sector type 1: single sensor of type 1 + TGeoVolumeAssembly* sector01 = new TGeoVolumeAssembly("Sector01"); + sector01->AddNode(sensor01, 1); + sector01->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 2: single sensor of type 2 + TGeoVolumeAssembly* sector02 = new TGeoVolumeAssembly("Sector02"); + sector02->AddNode(sensor02, 1); + sector02->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 3: single sensor of type 3 + TGeoVolumeAssembly* sector03 = new TGeoVolumeAssembly("Sector03"); + sector03->AddNode(sensor03, 1); + sector03->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 4: single sensor of type 4 + TGeoVolumeAssembly* sector04 = new TGeoVolumeAssembly("Sector04"); + sector04->AddNode(sensor04, 1); + sector04->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 5: single sensor of type 5 + TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); + sector05->AddNode(sensor05, 1); + sector05->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 6: single sensor of type 6 + TGeoVolumeAssembly* sector06 = new TGeoVolumeAssembly("Sector06"); + sector06->AddNode(sensor06, 1); + sector06->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 7: single sensor of type 7 + TGeoVolumeAssembly* sector07 = new TGeoVolumeAssembly("Sector07"); + sector07->AddNode(sensor07, 1); + sector07->GetShape()->ComputeBBox(); + nSectors++; + +// // --- Sector type 5: two sensors of type 4 +// TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); +// Double_t shift5 = 0.5 * gkChainGapY + box4->GetDY(); +// TGeoTranslation* transD5 = +// new TGeoTranslation("td", 0., -1. * shift5, 0.); +// TGeoTranslation* transU5 = +// new TGeoTranslation("tu", 0., shift5, 0.); +// sector05->AddNode(sensor04, 1, transD5); +// sector05->AddNode(sensor04, 2, transU5); +// sector05->GetShape()->ComputeBBox(); +// nSectors++; + + return nSectors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create ladders + ** + ** Ladders are the building blocks of the stations. They contain + ** several modules placed one after the other along the z axis + ** such that the sectors are arranged vertically (with overlap). + ** + ** A ladder is constructed out of two half ladders, the second of which + ** is rotated in the x-y plane by 180 degrees and displaced + ** in z direction. + **/ +Int_t CreateLadders() { + + Int_t nLadders = 0; + + // --- Some variables + Int_t nSectors = 0; + Int_t sectorTypes[10]; + TGeoBBox* shape = NULL; + TString s0name; + TString hlname; + char align; + TGeoVolume* s0vol = NULL; + TGeoVolume* halfLadderU = NULL; + TGeoVolume* halfLadderD = NULL; + + // --- Ladders 01-23 + Int_t allSectorTypes[27][6] = { { 1, 2, 3, 3, 0, -1 }, // ladder 01 - 5 - last column defines alignment of small sensors + { 1, 2, 3, 3, 0, 0 }, // ladder 02 - 5 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, -1 }, // ladder 03 - 6 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 04 - 6 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, -1 }, // ladder 05 - 7 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 06 - 7 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 07 - last column defines alignment of small sensors + { 3, 4, 4, 4, 0, 0 }, // ladder 08 - last column defines alignment of small sensors + + { 1, 1, 2, 3, 3, 0 }, // ladder 09 - last column defines alignment of small sensors + { 1, 1, 2, 2, 3, 0 }, // ladder 10 - last column defines alignment of small sensors + { 2, 2, 0, 0, 0, 0 }, // ladder 11 - last column defines alignment of small sensors + { 2, 2, 2, 3, 4, 0 }, // ladder 12 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 13 - last column defines alignment of small sensors + + { 2, 3, 4, 0, 0, 0 }, // ladder 14 - last column defines alignment of small sensors + { 3, 3, 0, 0, 0, 0 }, // ladder 15 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 16 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 17 - last column defines alignment of small sensors + { 3, 4, 4, 0, 0, 0 }, // ladder 18 - last column defines alignment of small sensors + + { 4, 4, 0, 0, 0, 0 }, // ladder 19 - last column defines alignment of small sensors + { 1, 2, 4, 4, 4, 0 }, // ladder 20 - last column defines alignment of small sensors + { 4, 0, 0, 0, 0, 0 }, // ladder 21 - last column defines alignment of small sensors + { 2, 3, 4, 4, 4, 0 }, // ladder 22 - last column defines alignment of small sensors + { 2, 3, 3, 4, 4, 0 }, // ladder 23 - last column defines alignment of small sensors + + { 2, 3, 4, 4, 0, 0 }, // ladder 24 - copy of 17 with different total length + { 3, 4, 4, 0, 0, 0 }, // ladder 25 - copy of 18 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 26 - copy of 19 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 27 - copy of 19 with different total length + }; // 8 full - 19 partial ladders + +// Issue #405 +// Counting from the most upstream ladder, the gaps between sensors are as follows: +// 01 (most upstream): 41.3mm +// 02: 41.3mm +// 03: 42.0mm +// 04: 48.6mm +// 05: 60.8mm +// 06: 67.0mm +// 07: 79.2mm +// 08 (most downstream): 88.0mm + + Double_t offsetZcarbon = 0; + Double_t gapXYZ[27][3] = { + { 0., 4.13, 0. }, // ladder 01 + { 0., 4.13, 0. }, // ladder 02 + { 0., 4.20, 0. }, // ladder 03 + { 0., 4.86, 0. }, // ladder 04 + { 0., 6.08, 0. }, // ladder 05 + { 0., 6.70, 0. }, // ladder 06 + { 0., 7.92, 0. }, // ladder 07 + { 0., 8.80, 0. }, // ladder 08 + { 0., -gkSectorOverlapY, 0. }, // ladder 09 + { 0., -gkSectorOverlapY, 0. }, // ladder 10 + { 0., -gkSectorOverlapY, 0. }, // ladder 11 + { 0., -gkSectorOverlapY, 0. }, // ladder 12 + { 0., -gkSectorOverlapY, 0. }, // ladder 13 + { 0., -gkSectorOverlapY, 0. }, // ladder 14 + { 0., -gkSectorOverlapY, 0. }, // ladder 15 + { 0., -gkSectorOverlapY, 0. }, // ladder 16 + { 0., -gkSectorOverlapY, 0. }, // ladder 17 + { 0., -gkSectorOverlapY, 0. }, // ladder 18 + { 0., -gkSectorOverlapY, 0. }, // ladder 19 + { 0., -gkSectorOverlapY, 0. }, // ladder 20 + { 0., -gkSectorOverlapY, 0. }, // ladder 21 + { 0., -gkSectorOverlapY, 0. }, // ladder 22 + { 0., -gkSectorOverlapY, 0. }, // ladder 23 + + { 0., -gkSectorOverlapY, 0. }, // ladder 24 - copy of 17 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 25 - copy of 18 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 26 - copy of 19 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 27 - copy of 19 with different total length + }; + + Double_t ladderLength[27] = { + 48.0, // ladder 01 + 48.0, // ladder 02 + 64.0, // ladder 03 + 64.0, // ladder 04 + 80.0, // ladder 05 + 80.0, // ladder 06 + 92.0, // ladder 07 + 96.0, // ladder 08 + 48.0, // ladder 09 + 48.0, // ladder 10 + 48.0, // ladder 11 + 64.0, // ladder 12 + 64.0, // ladder 13 + 64.0, // ladder 14 + 64.0, // ladder 15 + 80.0, // ladder 16 + 80.0, // ladder 17 + 80.0, // ladder 18 + 80.0, // ladder 19 + 92.0, // ladder 20 + 92.0, // ladder 21 + 96.0, // ladder 22 + 96.0, // ladder 23 + + 96.0, // ladder 24 - copy of 17 with different total length + 92.0, // ladder 25 - copy of 18 with different total length + 96.0, // ladder 26 - copy of 19 with different total length + 92.0, // ladder 27 - copy of 19 with different total length + }; +// ======================================================================== + + // calculate Z shift for ladders with and without gaps in the center + s0name = Form("Sector%02d", allSectorTypes[0][0]); + s0vol = gGeoMan->GetVolume(s0name); + shape = (TGeoBBox*) s0vol->GetShape(); + +// ======================================================================== + + for (Int_t iLadder = 0; iLadder < 27; iLadder++) + { + cout << endl; + nSectors = 0; + for (Int_t i=0; i < 5; i++) + if (allSectorTypes[iLadder][i] != 0) + { + sectorTypes[nSectors] = allSectorTypes[iLadder][i]; // copy sectors for this ladder + cout << "DE iLadder " << iLadder+1 << " sectorTypes[" << nSectors << "] = " << allSectorTypes[iLadder][i] << ";" << endl; + nSectors++; // count how many sectors are in this ladder + } + + // always set displacement in z between upper and lower half ladder + gapXYZ[iLadder][2] = 2. * shape->GetDZ() + gkSectorGapZ; + + // define additional offset to carbon ladder for half ladders with less than 5 sensors + offsetZcarbon = (5 - nSectors) * (2. * shape->GetDZ() + gkSectorGapZ); + + if (allSectorTypes[iLadder][5] == 0) + align = 'l'; + else + align = 'r'; + hlname = Form("HalfLadder%02du", iLadder+1); + // build upper half ladder + halfLadderU = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2.); // mirrored + + if (allSectorTypes[iLadder][5] == 0) + align = 'r'; + else + align = 'l'; + hlname = Form("HalfLadder%02dd", iLadder+1); + // build lower half ladder + halfLadderD = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2.); // mirrored + + // at this point half ladders are constructed + + // build all 4 possible ladders types for this sensor arrangement + ConstructLadder( iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], offsetZcarbon); // v19a + ConstructLadder( 100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], offsetZcarbon); // v19b + + ConstructLadder(1000+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], offsetZcarbon); // v19k + ConstructLadder(1100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], offsetZcarbon); // v19k + + nLadders++; + } + + return nLadders; +} +/** ======================================================================= **/ + + + +// **************************************************************************** +// ***** ***** +// ***** Generic functions for the construction of STS elements ***** +// ***** ***** +// ***** module: volume (made of a sector and a cable) ***** +// ***** haf ladder: assembly (made of modules) ***** +// ***** ladder: assembly (made of two half ladders) ***** +// ***** station: volume (made of ladders) ***** +// ***** ***** +// **************************************************************************** + + + +/** =========================================================================== + ** Construct a module + ** + ** A module is a sector plus the readout cable extending from the + ** top of the sector. The cable is made from passive silicon. + ** The cable has the same x size as the sector. + ** Its thickness is given by the global variable gkCableThickness. + ** The cable length is a parameter. + ** The sensor(s) of the sector is/are placed directly in the module; + ** the sector is just auxiliary for the proper placement. + ** + ** Arguments: + ** name volume name + ** sector pointer to sector volume + ** cableLength length of cable + **/ +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength) { + + // --- Check sector volume + if ( ! sector ) Fatal("CreateModule", "Sector volume not found!"); + + // --- Get size of sector + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + + // --- Get size of cable + Double_t cableX = sectorX; + Double_t cableY = cableLength; + Double_t cableZ = gkCableThickness; + + // --- Create module volume + Double_t moduleX = TMath::Max(sectorX, cableX); + Double_t moduleY = sectorY + cableLength; + + Double_t moduleZ = TMath::Max(sectorZ, cableZ); + + TGeoVolume* module = gGeoManager->MakeBox(name, gStsMedium, + moduleX/2., + moduleY/2., + moduleZ/2.); + + // --- Position of sector in module + // --- Sector is centred in x and z and aligned to the bottom + Double_t sectorXpos = 0.; + Double_t sectorYpos = 0.5 * (sectorY - moduleY); + Double_t sectorZpos = 0.; + + + // --- Get sensor(s) from sector + Int_t nSensors = sector->GetNdaughters(); + for (Int_t iSensor = 0; iSensor < nSensors; iSensor++) { + TGeoNode* sensor = sector->GetNode(iSensor); + + // --- Calculate position of sensor in module + const Double_t* xSensTrans = sensor->GetMatrix()->GetTranslation(); + Double_t sensorXpos = 0.; + Double_t sensorYpos = sectorYpos + xSensTrans[1]; + Double_t sensorZpos = 0.; + TGeoTranslation* sensTrans = new TGeoTranslation("sensTrans", + sensorXpos, + sensorYpos, + sensorZpos); + + // --- Add sensor volume to module + TGeoVolume* sensVol = sensor->GetVolume(); + module->AddNode(sensor->GetVolume(), iSensor+1, sensTrans); + module->GetShape()->ComputeBBox(); + } + + + // --- Create cable volume, if necessary, and place it in module + // --- Cable is centred in x and z and aligned to the top + if ( gkConstructCables && cableLength > 0.0001 ) { + TString cableName = TString(name) + "_cable"; + TGeoMedium* cableMedium = gGeoMan->GetMedium("STScable"); + if ( ! cableMedium ) Fatal("CreateModule", "Medium STScable not found!"); + TGeoVolume* cable = gGeoManager->MakeBox(cableName.Data(), + cableMedium, + cableX / 2., + cableY / 2., + cableZ / 2.); + // add color to cables + cable->SetLineColor(kOrange); + cable->SetTransparency(60); + Double_t cableXpos = 0.; + Double_t cableYpos = sectorY + 0.5 * cableY - 0.5 * moduleY; + Double_t cableZpos = 0.; + TGeoTranslation* cableTrans = new TGeoTranslation("cableTrans", + cableXpos, + cableYpos, + cableZpos); + module->AddNode(cable, 1, cableTrans); + module->GetShape()->ComputeBBox(); + } + + return module; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a half ladder + ** + ** A half ladder is a virtual volume (TGeoVolumeAssembly) consisting + ** of several modules arranged on top of each other. The modules + ** have a given overlap in y and a displacement in z to allow for the + ** overlap. + ** + ** The typ of sectors / modules to be placed must be specified: + ** 1 = sensor01 + ** 2 = sensor02 + ** 3 = sensor03 + ** 4 = sensor04 + ** 5 = 2 x sensor04 (chained) + ** 6 = 3 x sensor04 (chained) + ** The cable is added automatically from the top of each sensor to + ** the top of the half ladder. + ** The alignment can be left (l) or right (r), which matters in the + ** case of different x sizes of sensors (e.g. SensorType01). + ** + ** Arguments: + ** name volume name + ** nSectors number of sectors + ** sectorTypes array with sector types + ** align horizontal alignment of sectors + * ladderLength full length of the ladder towards FEE + * offsetY gap in the beam-pipe region + **/ +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY) { + + // --- Create half ladder volume assembly + TGeoVolumeAssembly* halfLadder = new TGeoVolumeAssembly(name); + + // --- Determine size of ladder + Double_t ladderX = 0.; + Double_t ladderY = 0.; + Double_t ladderZ = 0.; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + if ( ! sector ) + Fatal("ConstructHalfLadder", Form("Volume %s not found", sectorName.Data())); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + // --- Ladder x size equals largest sector x size + ladderX = TMath::Max(ladderX, 2. * box->GetDX()); + // --- Ladder y size is sum of sector ysizes + ladderY += 2. * box->GetDY(); + // --- Ladder z size is sum of sector z sizes + ladderZ += 2. * box->GetDZ(); + } + // --- Subtract overlaps in y + ladderY -= Double_t(nSectors-1) * gkSectorOverlapY; + // --- Add gaps in z direction + ladderZ += Double_t(nSectors-1) * gkSectorGapZ; + + ladderY = TMath::Max(ladderLength - offsetY, ladderY); + + // --- Create and place modules + Double_t yPosSect = -0.5 * ladderY; + Double_t zPosMod = -0.5 * ladderZ; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + yPosSect += 0.5 * sectorY; // Position of sector in ladder + Double_t cableLength = 0.5 * ladderY - yPosSect - 0.5 * sectorY; + TString moduleName = name + "_" + Form("Module%02d", + sectorTypes[iSector]); + TGeoVolume* module = ConstructModule(moduleName.Data(), + sector, cableLength); + + TGeoBBox* shapeMod = (TGeoBBox*) module->GetShape(); + Double_t moduleX = 2. * shapeMod->GetDX(); + Double_t moduleY = 2. * shapeMod->GetDY(); + Double_t moduleZ = 2. * shapeMod->GetDZ(); + Double_t xPosMod = 0.; + if ( align == 'l' ) + xPosMod = 0.5 * (moduleX - ladderX); // left aligned + else if ( align == 'r' ) + xPosMod = 0.5 * (ladderX - moduleX); // right aligned + else + xPosMod = 0.; // centred in x + Double_t yPosMod = 0.5 * (ladderY - moduleY); // top aligned + zPosMod += 0.5 * moduleZ; + TGeoTranslation* trans = new TGeoTranslation("t", xPosMod, + yPosMod, zPosMod); + halfLadder->AddNode(module, iSector+1, trans); + halfLadder->GetShape()->ComputeBBox(); + yPosSect += 0.5 * sectorY - gkSectorOverlapY; + zPosMod += 0.5 * moduleZ + gkSectorGapZ; + } + + CheckVolume(halfLadder); + cout << endl; + + return halfLadder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Add a carbon support to a ladder + ** + ** Arguments: + ** LadderIndex ladder number + ** ladder pointer to ladder + ** xu size of halfladder + ** ladderY height of ladder along y + ** ladderZ thickness of ladder along z + **/ +void AddCarbonLadder(Int_t LadderIndex, + TGeoVolume* ladder, + Double_t xu, + Double_t ladderY, + Double_t ladderZ) { + + // --- Some variables + TString name = Form("LadderType%04d", LadderIndex); // v19k + Int_t i; + Double_t j; + + Int_t YnumOfFrameBoxes = round(ladderY / gkFrameStep); + + // cout << "DEXZ: lad " << LadderIndex << " inum " << YnumOfFrameBoxes << endl; + + Double_t ladderDZ = (xu/2. + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2)/2.; + cout << "DEFR: frame Z size " << 2 * ladderDZ << " cm" << endl; + + TGeoBBox* fullFrameShp = new TGeoBBox (name+"_CarbonElement_shp", xu/2., gkFrameStep/2., ladderDZ); + TGeoVolume* fullFrameBoxVol = new TGeoVolume(name+"_CarbonElement", fullFrameShp, gStsMedium); + + ConstructFrameElement("CarbonElement", fullFrameBoxVol, xu/2.); + TGeoRotation* fullFrameRot = new TGeoRotation; + fullFrameRot->RotateY(180); + + Int_t inum = YnumOfFrameBoxes; + for (i=1; i<=inum; i++) + { + j=-(inum-1)/2.+(i-1); + // -(10-1)/2. +0 +10-1 -> -4.5 .. +4.5 -> -0.5, +0.5 (= 2) + // -(11-1)/2. +0 +11-1 -> -5.0 .. +5.0 -> -1, 0, 1 (= 3) + // cout << "DE: i " << i << " j " << j << endl; + + if (LadderIndex % 100 <= 3) // central ladders in stations 1 to 3 + { + if ((j>=-1) && (j<=1)) // keep the inner 2 (even) or 3 (odd) elements free for the cone + continue; + } + else if (LadderIndex % 100 <= 8) // central ladders in stations 4 to 8 + { + if ((j>=-2) && (j<=2)) // keep the inner 4 elements free for the cone + continue; + } + + cout << "DELZ: ladderDZ " << ladderDZ << " cm " << -ladderZ/2. - ladderDZ << " cm " << endl; + ladder->AddNode(fullFrameBoxVol, i, new TGeoCombiTrans(name+"_CarbonElement_posrot", 0., j*gkFrameStep, -(ladderZ/2.+ladderDZ), fullFrameRot)); + } + + ladder->GetShape()->ComputeBBox(); + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Construct a ladder out of two half ladders with vertical gap + ** + ** The second half ladder will be rotated by 180 degrees + ** in the x-y plane. The two half ladders will be put on top of each + ** other with a vertical gap. + ** + ** Arguments: + ** name volume name + ** halfLadderU pointer to upper half ladder + ** halfLadderD pointer to lower half ladder + ** gapY vertical gap + ** shiftZ relative displacement along the z axis + **/ + + TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ, + Double_t offsetZ) { + + // --- Some variables + TGeoBBox* shape = NULL; + + // --- Dimensions of half ladders + shape = (TGeoBBox*) halfLadderU->GetShape(); // up + Double_t xu = 2. * shape->GetDX(); + Double_t yu = 2. * shape->GetDY(); + Double_t zu = 2. * shape->GetDZ(); + + shape = (TGeoBBox*) halfLadderD->GetShape(); // down + Double_t xd = 2. * shape->GetDX(); + Double_t yd = 2. * shape->GetDY(); + Double_t zd = 2. * shape->GetDZ(); + + // --- Create ladder volume assembly + TString name = Form("LadderType%04d", LadderIndex); // v19k + TGeoVolumeAssembly* ladder = new TGeoVolumeAssembly(name); + Double_t ladderX = TMath::Max(xu, xd); + Double_t ladderY = yu + yd + gapY; + // Double_t ladderZ = TMath::Max(zu, zd + shiftZ); + Double_t ladderZ = TMath::Max(zu, zd + shiftZ + offsetZ); + + cout << "DERR iladder " << LadderIndex << " zu " << zu << " zd " << zd + << " zd+shi " << zd+shiftZ << " ladderZ " << ladderZ << endl; + + // --- Place half ladders + Double_t xPosU = 0.; // centred in x + Double_t yPosU = 0.5 * ( ladderY - yu ); // top aligned + Double_t zPosU = 0.5 * ( ladderZ - zu ); // front aligned // mount upper half ladder last + if (LadderIndex >= 1000) zPosU = -zPosU; // back aligned // mount upper half ladder first + + TGeoTranslation* tu = new TGeoTranslation("tu", xPosU, yPosU, zPosU); + ladder->AddNode(halfLadderU, 1, tu); + + Double_t xPosD = 0.; // centred in x + Double_t yPosD = 0.5 * ( yd - ladderY ); // bottom aligned + Double_t zPosD = 0.5 * ( zd - ladderZ ); // back aligned // mount lower half ladder first + if (LadderIndex >= 1000) zPosD = -zPosD; // front aligned // mount lower half ladder last + + TGeoRotation* rd = new TGeoRotation(); + rd->RotateZ(180.); + TGeoCombiTrans* cd = new TGeoCombiTrans(xPosD, yPosD, zPosD, rd); + ladder->AddNode(halfLadderD, 2, cd); + + ladder->GetShape()->ComputeBBox(); + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD0ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + cout << "DDDD ladder" << LadderIndex << endl; + cout << "DDDD1ladder" << LadderIndex << " ladderX " << ladderX << " ladderY " << ladderY << " ladderZ " << ladderZ << endl; + + // ---------------- Create and place frame boxes ------------------------ + + if (gkConstructFrames) + AddCarbonLadder(LadderIndex, ladder, ladderX, ladderY, ladderZ); + + // -------------------------------------------------------------------------- + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD2ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + return ladder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a unit + ** + ** The unit volume is the minimal box comprising all ladders + ** minus a tube accomodating the beam pipe. + ** + ** The ladders are arranged horizontally from left to right with + ** a given overlap in x. + ** Every second ladder is slightly displaced upstream from the centre + ** z plane and facing downstream, the others are slightly displaced + ** downstream and facing upstream (rotated around the y axis). + ** + ** Arguments: + ** name volume name + ** nLadders number of ladders + ** ladderTypes array of ladder types + **/ + + TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation) { + + Bool_t isFirstPartOfHalfUnit = kFALSE; + + // TString name = Form("Unit%02d", iUnit); // 0,1,2,3,4,5,6,7 - Unit00 missing in output + // TString name = Form("Unit%02d", iUnit+1); // 1,2,3,4,5,6,7,8 + + TGeoVolume* unit = gGeoMan->GetVolume(unitName[iUnit]); + if ( ! unit ) // if it does not yet exist, create a new one + { + unit = new TGeoVolumeAssembly(unitName[iUnit]); + isFirstPartOfHalfUnit = kTRUE; + } + + // --- Some local variables + TGeoBBox* ladderShape = NULL; + TGeoVolume* ladder = NULL; + TString ladderName; + Double_t subtractedVal; + + // --- Determine size of unit from ladders + Double_t statX = 0.; + // Double_t statY = 0.; + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) + { + Int_t ladderType = ladderTypes[iLadder]; // v19k + +// if (iSide == 0) cout << "DWER " << ladderTypes[iLadder] << " " << ladderType << endl; + + if (ladderType > 0) + { + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + if ( ! ladder ) Fatal("ConstructUnit", + Form("Volume %s not found", ladderName.Data())); + ladderShape = (TGeoBBox*) ladder->GetShape(); + statX += 2. * ladderShape->GetDX(); + } + else + statX += gkSensorSizeX; // empty ladder in unit + } + statX -= Double_t(nLadders-1) * gkLadderOverlapX; + +// if (iSide == 0) cout << "DWER -" << endl; + + // --- Place ladders in unit + cout << "xPos0: " << statX << endl; + Double_t xPos = -0.5 * statX; + cout << "xPos1: " << xPos << endl; + Double_t yPos = 0.; + Double_t zPos = 0.; + + Double_t maxdz = 0.; + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) // find maximum dz in this unit + { + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + if (maxdz < ladderShape->GetDZ()) + maxdz = ladderShape->GetDZ(); + } + } + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) + { + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + xPos += ladderShape->GetDX(); + cout << "xPos2: " << xPos << endl; + yPos = 0.; // vertically centred + TGeoRotation* rot = new TGeoRotation(); + + if (gkConstructFrames) + subtractedVal = ladderShape->GetDX() + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2; + else + subtractedVal = 0.; + + zPos = 0.5 * gkLadderGapZ + (2*maxdz-ladderShape->GetDZ()-subtractedVal/2.); // z-aligned ladders + +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " dx: " << ladderShape->GetDX() + << " dy: " << ladderShape->GetDY() + << " dz: " << ladderShape->GetDZ() + << " max dz: " << maxdz << endl; + +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " fra: " << gkFrameThickness/2. + << " sub: " << subtractedVal + << " zpo: " << zPos << endl << endl; + +// v19k + if (ladderTypes[iLadder]/1000 == 1) // flip some of the ladders to reproduce the CAD layout + rot->RotateY(180.); + else + zPos = -zPos; + + if (!isFirstPartOfHalfUnit) + zPos += 10.5; // v19d +// zPos += 10.0; // initial version + + TGeoCombiTrans* trans = new TGeoCombiTrans(xPos, yPos, zPos, rot); +// start +// cout << "DEEE** iLadder " << iLadder << " " << nLadders/2 << " " << nLadders << endl; + + if (iSide == 0) + { + if (iLadder < nLadders/2) // right side - only half unit -x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + else + { + if (iLadder >= nLadders/2) // left side - only half unit +x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + unit->GetShape()->ComputeBBox(); +// stop + xPos += ladderShape->GetDX() - gkLadderOverlapX; + cout << "xPos3: " << xPos << endl; + } + else + xPos += gkSensorSizeX - gkLadderOverlapX; + } + + return unit; + } +/** ======================================================================= **/ + + +/** =========================================================================== + ** Import and add the passive materials to the STS volume + **/ +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile) +{ + TString passiveName = TString("sts_passive_") + geoTag; + TString basePath = gSystem->Getenv("VMCWORKDIR"); + TString relPath = "/geometry/sts/passive/" + passiveName + ".gdml"; + TString passiveFileName = basePath + relPath; + infoFile << std::endl << std::endl; + infoFile << "Importing STS passive materials from GDML file '" << relPath << "'." << std::endl; + + TGDMLParse parser; + TGeoVolume* gdmlVolume = parser.GDMLReadFile(passiveFileName); + PostProcessGdml(gdmlVolume); + gdmlVolume->SetName(passiveName); + + TGeoTranslation* passiveTrans = new TGeoTranslation(0., 0., 4.68 - 2.); + infoFile << "Passive assembly is translated for Z=2.68 cm downstream with respect to parent volume" << std::endl << std::endl; + + gdmlVolume->GetShape()->ComputeBBox(); + CheckVolume(gdmlVolume, infoFile); + + infoFile << std::endl; + for (Int_t iNode = 0; iNode < gdmlVolume->GetNdaughters(); iNode++) { + CheckVolume(gdmlVolume->GetNode(iNode)->GetVolume(), infoFile, kFALSE); + } + + stsVolume->AddNode(gdmlVolume, stsVolume->GetNdaughters(), passiveTrans, ""); +} + +/** =========================================================================== + ** Assign visual properties to the imported gdml volumes + **/ +void PostProcessGdml(TGeoVolume* gdmlVolume) +{ + const UInt_t kPOBColor = kRed-6; + const UInt_t kPOBTransparency = 0;// 5; + + const UInt_t kFEBColor = kOrange-6; + const UInt_t kFEBTransparency = 0;// 5; + + const UInt_t kUnitColor = kCyan-10; + const UInt_t kUnitTransparency = 0;// 5; + + const UInt_t kCfColor = kGray+3; + const UInt_t kCfTransparency = 0;// 10; + + // name <Color, Transparency> + std::map<std::string, std::tuple<UInt_t,UInt_t> > props { + { "passive_POB", std::tuple<UInt_t,UInt_t> {kPOBColor, kPOBTransparency} }, + { "passive_FEB", std::tuple<UInt_t,UInt_t> {kFEBColor, kFEBTransparency} }, + { "passive_unit", std::tuple<UInt_t,UInt_t> {kUnitColor, kUnitTransparency} }, + { "passive_Box_Wall", std::tuple<UInt_t,UInt_t> {kCfColor, kCfTransparency} }, + { "passive_Box_Wall_Front_CF2", std::tuple<UInt_t,UInt_t> {kCfColor-3, kCfTransparency} }, + }; + + // Match volume name and apply visual properties + const TObjArray* volumes = gGeoManager->GetListOfVolumes(); + for (auto& entry : props) { + TIter next(volumes); + TGeoVolume *vol = nullptr; + while ((vol=(TGeoVolume*)next())) { + if (TString(vol->GetName()).Contains(entry.first.c_str())) { + vol->SetLineColor(std::get<0>(entry.second)); + vol->SetTransparency(std::get<1>(entry.second)); + } + } + } +} + +/** =========================================================================== + ** Volume information for debugging + **/ +void CheckVolume(TGeoVolume* volume) { + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + cout << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) cout << ", assembly"; + else { + if ( volume->GetMedium() ) + cout << ", medium " << volume->GetMedium()->GetName(); + else cout << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + cout << endl; + if ( volume->GetNdaughters() ) { + cout << "Daughters: " << endl; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) { + TGeoNode* node = volume->GetNode(iNode); + TGeoBBox* shape = (TGeoBBox*) node->GetVolume()->GetShape(); + cout << setw(15) << node->GetName() << ", size " + << fixed << setprecision(3) + << setw(6) << 2. * shape->GetDX() << " x " + << setw(6) << 2. * shape->GetDY() << " x " + << setw(6) << 2. * shape->GetDZ() << ", position ( "; + TGeoMatrix* matrix = node->GetMatrix(); + const Double_t* pos = matrix->GetTranslation(); + cout << setfill(' '); + cout << fixed << setw(8) << pos[0] << ", " + << setw(8) << pos[1] << ", " + << setw(8) << pos[2] << " )" << endl; + } + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Volume information for output to file + **/ +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren) { + if ( ! file ) return; + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + file << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) file << ", assembly"; + else { + if ( volume->GetMedium() ) + file << ", medium " << volume->GetMedium()->GetName(); + else file << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + file << endl; + if ( volume->GetNdaughters() && listChildren) { + file << "Contains: "; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) + file << volume->GetNode(iNode)->GetVolume()->GetName() << " "; + file << endl; + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Calculate beam pipe outer radius for a given z + **/ +Double_t BeamPipeRadius(Double_t z) { + if ( z < gkPipeZ2 ) return gkPipeR1; + Double_t slope = (gkPipeR3 - gkPipeR2 ) / (gkPipeZ3 - gkPipeZ2); + return gkPipeR2 + slope * (z - gkPipeZ2); +} +/** ======================================================================= **/ + + + +/** ======================================================================= **/ +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + TGeoBBox* frameVertPillarShp; + + Double_t t = gkFrameThickness/2.; + + // --- Main vertical pillars +// TGeoBBox* frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, gkFrameStep/2., t); // square crossection, along y +// TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); +// frameVertPillarVol->SetLineColor(kGreen); +// frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoTranslation(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2.)); +// frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoTranslation(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkCylindricalFrames) + // TGeoBBox* frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", 0, t, gkFrameStep/2.); // circle crossection, along z + frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", gkCylinderDiaInner/2., gkCylinderDiaOuter/2., gkFrameStep/2.); // circle crossection, along z + else + frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, t, gkFrameStep/2.); // square crossection, along z + TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); + frameVertPillarVol->SetLineColor(kGreen); + + TGeoRotation* xRot90 = new TGeoRotation; + xRot90->RotateX(90.); + frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoCombiTrans(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoCombiTrans(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + + // TGeoRotation* vertRot = new TGeoRotation(name + "_vertpillar_rot_1", 90., 45., -90.); + TGeoRotation* vertRot = new TGeoRotation; + vertRot->RotateX(90.); + vertRot->RotateY(45.); + frameBoxVol->AddNode(frameVertPillarVol, 3, new TGeoCombiTrans(name + "_vertpillar_pos_3", 0., 0., (x-sqrt(2.)*t)/2., vertRot)); + + // --- Small horizontal pillar + // TGeoBBox* frameHorPillarShp = new TGeoBBox(name + "_horpillar_shape", x-2.*t, gkThinFrameThickness/2., gkThinFrameThickness/2.); + // TGeoVolume* frameHorPillarVol = new TGeoVolume(name + "_horpillar", frameHorPillarShp, framesMaterial); + // frameHorPillarVol->SetLineColor(kCyan); + // frameBoxVol->AddNode(frameHorPillarVol, 1, new TGeoTranslation(name + "_horpillar_pos_1", 0., -gkFrameStep/2.+gkThinFrameThickness/2., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkConstructSmallFrames) { + + // --- Small sloping pillars + TGeoPara* frameSlopePillarShp = new TGeoPara(name + "_slopepillar_shape", + (x-2.*t)/TMath::Cos(31.4/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., 31.4, 0., 90.); + TGeoVolume* frameSlopePillarVol = new TGeoVolume(name + "_slopepillar", frameSlopePillarShp, framesMaterial); + frameSlopePillarVol->SetLineColor(kCyan); + TGeoRotation* slopeRot = new TGeoRotation(name + "_slopepillar_rot_1", 0., 0., 31.4); + TGeoRotation* slopeRot2 = new TGeoRotation(name + "_slopepillar_rot_2", 0., 0., -31.4); + TGeoCombiTrans* slopeTrRot = new TGeoCombiTrans(name + "_slopepillar_posrot_1", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot); + TGeoCombiTrans* slopeTrRot2 = new TGeoCombiTrans(name + "_slopepillar_posrot_2", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot2); + + frameBoxVol->AddNode(frameSlopePillarVol, 1, slopeTrRot); + frameBoxVol->AddNodeOverlap(frameSlopePillarVol, 2, slopeTrRot2); + + + Double_t angl = 23.; + // --- Small sub pillar + TGeoPara* frameSubPillarShp = new TGeoPara(name + "_subpillar_shape", + (sqrt(2)*(x/2.-t)-t/2.)/TMath::Cos(angl/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., angl, 0., 90.); + TGeoVolume* frameSubPillarVol = new TGeoVolume(name + "_subpillar", frameSubPillarShp, framesMaterial); + frameSubPillarVol->SetLineColor(kMagenta); + + Double_t posZ = t * (1. - 3. / ( 2.*sqrt(2.) )); + + // one side of X direction + TGeoRotation* subRot1 = new TGeoRotation(name + "_subpillar_rot_1", 90., 45., -90.+angl); + TGeoCombiTrans* subTrRot1 = new TGeoCombiTrans(name + "_subpillar_posrot_1", -(-x/2.+t-t/(2.*sqrt(2.))), 1., posZ, subRot1); + + TGeoRotation* subRot2 = new TGeoRotation(name + "_subpillar_rot_2", 90., -90.-45., -90.+angl); + TGeoCombiTrans* subTrRot2 = new TGeoCombiTrans(name + "_subpillar_posrot_2", -(-x/2.+t-t/(2.*sqrt(2.))), -1., posZ, subRot2); + + // other side of X direction + TGeoRotation* subRot3 = new TGeoRotation(name + "_subpillar_rot_3", 90., 90.+45., -90.+angl); + TGeoCombiTrans* subTrRot3 = new TGeoCombiTrans(name + "_subpillar_posrot_3", -x/2.+t-t/(2.*sqrt(2.)), 1., posZ, subRot3); + + TGeoRotation* subRot4 = new TGeoRotation(name + "_subpillar_rot_4", 90., -45., -90.+angl); + TGeoCombiTrans* subTrRot4 = new TGeoCombiTrans(name + "_subpillar_posrot_4", -x/2.+t-t/(2.*sqrt(2.)), -1., posZ, subRot4); + + frameBoxVol->AddNode(frameSubPillarVol, 1, subTrRot1); + frameBoxVol->AddNode(frameSubPillarVol, 2, subTrRot2); + frameBoxVol->AddNode(frameSubPillarVol, 3, subTrRot3); + frameBoxVol->AddNode(frameSubPillarVol, 4, subTrRot4); + // frameBoxVol->GetShape()->ComputeBBox(); + } + + return frameBoxVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructSmallCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 6., 7.6, 6., 6.04, 0., 180.); +// TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + Double_t radius = 3.0; + Double_t thickness = 0.04; // 0.4 mm +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 3., 3.2, 3., 3.2, 0., 180.); + TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, radius, radius+thickness, radius, radius+thickness, 0., 180.); + TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + TGeoCombiTrans* M = new TGeoCombiTrans ("M"); + M->RotateX (45.); + M->SetDy (-5.575); + M->SetDz (6.935); + M->RegisterYourself(); + + TGeoShape* coneShp = new TGeoCompositeShape ("Cone_shp", "A-B:M"); + TGeoVolume* coneVol = new TGeoVolume ("Cone", coneShp, framesMaterial); + coneVol->SetLineColor(kGreen); +// coneVol->RegisterYourself(); + +// // --- Inner cone +// Double_t thickness = 0.02; +// Double_t thickness2 = 0.022; +// // TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); +// TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 3.+thickness, 4.6-thickness2, 2.99+thickness, 3.05-thickness2, 0., 180.); +// +// TGeoCombiTrans* M2 = new TGeoCombiTrans ("M2"); +// M2->RotateX (45.); +// M2->SetDy (-5.575+thickness*sqrt(2.)); +// M2->SetDz (6.935); +// M2->RegisterYourself(); +// +// TGeoShape* coneShp2 = new TGeoCompositeShape ("Cone2_shp", "A2-B:M2"); +// TGeoVolume* coneVol2 = new TGeoVolume ("Cone2", coneShp2, gStsMedium); +// coneVol2->SetLineColor(kGreen); +//// coneVol2->RegisterYourself(); +// +// coneVol->AddNode(coneVol2, 1); + + return coneVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructBigCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone + TGeoConeSeg* bA = new TGeoConeSeg ("bA", coneDz, 6., 7.6, 6., 6.04, 0., 180.); + TGeoBBox* bB = new TGeoBBox ("bB", 8., 6., 10.); + + TGeoCombiTrans* bM = new TGeoCombiTrans ("bM"); + bM->RotateX (45.); + bM->SetDy (-5.575); + bM->SetDz (6.935); + bM->RegisterYourself(); + + TGeoShape* coneBigShp = new TGeoCompositeShape ("ConeBig_shp", "bA-bB:bM"); + TGeoVolume* coneBigVol = new TGeoVolume ("ConeBig", coneBigShp, framesMaterial); + coneBigVol->SetLineColor(kGreen); +// coneBigVol->RegisterYourself(); + + // --- Inner cone + Double_t thickness = 0.02; + Double_t thickness2 = 0.022; + TGeoConeSeg* bA2 = new TGeoConeSeg ("bA2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); + + TGeoCombiTrans* bM2 = new TGeoCombiTrans ("bM2"); + bM2->RotateX (45.); + bM2->SetDy (-5.575+thickness*sqrt(2.)); + bM2->SetDz (6.935); + bM2->RegisterYourself(); + + TGeoShape* coneBigShp2 = new TGeoCompositeShape ("ConeBig2_shp", "bA2-bB:bM2"); + TGeoVolume* coneBigVol2 = new TGeoVolume ("ConeBig2", coneBigShp2, gStsMedium); + coneBigVol2->SetLineColor(kGreen); +// coneBigVol2->RegisterYourself(); + + coneBigVol->AddNode(coneBigVol2, 1); + + return coneBigVol; +} + +/** ======================================================================= **/ diff --git a/macro/sts/geometry/create_stsgeo_v19r.C b/macro/sts/geometry/create_stsgeo_v19r.C new file mode 100644 index 0000000000000000000000000000000000000000..6a2ca2b94d9dbe99f96114c837b4cc319e5cc88a --- /dev/null +++ b/macro/sts/geometry/create_stsgeo_v19r.C @@ -0,0 +1,2377 @@ +/****************************************************************************** + ** Creation of STS geometry in ROOT format (TGeo). + ** + ** @file create_stsgeo_v19r.C + ** @author Volker Friese <v.friese@gsi.de> + ** @since 15 June 2012 + ** @date 09.05.2014 + ** @author Tomas Balog <T.Balog@gsi.de> + ** + ** v19r: bugfix of v19q - align all halfladders + ** v19q: based on v19l - align ladders to virtual plane in station center, closing the gaps in z + ** v19p: based on v19k - parameters : delta Z prime = 0.70 cm - delta Z pitch = 0.20 cm + ** v19o: based on v19k - parameters : delta Z prime = 0.30 cm - delta Z pitch = 0.20 cm + ** v19n: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.20 cm (bug fix of v19m) + ** v19m: based on v19k - parameters : delta Z prime = 0.55 cm - delta Z pitch = 0.20 cm (bug) + ** v19l: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.15 cm + ** v19k: ladders on upstream side of units get upper half ladders installed first, + ** ladders on downstream side of units get lower half ladders installed first, + ** this saves 1.5 mm space in z per station, 12 mm in total (LadderType went from 3 to 4 digits) + ** parameters : delta Z prime = 1.00 cm - delta Z pitch = 0.15 cm + ** v19j: use overlap and distance parameters from CAD model + ** v19h: put STS stations from v19d at z-positions = 260; 365; 470; 575; 680; 785; 890; 995 mm + ** v19g: place a box with services around v19e + ** v19f: place a box with services around v19d + ** v19e: increase spacing between stations by +10 mm from 100 mm + ** v19d: increase spacing between stations by + 5 mm from 100 mm + ** v19c: drop station 8 and increase spacing between remaining 7 stations from 10 cm to 12 c + ** v19b: introduce FEB orientation in ladder numbering (LadderType went from 2 to 3 digits) + ** v19a: import passive materials from gdml file + ** extend CF ladder structures and cables towards FEE plane + ** change CF ladder frame shape + ** v18d: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu (based on v18b) + ** v18c: fixed cut-out windows in cooling plates, improve the box shape/materials + ** v18b: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu + ** v18a: adds 9 cooling/holding plates and a box around the setup + ** v16g: v16g is the new standard geometry from November 2017 + ** v16g: switch from stations to units - left / right ("Unit01L", "Unit01R") + ** v16f: switch from stations to units + ** - split in upstream / downstream and left / right parts + ** - named Unit0xUR, Unit0xUL, Unit0xDR, Unit0xDL + ** v16e: switch from stations to units - upstream / downstream ("Unit01U", "Unit01D") + ** v16d: skip keeping volumes of sts and stations + ** v16c: like v16b, but senors of ladders beampipe next to beampipe + ** shifted closer to the pipe, like in the CAD model + ** v16b: like v16a, but yellow sensors removed + ** v16a: derived from v15c (no cones), but with sensor types renamed: + ** 2 -> 1, 3 -> 2, 4 -> 3, 5 -> 4, 1 -> 5 + ** + ** v15c: as v15b without cones + ** v15b: introduce modified carbon ladders from v13z + ** v15a: with flipped ladder orientation for stations 0,2,4,6 to match CAD design + ** + ** TODO: + ** + ** DONE: + ** v15b - use carbon macaroni as ladder support + ** v15b - introduce a small gap between lowest sensor and carbon ladder + ** v15b - build small cones for the first 2 stations + ** v15b - within a station the ladders of adjacent units should not touch eachother - set gkLadderGapZ to 10 mm + ** v15b - for all ladders set an even number of ladder elements + ** v15b - z offset of cones to ladders should not be 0.3 by default, but 0.26 + ** v15b - within a station the ladders should be aligned in z, defined either by the unit or the ladder with most sensors + ** v15b - get rid of cone overlap in stations 7 and 8 - done by adapting rHole size + ** + ** The geometry hierarachy is: + ** + ** 1. Sensors (see function CreateSensors) + ** The sensors are the active volumes and the lowest geometry level. + ** They are built as TGeoVolumes, shape box, material silicon. + ** x size is determined by strip pitch 58 mu and 1024 strips + ** plus guard ring of 1.3 mm at each border -> 6.1992 cm. + ** Sensor type 1 is half of that (3.0792 cm). + ** y size is determined by strip length (2.2 / 4.2 / 6.3 cm) plus + ** guard ring of 1.3 mm at top and bottom -> 2.46 / 4.46 / 6.46 cm. + ** z size is a parameter, to be set by gkSensorThickness. + ** + ** 2. Sectors (see function CreateSectors) + ** Sectors consist of several chained sensors. These are arranged + ** vertically on top of each other with a gap to be set by + ** gkChainGapY. Sectors are constructed as TGeoVolumeAssembly. + ** The sectors are auxiliary volumes used for proper placement + ** of the sensor(s) in the module. They do not show up in the + ** final geometry. + ** + ** 3. Modules (see function ConstructModule) + ** A module is a readout unit, consisting of one sensor or + ** a chain of sensors (see sector) and a cable. + ** The cable extends from the top of the sector vertically to the + ** top of the halfladder the module is placed in. The cable and module + ** volume thus depend on the vertical position of the sector in + ** the halfladder. The cables consist of silicon with a thickness to be + ** set by gkCableThickness. + ** Modules are constructed as TGeoVolume, shape box, medium gStsMedium. + ** The module construction can be switched off (gkConstructCables) + ** to reproduce older geometries. + ** + ** 4. Halfladders (see function ConstructHalfLadder) + ** A halfladder is a vertical assembly of several modules. The modules + ** are placed vertically such that their sectors overlap by + ** gkSectorOverlapY. They are displaced in z direction to allow for the + ** overlap in y by gkSectorGapZ. + ** The horizontal placement of modules in the halfladder can be choosen + ** to left aligned or right aligned, which only matters if sensors of + ** different x size are involved. + ** Halfladders are constructed as TGeoVolumeAssembly. + ** + ** 5. Ladders (see function CreateLadders and ConstructLadder) + ** A ladder is a vertical assembly of two halfladders, and is such the + ** vertical building block of a station. The second (bottom) half ladder + ** is rotated upside down. The vertical arrangement is such that the + ** inner sectors of the two halfladders have the overlap gkSectorOverlapY + ** (function CreateLadder) or that there is a vertical gap for the beam + ** hole (function CreateLadderWithGap). + ** Ladders are constructed as TGeoVolumeAssembly. + ** + ** 6. Stations (see function ConstructStation) + ** A station represents one layer of the STS geometry: one measurement + ** at (approximately) a given z position. It consist of several ladders + ** arranged horizontally to cover the acceptance. + ** The ladders are arranged such that there is a horizontal overlap + ** between neighbouring ladders (gkLadderOverLapX) and a vertical gap + ** to allow for this overlap (gkLadderGapZ). Each second ladder is + ** rotated around its y axis to face away from or into the beam. + ** Stations are constructed as TGeoVolumes, shape box minus tube (for + ** the beam hole), material gStsMedium. + ** + ** 7. STS + ** The STS is a volume hosting the entire detectors system. It consists + ** of several stations located at different z positions. + ** The STS is constructed as TGeoVolume, shape box minus cone (for the + ** beam pipe), material gStsMedium. The size of the box is computed to + ** enclose all stations. + *****************************************************************************/ + + +// Remark: With the proper steering variables, this should exactly reproduce +// the geometry version v11b of A. Kotynia's described in the ASCII format. +// The only exception is a minimal difference in the z position of the +// sectors/sensors. This is because of ladder types 2 and 4 containing the half +// sensors around the beam hole (stations 1,2 and 3). In v11b, the two ladders +// covering the beam hole cannot be transformed into each other by rotations, +// but only by a reflection. This means they are constructionally different. +// To avoid introducing another two ladder types, the difference in z position +// was accepted. + + +// Differences to v12: +// gkChainGap reduced from 1 mm to 0 +// gkCableThickness increased from 100 mum to 200 mum (2 cables per module) +// gkSectorOverlapY reduced from 3 mm to 2.4 mm +// New sensor types 05 and 06 +// New sector types 07 and 08 +// Re-definiton of ladders (17 types instead of 8) +// Re-definiton of station from new ladders + + +#include <iomanip> +#include <iostream> +#include "TGeoManager.h" + +#include "TGeoTube.h" +#include "TGeoPara.h" +#include "TGeoCone.h" +#include "TGeoTrd2.h" +#include "TGeoCompositeShape.h" +#include "TGeoXtru.h" +#include "TGeoPhysicalNode.h" + +// forward declarations +Int_t CreateSensors(); +Int_t CreateSectors(); +Int_t CreateLadders(); +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength); +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY); +TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ, + Double_t pitchZ, + Int_t nSectors); +TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation); +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile); +void PostProcessGdml(TGeoVolume* gdmlTop); +void CheckVolume(TGeoVolume* volume); +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren = kTRUE); +Double_t BeamPipeRadius(Double_t z); +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x); +TGeoVolume* ConstructSmallCone(Double_t coneDz); +TGeoVolume* ConstructBigCone(Double_t coneDz); + +// ------------- Version highlight ----------------------------------- + +const std::string gVersionHighlight = R"( +Summary: + This version adds passive materials imported from GDML model to the STS geometry: + * Taken from and largely correspond to mechanical CAD drawings of the detector + * Thermal insulation box: + - made out of carbon sandwitch panel (2mm carbon fiber sheet + layer of carbon foam + 2mm carbon fiber sheet) + - front window of complex shape with interface to MVD / target chamber + - back window with large aperture (2000 x 1200 mm) square cut into carbon foam + * Structural units: + - made of 2 complex shape aluminum C-Frames, 15mm thick + - placed at 25, 35, ... ,105 cm absolute Z + - contain front-end and power distribution boxes with equivalent X_0 values + + Scripted geometry tweaks: + * Ladders and cables are extended towards the read-out planes having same lengths in respective rows + * Adjusted form and shape of carbon ladder structures from L-type to X-type + * Reduced verbosity of this file + + Sensor arrangement is the same as in version v16g + + !! Important for this version is the discrepancy from the mechanical CAD w.r.t. front wall. + The square window was replaced by a round one to avoid overlaps with present beam pipe designs, e.g. pipe_v16b_1e +)"; + +// ------------- Steering variables ----------------------------------- + +// ---> Horizontal width of sensors [cm] +const Double_t gkSensorSizeX = 6.2; // was 6.2092; // 6.2 - Oleg CAD 15/05/2020 + +// ---> Thickness of sensors [cm] +const Double_t gkSensorThickness = 0.03; + +// ---> Vertical gap between chained sensors [cm] +const Double_t gkChainGapY = 0.00; + +// ---> Thickness of cables [cm] +const Double_t gkCableThickness = 0.02; + +// ---> Horizontal overlap of neighbouring ladders [cm] +const Double_t gkLadderOverlapX = 0.25; // delta X - Oleg CAD 14/05/2020 + +// ---> Vertical overlap of neighbouring sectors in a ladder [cm] +const Double_t gkSectorOverlapY = 0.46; // delta Y - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring sectors in a ladder [cm] +const Double_t gkSectorGapZ = 0.12; // gap + thickness = pitch // delta Z pitch = 0.15 - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring ladders [cm] +const Double_t gkLadderGapZ = 0.50 - 0.15; // for asym // 0.5 for sym // delta Z prime + +// ---> Gap in z between lowest sector to carbon support structure [cm] +const Double_t gkSectorGapZFrame = 0.280 - 0.025; // Oleg CAD 05/05/2020 // there is a 2.8 mm gap between the bottom side of the sensor and the top ledge of the carbon ladder + +// ---> Switch to construct / not to construct readout cables +const Bool_t gkConstructCables = kTRUE; + +// ---> Switch to construct / not to construct frames +const Bool_t gkConstructCones = kFALSE; // kTRUE; // switch this false by default for v15c and v16x +const Bool_t gkConstructFrames = kTRUE; // kFALSE; // switch this true by default for v15c and v16x +const Bool_t gkConstructSmallFrames = kTRUE; // kFALSE; +const Bool_t gkCylindricalFrames = kTRUE; // kFALSE; + +// ---> Size of the frame +const Double_t gkFrameThickness = 0.2; +const Double_t gkThinFrameThickness = 0.05; +const Double_t gkFrameStep = 4.0; // size of frame cell along y direction + +const Double_t gkCylinderDiaInner = 0.07; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) +const Double_t gkCylinderDiaOuter = 0.15; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) + +// ---> Switch to import / not to import the Passive materials from GDML file +//const Bool_t gkImportPassive = kTRUE; +const Bool_t gkImportPassive = kFALSE; + +// ---------------------------------------------------------------------------- + + +// -------------- Parameters of beam pipe in the STS region -------------- +// ---> Needed to compute stations and STS such as to avoid overlaps +const Double_t gkPipeZ1 = 22.0; +const Double_t gkPipeR1 = 1.8; +const Double_t gkPipeZ2 = 50.0; +const Double_t gkPipeR2 = 1.8; +const Double_t gkPipeZ3 = 125.0; +const Double_t gkPipeR3 = 5.5; + +//DE const Double_t gkPipeZ1 = 27.0; +//DE const Double_t gkPipeR1 = 1.05; +//DE const Double_t gkPipeZ2 = 160.0; +//DE const Double_t gkPipeR2 = 3.25; +// ---------------------------------------------------------------------------- + +//TString unitName[16] = // names of units for v16e +// { "Unit00D", +// "Unit01U", "Unit01D", +// "Unit02U", "Unit02D", +// "Unit03U", "Unit03D", +// "Unit04U", "Unit04D", +// "Unit05U", "Unit05D", +// "Unit06U", "Unit06D", +// "Unit07U", "Unit07D", +// "Unit08U" }; + +//TString unitName[32] = // names of units for v16f +// { "Unit00DR", "Unit00DL", +// "Unit01UR", "Unit01UL", "Unit01DR", "Unit01DL", +// "Unit02UR", "Unit02UL", "Unit02DR", "Unit02DL", +// "Unit03UR", "Unit03UL", "Unit03DR", "Unit03DL", +// "Unit04UR", "Unit04UL", "Unit04DR", "Unit04DL", +// "Unit05UR", "Unit05UL", "Unit05DR", "Unit05DL", +// "Unit06UR", "Unit06UL", "Unit06DR", "Unit06DL", +// "Unit07UR", "Unit07UL", "Unit07DR", "Unit07DL", +// "Unit08UR", "Unit08UL" }; + +TString unitName[32] = // names of units for v16g - while merging D and U parts + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", "Unit01R", "Unit01L", + "Unit02R", "Unit02L", "Unit02R", "Unit02L", + "Unit03R", "Unit03L", "Unit03R", "Unit03L", + "Unit04R", "Unit04L", "Unit04R", "Unit04L", + "Unit05R", "Unit05L", "Unit05R", "Unit05L", + "Unit06R", "Unit06L", "Unit06R", "Unit06L", + "Unit07R", "Unit07L", "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +TString unitName18[18] = // names of units for v16g + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", + "Unit02R", "Unit02L", + "Unit03R", "Unit03L", + "Unit04R", "Unit04L", + "Unit05R", "Unit05L", + "Unit06R", "Unit06L", + "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +// ------------- Other global variables ----------------------------------- +// ---> STS medium (for every volume except silicon) +TGeoMedium* gStsMedium = NULL; // will be set later +// ---> TGeoManager (too lazy to write out 'Manager' all the time +TGeoManager* gGeoMan = NULL; // will be set later +// ---------------------------------------------------------------------------- + + + + +// ============================================================================ +// ====== Main function ===== +// ============================================================================ + +void create_stsgeo_v19r(const char* geoTag="v19r") +{ + + // ------- Geometry file name (output) ---------------------------------- + TString geoFileName = "sts_"; + geoFileName = geoFileName + geoTag + ".geo.root"; + // -------------------------------------------------------------------------- + + + // ------- Open info file ----------------------------------------------- + TString infoFileName = geoFileName; + infoFileName.ReplaceAll("root", "info"); + fstream infoFile; + infoFile.open(infoFileName.Data(), fstream::out); + infoFile << "STS geometry created with create_stsgeo_v19r.C" << endl; + infoFile << gVersionHighlight << endl; + infoFile << "Global variables: " << endl; + infoFile << "Sensor thickness = " << gkSensorThickness << " cm" << endl; + infoFile << "Vertical gap in sensor chain = " + << gkChainGapY << " cm" << endl; + infoFile << "Vertical overlap of sensors = " + << gkSectorOverlapY << " cm" << endl; + infoFile << "Gap in z between neighbour sensors = " + << gkSectorGapZ << " cm" << endl; + infoFile << "Horizontal overlap of sensors = " + << gkLadderOverlapX << " cm" << endl; + infoFile << "Gap in z between neighbour ladders = " + << gkLadderGapZ << " cm" << endl; + if ( gkConstructCables ) + infoFile << "Cable thickness = " << gkCableThickness << " cm" << endl; + else + infoFile << "No cables" << endl; + infoFile << endl; + infoFile << "Beam pipe: R1 = " << gkPipeR1 << " cm at z = " + << gkPipeZ1 << " cm" << endl; + infoFile << "Beam pipe: R2 = " << gkPipeR2 << " cm at z = " + << gkPipeZ2 << " cm" << endl; + infoFile << "Beam pipe: R3 = " << gkPipeR3 << " cm at z = " + << gkPipeZ3 << " cm" << endl; + // -------------------------------------------------------------------------- + + + // ------- Load media from media file ----------------------------------- + FairGeoLoader* geoLoad = new FairGeoLoader("TGeo","FairGeoLoader"); + FairGeoInterface* geoFace = geoLoad->getGeoInterface(); + TString geoPath = gSystem->Getenv("VMCWORKDIR"); + TString medFile = geoPath + "/geometry/media.geo"; + geoFace->setMediaFile(medFile); + geoFace->readMedia(); + gGeoMan = gGeoManager; + // -------------------------------------------------------------------------- + + + // ----------------- Get and create the required media ----------------- + FairGeoMedia* geoMedia = geoFace->getMedia(); + FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder(); + + // ---> air + FairGeoMedium* mAir = geoMedia->getMedium("air"); + if ( ! mAir ) Fatal("Main", "FairMedium air not found"); + geoBuild->createMedium(mAir); + TGeoMedium* air = gGeoMan->GetMedium("air"); + if ( ! air ) Fatal("Main", "Medium air not found"); + + // ---> silicon + FairGeoMedium* mSilicon = geoMedia->getMedium("silicon"); + if ( ! mSilicon ) Fatal("Main", "FairMedium silicon not found"); + geoBuild->createMedium(mSilicon); + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + if ( ! silicon ) Fatal("Main", "Medium silicon not found"); + + // ---> carbon + FairGeoMedium* mCarbon = geoMedia->getMedium("carbon"); + if ( ! mCarbon ) Fatal("Main", "FairMedium carbon not found"); + geoBuild->createMedium(mCarbon); + TGeoMedium* carbon = gGeoMan->GetMedium("carbon"); + if ( ! carbon ) Fatal("Main", "Medium carbon not found"); + + // ---> STSBoxCarbonFoam + FairGeoMedium* mSTSBoxCarbonFoam = geoMedia->getMedium("STSBoxCarbonFoam"); + if ( ! mSTSBoxCarbonFoam ) Fatal("Main", "FairMedium STSBoxCarbonFoam not found"); + geoBuild->createMedium(mSTSBoxCarbonFoam); + TGeoMedium* STSBoxCarbonFoam = gGeoMan->GetMedium("STSBoxCarbonFoam"); + if ( ! STSBoxCarbonFoam ) Fatal("Main", "Medium STSBoxCarbonFoam not found"); + + // ---> STSBoxCarbonFibre + FairGeoMedium* mSTSBoxCarbonFibre = geoMedia->getMedium("STSBoxCarbonFibre"); + if ( ! mSTSBoxCarbonFibre ) Fatal("Main", "FairMedium STSBoxCarbonFibre not found"); + geoBuild->createMedium(mSTSBoxCarbonFibre); + TGeoMedium* STSBoxCarbonFibre = gGeoMan->GetMedium("STSBoxCarbonFibre"); + if ( ! STSBoxCarbonFibre ) Fatal("Main", "Medium STSBoxCarbonFibre not found"); + + // ---> STScable + FairGeoMedium* mSTScable = geoMedia->getMedium("STScable"); + if ( ! mSTScable ) Fatal("Main", "FairMedium STScable not found"); + geoBuild->createMedium(mSTScable); + TGeoMedium* STScable = gGeoMan->GetMedium("STScable"); + if ( ! STScable ) Fatal("Main", "Medium STScable not found"); + + // ---> Aluminium + FairGeoMedium* mAluminium = geoMedia->getMedium("aluminium"); + if ( ! mAluminium ) Fatal("Main", "FairMedium aluminium not found"); + geoBuild->createMedium(mAluminium); + TGeoMedium* aluminium = gGeoMan->GetMedium("aluminium"); + if ( ! aluminium ) Fatal("Main", "Medium aluminium not found"); + + // --- + gStsMedium = air; + // -------------------------------------------------------------------------- + + + // -------------- Create geometry and top volume ------------------------- + gGeoMan = (TGeoManager*)gROOT->FindObject("FAIRGeom"); +// gGeoMan->SetName("STSgeom"); + TGeoVolume* top = new TGeoVolumeAssembly("top"); +// TGeoBBox* topbox= new TGeoBBox("", 120., 120., 120.); +// TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air")); + gGeoMan->SetTopVolume(top); + // -------------------------------------------------------------------------- + + + // -------------- Create media ------------------------------------------ + /* + cout << endl; + cout << "===> Creating media...."; + cout << CreateMedia(); + cout << " media created" << endl; + TList* media = gGeoMan->GetListOfMedia(); + for (Int_t iMedium = 0; iMedium < media->GetSize(); iMedium++ ) { + cout << "Medium " << iMedium << ": " + << ((TGeoMedium*) media->At(iMedium))->GetName() << endl; + } + gStsMedium = gGeoMan->GetMedium("air"); + if ( ! gStsMedium ) Fatal("Main", "medium sts_air not found"); + */ + // -------------------------------------------------------------------------- + + + // --------------- Create sensors --------------------------------------- + cout << endl << endl; + cout << "===> Creating sensors...." << endl << endl; + infoFile << endl << "Sensors: " << endl; + Int_t nSensors = CreateSensors(); + for (Int_t iSensor = 1; iSensor <= nSensors; iSensor++) { + TString name = Form("Sensor%02d",iSensor); + TGeoVolume* sensor = gGeoMan->GetVolume(name); + + // add color to sensors + if (iSensor == 1) + sensor->SetLineColor(kRed); + if (iSensor == 2) + sensor->SetLineColor(kGreen); + if (iSensor == 3) + sensor->SetLineColor(kBlue); + if (iSensor == 4) + sensor->SetLineColor(kAzure); + if (iSensor == 5) + sensor->SetLineColor(kYellow); + if (iSensor == 6) + sensor->SetLineColor(kYellow); + if (iSensor == 7) + sensor->SetLineColor(kYellow); + + CheckVolume(sensor); + CheckVolume(sensor, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create sectors -------------------------------------- + cout << endl << endl; + cout << "===> Creating sectors...." << endl; + // infoFile << endl << "Sectors: " << endl; + Int_t nSectors = CreateSectors(); + for (Int_t iSector = 1; iSector <= nSectors; iSector++) { + // cout << endl; + TString name = Form("Sector%02d", iSector); + TGeoVolume* sector = gGeoMan->GetVolume(name); + CheckVolume(sector); + // CheckVolume(sector, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create ladders -------------------------------------- + cout << endl << endl; + cout << "===> Creating ladders...." << endl; + infoFile << endl << "Ladders:" << endl; + + TString name = ""; + TGeoVolume* ladder; + + + Int_t nLadders = CreateLadders(); + + for (Int_t iLadder = 1; iLadder <= nLadders; iLadder++) { + cout << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType0%02d", iLadder); // v19b + name = Form("LadderType00%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF1: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType1%02d", iLadder); // v19b + name = Form("LadderType01%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF2: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType10%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF3: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType11%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF4: ladder name: " << name << endl << endl; + } + // -------------------------------------------------------------------------- + + + // ---------------- Create cones ---------------------------------------- + Double_t coneDz = 1.64; + TGeoVolume* coneSmallVolum = ConstructSmallCone(coneDz); + if (!coneSmallVolum) Fatal("ConstructSmallCone", "Volume Cone not found"); + TGeoVolume* coneBigVolum = ConstructBigCone(coneDz); + if (!coneBigVolum) Fatal("ConstructBigCone", "Volume Cone not found"); + // -------------------------------------------------------------------------- + + + // ---------------- Create stations ------------------------------------- + cout << endl << endl; + cout << "===> Creating stations...." << endl; + infoFile << endl << "Stations: " << endl; + Int_t angle = 0; + nLadders = 0; + Int_t ladderTypes[16]; // there are max 16 ladders in one layer + TGeoTranslation* statTrans = NULL; + + TGeoVolume *myunit[32]; // units + +// Int_t statPos[8] = { 30, 40, 50, 60, 70, 80, 90, 100 }; // z positions of stations +// Int_t statPos[16] = { 28, 32, 38, 42, 48, 52, 58, 62, +// 68, 72, 78, 82, 88, 92, 98,102 }; // z positions of units +// Int_t statPos[16] = { 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units +// Int_t statPos18[18] = { 30, 30, // expanded for placement of Unit00 +// 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units + // v19h + Double_t statPos[16] = { 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of units + Double_t statPos18[18] = { 26.0, 26.0, // expanded for placement of Unit00 + 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of unit + +// // v19d +// Double_t statPos[16] = { 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units +// Double_t statPos18[18] = { 30.0, 30.0, // expanded for placement of Unit00 +// 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units + +////Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.9 , 3.7 , 3.7 , 4.2 , 4.2 }; // size of cutouts in stations +// Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.43, 3.04, 3.35, 3.96, 4.2 }; // size of cutouts in stations, derived from gapXYZ[x][1]/2 + + Int_t cone_size[8] = { 0, 0, 0, 1, 1, 1, 1, 1 }; // size of cones: 0 = small, 1 = large + + Double_t cone_offset[2] = { 0.305, 0.285 }; + +// Int_t allLadderTypes[8][16]= +// { { -1, -1, -1, -1, 10, 109, 9, 101, 1, 109, 9, 110, -1, -1, -1, -1 }, // station 1 +// { -1, -1, 111, 10, 110, 9, 109, 2, 102, 9, 109, 10, 110, 11, -1, -1 }, // station 2 +// { -1, -1, 14, 113, 12, 112, 12, 103, 3, 112, 12, 112, 13, 114, -1, -1 }, // station 3 +// { -1, 15, 114, 13, 112, 12, 112, 4, 104, 12, 112, 12, 113, 14, 115, -1 }, // station 4 +// { -1, 119, 18, 117, 17, 116, 16, 105, 5, 116, 16, 117, 17, 118, 19, -1 }, // station 5 +// { -1, 19, 118, 17, 117, 16, 116, 6, 106, 16, 116, 17, 117, 18, 119, -1 }, // station 6 +// { 21, 119, 18, 120, 20, 120, 20, 107, 7, 120, 20, 120, 20, 118, 19, 121 }, // station 7 +// { 119, 17, 123, 22, 122, 22, 122, 8, 108, 22, 122, 22, 122, 23, 117, 19 } }; // station 8 + +//============================================================================================== + +// explanation: type xyzz +// where x = carbon ladder orientation +// where y = FEB box orientation +// where zz = sensor arrangement on ladder +// with FEB orientation - v19b + Int_t allUnitTypes[16][16]= + { { -1, -1, -1, -1, 10, 0, 9, 0, 101, 0, 109, 0, -1, -1, -1, -1 }, // unit00D Station01 00 + { -1, -1, -1, -1, 0, 1109, 0, 1101, 0, 1009, 0, 1010, -1, -1, -1, -1 }, // unit01U Station01 01 + + { -1, -1, 0, 10, 0, 9, 0, 2, 0, 109, 0, 110, 0, 111, -1, -1 }, // unit01D Station02 02 + { -1, -1, 1111, 0, 1110, 0, 1109, 0, 1002, 0, 1009, 0, 1010, 0, -1, -1 }, // unit02U Station02 03 + + { -1, -1, 14, 0, 12, 0, 12, 0, 103, 0, 112, 0, 113, 0, -1, -1 }, // unit02D Station03 04 + { -1, -1, 0, 1113, 0, 1112, 0, 1103, 0, 1012, 0, 1012, 0, 1014, -1, -1 }, // unit03U Station03 05 + + { -1, 15, 0, 13, 0, 12, 0, 4, 0, 112, 0, 112, 0, 114, 0, -1 }, // unit03D Station04 06 + { -1, 0, 1114, 0, 1112, 0, 1112, 0, 1004, 0, 1012, 0, 1013, 0, 1015, -1 }, // unit04U Station04 07 + + { -1, 0, 18, 0, 17, 0, 16, 0, 105, 0, 116, 0, 117, 0, 119, -1 }, // unit04D Station05 08 + { -1, 1119, 0, 1117, 0, 1116, 0, 1105, 0, 1016, 0, 1017, 0, 1018, 0, -1 }, // unit05U Station05 09 + + { -1, 19, 0, 17, 0, 16, 0, 6, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05D Station06 10 + { -1, 0, 1118, 0, 1117, 0, 1116, 0, 1006, 0, 1016, 0, 1017, 0, 1019, -1 }, // unit06U Station06 11 + + { 21, 0, 25, 0, 20, 0, 20, 0, 107, 0, 120, 0, 120, 0, 127, 0 }, // unit06D Station07 12 + { 0, 1127, 0, 1120, 0, 1120, 0, 1107, 0, 1020, 0, 1020, 0, 1025, 0, 1021 }, // unit07U Station07 13 + + { 0, 24, 0, 22, 0, 22, 0, 8, 0, 122, 0, 122, 0, 123, 0, 126 }, // unit07D Station08 14 + { 1126, 0, 1123, 0, 1122, 0, 1122, 0, 1008, 0, 1022, 0, 1022, 0, 1024, 0 } }; // unit08U Station08 15 + +//============================================================================================== + +// without FEB orientation - v19a +// v19a Int_t allUnitTypes[16][16]= +// v19a { { -1, -1, -1, -1, 10, 0, 9, 0, 1, 0, 9, 0, -1, -1, -1, -1 }, // unit00D Station01 00 +// v19a { -1, -1, -1, -1, 0, 109, 0, 101, 0, 109, 0, 110, -1, -1, -1, -1 }, // unit01U Station01 01 +// v19a { -1, -1, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, -1, -1 }, // unit01D Station02 02 +// v19a { -1, -1, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, -1, -1 }, // unit02U Station02 03 +// v19a { -1, -1, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, -1, -1 }, // unit02D Station03 04 +// v19a { -1, -1, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, -1, -1 }, // unit03U Station03 05 +// v19a { -1, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, -1 }, // unit03D Station04 06 +// v19a { -1, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, -1 }, // unit04U Station04 07 +// v19a { -1, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, -1 }, // unit04D Station05 08 +// v19a { -1, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05U Station05 09 +// v19a { -1, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, -1 }, // unit05D Station06 10 +// v19a { -1, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, -1 }, // unit06U Station06 11 +// v19a { 21, 0, 25, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 27, 0 }, // unit06D Station07 12 +// v19a { 0, 127, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 125, 0, 121 }, // unit07U Station07 13 +// v19a { 0, 24, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 26 }, // unit07D Station08 14 +// v19a { 126, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 124, 0 } }; // unit08U Station08 15 + + +// unitTypes[0] = { 0, 0, 0, 0, 10, 0, 9, 0, 1, 0, 9, 0, 0, 0, 0, 0 }; // unit 0D +// unitTypes[1] = { 0, 0, 0, 0, 0, 109, 0, 101, 0, 109, 0, 110, 0, 0, 0, 0 }; // unit 1U +// unitTypes[2] = { 0, 0, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, 0, 0 }; // unit 1D +// unitTypes[3] = { 0, 0, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, 0, 0 }; // unit 2U +// unitTypes[4] = { 0, 0, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, 0, 0 }; // unit 2D +// unitTypes[5] = { 0, 0, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, 0, 0 }; // unit 3U +// unitTypes[6] = { 0, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, 0 }; // unit 3D +// unitTypes[7] = { 0, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, 0 }; // unit 4U +// unitTypes[8] = { 0, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, 0 }; // unit 4D +// unitTypes[9] = { 0, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, 0 }; // unit 5U +// unitTypes[10] = { 0, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, 0 }; // unit 5D +// unitTypes[11] = { 0, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, 0 }; // unit 6U +// unitTypes[12] = { 21, 0, 18, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 19, 0 }; // unit 6D +// unitTypes[13] = { 0, 119, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 118, 0, 121 }; // unit 7U +// unitTypes[14] = { 0, 17, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 19 }; // unit 7D +// unitTypes[15] = { 119, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 117, 0 }; // unit 8U + + +// // generate unit +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) +// for (Int_t iLadder = 0; iLadder < 16; iLadder++) +// { +// allUnitTypes[iUnit][iLadder] = 0; +// if ((iUnit % 2 == 0) && (allLadderTypes[iUnit/2][iLadder] < 100)) // if carbon structure is oriented upstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// if ((iUnit % 2 == 1) && (allLadderTypes[iUnit/2][iLadder] >= 100)) // if carbon structure is oriented downstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// } + + + // dump unit + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << "DE unitTypes[" << iUnit << "] = { "; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + { + cout << allUnitTypes[iUnit][iLadder]; + if (iLadder < 15) + cout << ", "; + else + cout << " };"; + } + cout << endl; + } + + + // --- Units 01 - 16 + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << endl; + + nLadders = 0; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + if (allUnitTypes[iUnit][iLadder] >= 0) + { + ladderTypes[nLadders] = allUnitTypes[iUnit][iLadder]; + cout << "DE ladderTypes[" << nLadders << "] = " << allUnitTypes[iUnit][iLadder] << ";" << endl; + nLadders++; + } + myunit[iUnit*2+0] = ConstructUnit(0, iUnit*2+0, nLadders, ladderTypes, iUnit/2+1); + myunit[iUnit*2+1] = ConstructUnit(1, iUnit*2+1, nLadders, ladderTypes, iUnit/2+1); + +// if (gkConstructCones) { +// if (iUnit%2 == 0) +// angle = 90; +// else +// angle = -90; +// +// // upstream +// TGeoRotation* coneRot11 = new TGeoRotation; +// coneRot11->RotateZ(angle); +// coneRot11->RotateY(180); +// TGeoCombiTrans* conePosRot11 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-cone_offset[cone_size[iUnit]]-gkLadderGapZ/2., coneRot11); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 1, conePosRot11); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 1, conePosRot11); +// +// // downstream +// TGeoRotation* coneRot12 = new TGeoRotation; +// coneRot12->RotateZ(angle); +// TGeoCombiTrans* conePosRot12 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+cone_offset[cone_size[iUnit]]+gkLadderGapZ/2., coneRot12); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 2, conePosRot12); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 2, conePosRot12); +// +// myunit[iUnit]->GetShape()->ComputeBBox(); +// } + +// CheckVolume(myunit[iUnit]); +// CheckVolume(myunit[iUnit], infoFile); + if ((iUnit%2 == 0)||(iUnit == 15)) + { + CheckVolume(myunit[iUnit*2+0]); + CheckVolume(myunit[iUnit*2+0], infoFile); + CheckVolume(myunit[iUnit*2+1]); + CheckVolume(myunit[iUnit*2+1], infoFile); + } + infoFile << "Position z = " << statPos[iUnit] << endl; + } + // -------------------------------------------------------------------------- + + + // --------------- Create STS volume ------------------------------------ + cout << endl << endl; + cout << "===> Creating STS...." << endl; + +// // --- Determine size of STS box +// Double_t stsX = 0.; +// Double_t stsY = 0.; +// Double_t stsZ = 0.; +// Double_t stsBorder = 2*5.; // 5 cm space for carbon ladders on each side +// for (Int_t iStation = 1; iStation<=8; iStation++) { +// TString statName = Form("Station%02d", iStation); +// TGeoVolume* station = gGeoMan->GetVolume(statName); +// TGeoBBox* shape = (TGeoBBox*) station->GetShape(); +// stsX = TMath::Max(stsX, 2.* shape->GetDX() ); +// stsY = TMath::Max(stsY, 2.* shape->GetDY() ); +// cout << "Station " << iStation << ": Y " << stsY << endl; +// } +// // --- Some border around the stations +// stsX += stsBorder; +// stsY += stsBorder; +// stsZ = ( statPos[7] - statPos[0] ) + stsBorder; +// +// // --- Create box around the stations +// new TGeoBBox("stsBox", stsX/2., stsY/2., stsZ/2.); +// cout << "size of STS box: x " << stsX << " - y " << stsY << " - z " << stsZ << endl; +// +// // --- Create cone hosting the beam pipe +// // --- One straight section with constant radius followed by a cone +// Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +// Double_t z2 = gkPipeZ2; +// Double_t z3 = statPos[7] + 0.5 * stsBorder; // end of STS box +// Double_t r1 = BeamPipeRadius(z1); +// Double_t r2 = BeamPipeRadius(z2); +// Double_t r3 = BeamPipeRadius(z3); +// r1 += 0.01; // safety margin +// r2 += 0.01; // safety margin +// r3 += 0.01; // safety margin +// +// cout << endl; +// cout << z1 << " " << r1 << endl; +// cout << z2 << " " << r2 << endl; +// cout << z3 << " " << r3 << endl; +// +// cout << endl; +// cout << "station1 : " << BeamPipeRadius(statPos[0]) << endl; +// cout << "station2 : " << BeamPipeRadius(statPos[1]) << endl; +// cout << "station3 : " << BeamPipeRadius(statPos[2]) << endl; +// cout << "station4 : " << BeamPipeRadius(statPos[3]) << endl; +// cout << "station5 : " << BeamPipeRadius(statPos[4]) << endl; +// cout << "station6 : " << BeamPipeRadius(statPos[5]) << endl; +// cout << "station7 : " << BeamPipeRadius(statPos[6]) << endl; +// cout << "station8 : " << BeamPipeRadius(statPos[7]) << endl; +// +// // TGeoPcon* cutout = new TGeoPcon("stsCone", 0., 360., 3); // 2.*TMath::Pi(), 3); +// // cutout->DefineSection(0, z1, 0., r1); +// // cutout->DefineSection(1, z2, 0., r2); +// // cutout->DefineSection(2, z3, 0., r3); +// new TGeoTrd2("stsCone1", r1, r2, r1, r2, (z2-z1)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans1 = new TGeoTranslation("trans1", 0., 0., -(z3-z1)/2.+(z2-z1)/2.); +// trans1->RegisterYourself(); +// new TGeoTrd2("stsCone2", r2, r3, r2, r3, (z3-z2)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans2 = new TGeoTranslation("trans2", 0., 0., +(z3-z1)/2.-(z3-z2)/2.); +// trans2->RegisterYourself(); +// +////DE Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +////DE Double_t z2 = statPos[7] + 0.5 * stsBorder; // end of STS box +////DE Double_t slope = (gkPipeR2 - gkPipeR1) / (gkPipeZ2 - gkPipeZ1); +////DE Double_t r1 = gkPipeR1 + slope * (z1 - gkPipeZ1); // at start of STS +////DE Double_t r2 = gkPipeR1 + slope * (z2 - gkPipeZ1); // at end of STS +////DE r1 += 0.1; // safety margin +////DE r2 += 0.1; // safety margin +////DE // new TGeoCone("stsCone", stsZ/2., 0., r1, 0., r2); +////DE new TGeoTrd2("stsCone", r1, r2, r1, r2, stsZ/2.); + + + // // Create holding/cooling plates + // static std::vector< std::vector<Double_t> > plateSizes = { + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // }; + + // // 8-vertex cut-outs { minWidth, maxWidth, minHeight, maxHeight } + // static std::vector< std::vector<Double_t> > plateCutOuts = { + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 17.6, 47.6 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 49.0, 79.0 }, + // { 85.5,115.5, 51.5, 82.8 }, + // { 85.5,115.5, 59.0, 91.4 }, + // { 85.5,115.5, 68.0, 99.0 }, + // }; + + // for (Int_t iPlate = 0; iPlate < 9; iPlate++) { + // Int_t iUnit = iPlate * 2; + // TGeoBBox* outerPlate = new TGeoBBox(Form("outerPlate%02d",iPlate), + // plateSizes[iPlate][0], plateSizes[iPlate][1], plateSizes[iPlate][2]); + + // TGeoBBox* unitShapeR = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+0])->GetShape(); + // TGeoBBox* unitShapeL = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+1])->GetShape(); + + // Double_t maxDx = (unitShapeR->GetDX() + unitShapeL->GetDX()) / 2.; + // Double_t maxDy = TMath::Max(unitShapeR->GetDY(), unitShapeL->GetDY()); + // cout << maxDy << endl; + + // Double_t* cutOutX = new Double_t[8]; + // Double_t* cutOutY = new Double_t[8]; + + // cutOutX[0] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[0] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[1] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[1] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[2] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[2] = 1/2. * plateCutOuts[iPlate][2]; + // cutOutX[3] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[3] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[4] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[4] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[5] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[5] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[6] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[6] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[7] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[7] = 1/2. * plateCutOuts[iPlate][2]; + + // TGeoXtru* cutOutShape = new TGeoXtru(2); + // cutOutShape->SetName(Form("innerPlate%02d", iPlate)); + // cutOutShape->DefinePolygon(8, cutOutX, cutOutY); + // cutOutShape->DefineSection(0, -1*plateSizes[iPlate][2]-1e-7); + // cutOutShape->DefineSection(1, +1*plateSizes[iPlate][2]+1e-7); + + // TGeoShape* plateShape = new TGeoCompositeShape(Form("PlateShape%02d",iPlate), Form("outerPlate%02d-innerPlate%02d",iPlate,iPlate)); + // TGeoVolume* plate = new TGeoVolume(Form("Plate%02d", iPlate), plateShape, gGeoManager->GetMedium("aluminium")); + // plate->SetLineColor(kRed); + // plate->SetTransparency(65); + // plate->GetShape()->ComputeBBox(); + // } + + // --- Create STS volume + TString stsName = "sts_"; + stsName += geoTag; + +// TGeoShape* stsShape = new TGeoCompositeShape("stsShape", +// "stsBox-stsCone1:trans1-stsCone2:trans2"); +// TGeoVolume* sts = new TGeoVolume(stsName.Data(), stsShape, gStsMedium); + + Double_t stsBorder = 2 * 5.; + + TGeoVolume* sts = new TGeoVolumeAssembly(stsName.Data()); + + // --- Place stations in the STS + Double_t stsPosZ = 0.5 * ( statPos[15] + statPos[0] ); // todo units: update statPos[7] + // cout << "stsPosZ " << stsPosZ << " " << statPos[15] << " " << statPos[0] << "*****" << endl; + +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) { + for (Int_t iUnit = 0; iUnit < 18; iUnit++) { +// for (Int_t iUnit = 0; iUnit < 32; iUnit++) { + TGeoVolume* station = gGeoMan->GetVolume(unitName18[iUnit]); +// Double_t posZ = statPos[iUnit] - stsPosZ; + Double_t posZ = statPos18[iUnit] - stsPosZ; +// Double_t posZ = statPos[iUnit/2] - stsPosZ; + TGeoTranslation* trans = new TGeoTranslation(0., 0., posZ); + sts->AddNode(station, iUnit+1, trans); + sts->GetShape()->ComputeBBox(); + } + + // --- Import passive elements from GDML file + if (gkImportPassive) { + ImportPassive(sts, geoTag, infoFile); + } + + cout << endl; + CheckVolume(sts); + // -------------------------------------------------------------------------- + + + // --------------- Finish ----------------------------------------------- + TGeoTranslation* stsTrans = new TGeoTranslation(0., 0., stsPosZ); + top->AddNode(sts, 1, stsTrans); + top->GetShape()->ComputeBBox(); + cout << endl << endl; + + CheckVolume(top); + cout << endl << endl; + gGeoMan->CloseGeometry(); + gGeoMan->CheckOverlaps(0.0001); + gGeoMan->PrintOverlaps(); + gGeoMan->CheckOverlaps(0.0001, "s"); + gGeoMan->PrintOverlaps(); + gGeoMan->Test(); + + TFile* geoFile = new TFile(geoFileName, "RECREATE"); + top->Write(); + cout << endl; + cout << "Geometry " << top->GetName() << " written to " + << geoFileName << endl; + geoFile->Close(); + + TString geoFileName_ = "sts_"; + geoFileName_ = geoFileName_ + geoTag + "_geo.root"; + + geoFile = new TFile(geoFileName_, "RECREATE"); + gGeoMan->Write(); // use this is you want GeoManager format in the output + geoFile->Close(); + + TString geoFileName__ = "sts_"; + geoFileName_ = geoFileName__ + geoTag + "-geo.root"; + sts->Export(geoFileName_); + + geoFile = new TFile(geoFileName_, "UPDATE"); + stsTrans->Write(); + geoFile->Close(); + + // gGeoManager->FindVolumeFast("LadderType10_CarbonElement")->Draw("ogl"); + top->Draw("ogl"); + gGeoManager->SetVisLevel(8); + + infoFile.close(); + +} +// ============================================================================ +// ====== End of main function ===== +// ============================================================================ + + + + + +// **************************************************************************** +// ***** Definition of media, sensors, sectors and ladders ***** +// ***** ***** +// ***** Decoupled from main function for better readability ***** +// **************************************************************************** + + +/** =========================================================================== + ** Create media + ** + ** Currently created: air, active silicon, passive silion + ** + ** Not used for the time being + **/ +Int_t CreateMedia() { + + Int_t nMedia = 0; + Double_t density = 0.; + + // --- Material air + density = 1.205e-3; // [g/cm^3] + TGeoMixture* matAir = new TGeoMixture("sts_air", 3, density); + matAir->AddElement(14.0067, 7, 0.755); // Nitrogen + matAir->AddElement(15.999, 8, 0.231); // Oxygen + matAir->AddElement(39.948, 18, 0.014); // Argon + + // --- Material silicon + density = 2.33; // [g/cm^3] + TGeoElement* elSi = gGeoMan->GetElementTable()->GetElement(14); + TGeoMaterial* matSi = new TGeoMaterial("matSi", elSi, density); + + + // --- Air (passive) + TGeoMedium* medAir = new TGeoMedium("air", nMedia++, matAir); + medAir->SetParam(0, 0.); // is passive + medAir->SetParam(1, 1.); // is in magnetic field + medAir->SetParam(2, 20.); // max. field [kG] + medAir->SetParam(6, 0.001); // boundary crossing precision [cm] + + + // --- Active silicon for sensors + TGeoMedium* medSiAct = new TGeoMedium("silicon", + nMedia++, matSi); + medSiAct->SetParam(0, 1.); // is active + medSiAct->SetParam(1, 1.); // is in magnetic field + medSiAct->SetParam(2, 20.); // max. field [kG] + medSiAct->SetParam(6, 0.001); // boundary crossing precisison [cm] + + // --- Passive silicon for cables + TGeoMedium* medSiPas = new TGeoMedium("carbon", + nMedia++, matSi); + medSiPas->SetParam(0, 0.); // is passive + medSiPas->SetParam(1, 1.); // is in magnetic field + medSiPas->SetParam(2, 20.); // max. field [kG] + medSiPas->SetParam(6, 0.001); // boundary crossing precisison [cm] + + return nMedia; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sensors + ** + ** Sensors are created as volumes with box shape and active silicon as medium. + ** Four kinds of sensors: 3.2x2.2, 6.2x2.2, 6.2x4.2, 6.2x6.2 + **/ +Int_t CreateSensors() { + + Int_t nSensors = 0; + + Double_t xSize = 0.; + Double_t ySize = 0.; + Double_t zSize = gkSensorThickness; + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + + + // --- Sensor type 01: Small sensor (6.2 cm x 2.2 cm) + xSize = gkSensorSizeX; + ySize = 2.2; + TGeoBBox* shape_sensor01 = new TGeoBBox("sensor01", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor01", shape_sensor01, silicon); + nSensors++; + + + // --- Sensor type 02: Medium sensor (6.2 cm x 4.2 cm) + xSize = gkSensorSizeX; + ySize = 4.2; + TGeoBBox* shape_sensor02 = new TGeoBBox("sensor02", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor02", shape_sensor02, silicon); + nSensors++; + + + // --- Sensor type 03: Big sensor (6.2 cm x 6.2 cm) + xSize = gkSensorSizeX; + ySize = 6.2; + TGeoBBox* shape_sensor03 = new TGeoBBox("sensor03", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor03", shape_sensor03, silicon); + nSensors++; + + + // --- Sensor type 04: Big sensor (6.2 cm x 12.4 cm) + xSize = gkSensorSizeX; + ySize = 12.4; + TGeoBBox* shape_sensor04 = new TGeoBBox("sensor04", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor04", shape_sensor04, silicon); + nSensors++; + + + // below are extra small sensors, those are not available in the CAD model + + // --- Sensor Type 05: Half small sensor (4 cm x 2.5 cm) + xSize = 4.0; + ySize = 2.5; + TGeoBBox* shape_sensor05 = new TGeoBBox("sensor05", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor05", shape_sensor05, silicon); + nSensors++; + + + // --- Sensor type 06: Additional "in hole" sensor (3.1 cm x 4.2 cm) + xSize = 3.1; + ySize = 4.2; + TGeoBBox* shape_sensor06 = new TGeoBBox("sensor06", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor06", shape_sensor06, silicon); + nSensors++; + + + // --- Sensor type 07: Mini Medium sensor (1.5 cm x 4.2 cm) + xSize = 1.5; + ySize = 4.2; + TGeoBBox* shape_sensor07 = new TGeoBBox("sensor07", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor07", shape_sensor07, silicon); + nSensors++; + + + return nSensors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sectors + ** + ** A sector is either a single sensor or several chained sensors. + ** It is implemented as TGeoVolumeAssembly. + ** Currently available: + ** - single sensors of type 1 - 4 + ** - two chained sensors of type 4 + ** - three chained sensors of type 4 + **/ +Int_t CreateSectors() { + + Int_t nSectors = 0; + + TGeoVolume* sensor01 = gGeoMan->GetVolume("Sensor01"); + TGeoVolume* sensor02 = gGeoMan->GetVolume("Sensor02"); + TGeoVolume* sensor03 = gGeoMan->GetVolume("Sensor03"); + TGeoVolume* sensor04 = gGeoMan->GetVolume("Sensor04"); + TGeoVolume* sensor05 = gGeoMan->GetVolume("Sensor05"); + TGeoVolume* sensor06 = gGeoMan->GetVolume("Sensor06"); + TGeoVolume* sensor07 = gGeoMan->GetVolume("Sensor07"); + // TGeoBBox* box4 = (TGeoBBox*) sensor04->GetShape(); + + // --- Sector type 1: single sensor of type 1 + TGeoVolumeAssembly* sector01 = new TGeoVolumeAssembly("Sector01"); + sector01->AddNode(sensor01, 1); + sector01->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 2: single sensor of type 2 + TGeoVolumeAssembly* sector02 = new TGeoVolumeAssembly("Sector02"); + sector02->AddNode(sensor02, 1); + sector02->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 3: single sensor of type 3 + TGeoVolumeAssembly* sector03 = new TGeoVolumeAssembly("Sector03"); + sector03->AddNode(sensor03, 1); + sector03->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 4: single sensor of type 4 + TGeoVolumeAssembly* sector04 = new TGeoVolumeAssembly("Sector04"); + sector04->AddNode(sensor04, 1); + sector04->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 5: single sensor of type 5 + TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); + sector05->AddNode(sensor05, 1); + sector05->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 6: single sensor of type 6 + TGeoVolumeAssembly* sector06 = new TGeoVolumeAssembly("Sector06"); + sector06->AddNode(sensor06, 1); + sector06->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 7: single sensor of type 7 + TGeoVolumeAssembly* sector07 = new TGeoVolumeAssembly("Sector07"); + sector07->AddNode(sensor07, 1); + sector07->GetShape()->ComputeBBox(); + nSectors++; + +// // --- Sector type 5: two sensors of type 4 +// TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); +// Double_t shift5 = 0.5 * gkChainGapY + box4->GetDY(); +// TGeoTranslation* transD5 = +// new TGeoTranslation("td", 0., -1. * shift5, 0.); +// TGeoTranslation* transU5 = +// new TGeoTranslation("tu", 0., shift5, 0.); +// sector05->AddNode(sensor04, 1, transD5); +// sector05->AddNode(sensor04, 2, transU5); +// sector05->GetShape()->ComputeBBox(); +// nSectors++; + + return nSectors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create ladders + ** + ** Ladders are the building blocks of the stations. They contain + ** several modules placed one after the other along the z axis + ** such that the sectors are arranged vertically (with overlap). + ** + ** A ladder is constructed out of two half ladders, the second of which + ** is rotated in the x-y plane by 180 degrees and displaced + ** in z direction. + **/ +Int_t CreateLadders() { + + Int_t nLadders = 0; + + // --- Some variables + Int_t nSectors = 0; + Int_t sectorTypes[10]; + TGeoBBox* shape = NULL; + TString s0name; + TString hlname; + char align; + TGeoVolume* s0vol = NULL; + TGeoVolume* halfLadderU = NULL; + TGeoVolume* halfLadderD = NULL; + + // --- Ladders 01-23 + Int_t allSectorTypes[27][6] = { { 1, 2, 3, 3, 0, -1 }, // ladder 01 - 5 - last column defines alignment of small sensors + { 1, 2, 3, 3, 0, 0 }, // ladder 02 - 5 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, -1 }, // ladder 03 - 6 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 04 - 6 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, -1 }, // ladder 05 - 7 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 06 - 7 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 07 - last column defines alignment of small sensors + { 3, 4, 4, 4, 0, 0 }, // ladder 08 - last column defines alignment of small sensors + + { 1, 1, 2, 3, 3, 0 }, // ladder 09 - last column defines alignment of small sensors + { 1, 1, 2, 2, 3, 0 }, // ladder 10 - last column defines alignment of small sensors + { 2, 2, 0, 0, 0, 0 }, // ladder 11 - last column defines alignment of small sensors + { 2, 2, 2, 3, 4, 0 }, // ladder 12 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 13 - last column defines alignment of small sensors + + { 2, 3, 4, 0, 0, 0 }, // ladder 14 - last column defines alignment of small sensors + { 3, 3, 0, 0, 0, 0 }, // ladder 15 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 16 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 17 - last column defines alignment of small sensors + { 3, 4, 4, 0, 0, 0 }, // ladder 18 - last column defines alignment of small sensors + + { 4, 4, 0, 0, 0, 0 }, // ladder 19 - last column defines alignment of small sensors + { 1, 2, 4, 4, 4, 0 }, // ladder 20 - last column defines alignment of small sensors + { 4, 0, 0, 0, 0, 0 }, // ladder 21 - last column defines alignment of small sensors + { 2, 3, 4, 4, 4, 0 }, // ladder 22 - last column defines alignment of small sensors + { 2, 3, 3, 4, 4, 0 }, // ladder 23 - last column defines alignment of small sensors + + { 2, 3, 4, 4, 0, 0 }, // ladder 24 - copy of 17 with different total length + { 3, 4, 4, 0, 0, 0 }, // ladder 25 - copy of 18 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 26 - copy of 19 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 27 - copy of 19 with different total length + }; // 8 full - 19 partial ladders + +// Issue #405 +// Counting from the most upstream ladder, the gaps between sensors are as follows: +// 01 (most upstream): 41.3mm +// 02: 41.3mm +// 03: 42.0mm +// 04: 48.6mm +// 05: 60.8mm +// 06: 67.0mm +// 07: 79.2mm +// 08 (most downstream): 88.0mm + + Double_t pitchZ = 0; + Double_t gapXYZ[27][3] = { + { 0., 4.13, 0. }, // ladder 01 + { 0., 4.13, 0. }, // ladder 02 + { 0., 4.20, 0. }, // ladder 03 + { 0., 4.86, 0. }, // ladder 04 + { 0., 6.08, 0. }, // ladder 05 + { 0., 6.70, 0. }, // ladder 06 + { 0., 7.92, 0. }, // ladder 07 + { 0., 8.80, 0. }, // ladder 08 + { 0., -gkSectorOverlapY, 0. }, // ladder 09 + { 0., -gkSectorOverlapY, 0. }, // ladder 10 + { 0., -gkSectorOverlapY, 0. }, // ladder 11 + { 0., -gkSectorOverlapY, 0. }, // ladder 12 + { 0., -gkSectorOverlapY, 0. }, // ladder 13 + { 0., -gkSectorOverlapY, 0. }, // ladder 14 + { 0., -gkSectorOverlapY, 0. }, // ladder 15 + { 0., -gkSectorOverlapY, 0. }, // ladder 16 + { 0., -gkSectorOverlapY, 0. }, // ladder 17 + { 0., -gkSectorOverlapY, 0. }, // ladder 18 + { 0., -gkSectorOverlapY, 0. }, // ladder 19 + { 0., -gkSectorOverlapY, 0. }, // ladder 20 + { 0., -gkSectorOverlapY, 0. }, // ladder 21 + { 0., -gkSectorOverlapY, 0. }, // ladder 22 + { 0., -gkSectorOverlapY, 0. }, // ladder 23 + + { 0., -gkSectorOverlapY, 0. }, // ladder 24 - copy of 17 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 25 - copy of 18 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 26 - copy of 19 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 27 - copy of 19 with different total length + }; + + Double_t ladderLength[27] = { + 48.0, // ladder 01 + 48.0, // ladder 02 + 64.0, // ladder 03 + 64.0, // ladder 04 + 80.0, // ladder 05 + 80.0, // ladder 06 + 92.0, // ladder 07 + 96.0, // ladder 08 + 48.0, // ladder 09 + 48.0, // ladder 10 + 48.0, // ladder 11 + 64.0, // ladder 12 + 64.0, // ladder 13 + 64.0, // ladder 14 + 64.0, // ladder 15 + 80.0, // ladder 16 + 80.0, // ladder 17 + 80.0, // ladder 18 + 80.0, // ladder 19 + 92.0, // ladder 20 + 92.0, // ladder 21 + 96.0, // ladder 22 + 96.0, // ladder 23 + + 96.0, // ladder 24 - copy of 17 with different total length + 92.0, // ladder 25 - copy of 18 with different total length + 96.0, // ladder 26 - copy of 19 with different total length + 92.0, // ladder 27 - copy of 19 with different total length + }; +// ======================================================================== + + // calculate Z shift for ladders with and without gaps in the center + s0name = Form("Sector%02d", allSectorTypes[0][0]); + s0vol = gGeoMan->GetVolume(s0name); + shape = (TGeoBBox*) s0vol->GetShape(); + +// ======================================================================== + + for (Int_t iLadder = 0; iLadder < 27; iLadder++) + { + cout << endl; + nSectors = 0; + for (Int_t i=0; i < 5; i++) + if (allSectorTypes[iLadder][i] != 0) + { + sectorTypes[nSectors] = allSectorTypes[iLadder][i]; // copy sectors for this ladder + cout << "DE iLadder " << iLadder+1 << " sectorTypes[" << nSectors << "] = " << allSectorTypes[iLadder][i] << ";" << endl; + nSectors++; // count how many sectors are in this ladder + } + + // always set displacement in z between upper and lower half ladder + gapXYZ[iLadder][2] = 2. * shape->GetDZ() + gkSectorGapZ; + + // define additional offset to carbon ladder for half ladders with less than 5 sensors + pitchZ = 2. * shape->GetDZ() + gkSectorGapZ; + + if (allSectorTypes[iLadder][5] == 0) + align = 'l'; + else + align = 'r'; + hlname = Form("HalfLadder%02du", iLadder+1); + // build upper half ladder + halfLadderU = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2.); // mirrored + + if (allSectorTypes[iLadder][5] == 0) + align = 'r'; + else + align = 'l'; + hlname = Form("HalfLadder%02dd", iLadder+1); + // build lower half ladder + halfLadderD = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2.); // mirrored + + // at this point half ladders are constructed + + // build all 4 possible ladders types for this sensor arrangement + ConstructLadder( iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19a + ConstructLadder( 100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19b + + ConstructLadder(1000+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19k + ConstructLadder(1100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19k + + nLadders++; + } + + return nLadders; +} +/** ======================================================================= **/ + + + +// **************************************************************************** +// ***** ***** +// ***** Generic functions for the construction of STS elements ***** +// ***** ***** +// ***** module: volume (made of a sector and a cable) ***** +// ***** haf ladder: assembly (made of modules) ***** +// ***** ladder: assembly (made of two half ladders) ***** +// ***** station: volume (made of ladders) ***** +// ***** ***** +// **************************************************************************** + + + +/** =========================================================================== + ** Construct a module + ** + ** A module is a sector plus the readout cable extending from the + ** top of the sector. The cable is made from passive silicon. + ** The cable has the same x size as the sector. + ** Its thickness is given by the global variable gkCableThickness. + ** The cable length is a parameter. + ** The sensor(s) of the sector is/are placed directly in the module; + ** the sector is just auxiliary for the proper placement. + ** + ** Arguments: + ** name volume name + ** sector pointer to sector volume + ** cableLength length of cable + **/ +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength) { + + // --- Check sector volume + if ( ! sector ) Fatal("CreateModule", "Sector volume not found!"); + + // --- Get size of sector + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + + // --- Get size of cable + Double_t cableX = sectorX; + Double_t cableY = cableLength; + Double_t cableZ = gkCableThickness; + + // --- Create module volume + Double_t moduleX = TMath::Max(sectorX, cableX); + Double_t moduleY = sectorY + cableLength; + + Double_t moduleZ = TMath::Max(sectorZ, cableZ); + + TGeoVolume* module = gGeoManager->MakeBox(name, gStsMedium, + moduleX/2., + moduleY/2., + moduleZ/2.); + + // --- Position of sector in module + // --- Sector is centred in x and z and aligned to the bottom + Double_t sectorXpos = 0.; + Double_t sectorYpos = 0.5 * (sectorY - moduleY); + Double_t sectorZpos = 0.; + + + // --- Get sensor(s) from sector + Int_t nSensors = sector->GetNdaughters(); + for (Int_t iSensor = 0; iSensor < nSensors; iSensor++) { + TGeoNode* sensor = sector->GetNode(iSensor); + + // --- Calculate position of sensor in module + const Double_t* xSensTrans = sensor->GetMatrix()->GetTranslation(); + Double_t sensorXpos = 0.; + Double_t sensorYpos = sectorYpos + xSensTrans[1]; + Double_t sensorZpos = 0.; + TGeoTranslation* sensTrans = new TGeoTranslation("sensTrans", + sensorXpos, + sensorYpos, + sensorZpos); + + // --- Add sensor volume to module + TGeoVolume* sensVol = sensor->GetVolume(); + module->AddNode(sensor->GetVolume(), iSensor+1, sensTrans); + module->GetShape()->ComputeBBox(); + } + + + // --- Create cable volume, if necessary, and place it in module + // --- Cable is centred in x and z and aligned to the top + if ( gkConstructCables && cableLength > 0.0001 ) { + TString cableName = TString(name) + "_cable"; + TGeoMedium* cableMedium = gGeoMan->GetMedium("STScable"); + if ( ! cableMedium ) Fatal("CreateModule", "Medium STScable not found!"); + TGeoVolume* cable = gGeoManager->MakeBox(cableName.Data(), + cableMedium, + cableX / 2., + cableY / 2., + cableZ / 2.); + // add color to cables + cable->SetLineColor(kOrange); + cable->SetTransparency(60); + Double_t cableXpos = 0.; + Double_t cableYpos = sectorY + 0.5 * cableY - 0.5 * moduleY; + Double_t cableZpos = 0.; + TGeoTranslation* cableTrans = new TGeoTranslation("cableTrans", + cableXpos, + cableYpos, + cableZpos); + module->AddNode(cable, 1, cableTrans); + module->GetShape()->ComputeBBox(); + } + + return module; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a half ladder + ** + ** A half ladder is a virtual volume (TGeoVolumeAssembly) consisting + ** of several modules arranged on top of each other. The modules + ** have a given overlap in y and a displacement in z to allow for the + ** overlap. + ** + ** The typ of sectors / modules to be placed must be specified: + ** 1 = sensor01 + ** 2 = sensor02 + ** 3 = sensor03 + ** 4 = sensor04 + ** 5 = 2 x sensor04 (chained) + ** 6 = 3 x sensor04 (chained) + ** The cable is added automatically from the top of each sensor to + ** the top of the half ladder. + ** The alignment can be left (l) or right (r), which matters in the + ** case of different x sizes of sensors (e.g. SensorType01). + ** + ** Arguments: + ** name volume name + ** nSectors number of sectors + ** sectorTypes array with sector types + ** align horizontal alignment of sectors + * ladderLength full length of the ladder towards FEE + * offsetY gap in the beam-pipe region + **/ +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY) { + + // --- Create half ladder volume assembly + TGeoVolumeAssembly* halfLadder = new TGeoVolumeAssembly(name); + + // --- Determine size of ladder + Double_t ladderX = 0.; + Double_t ladderY = 0.; + Double_t ladderZ = 0.; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + if ( ! sector ) + Fatal("ConstructHalfLadder", Form("Volume %s not found", sectorName.Data())); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + // --- Ladder x size equals largest sector x size + ladderX = TMath::Max(ladderX, 2. * box->GetDX()); + // --- Ladder y size is sum of sector ysizes + ladderY += 2. * box->GetDY(); + // --- Ladder z size is sum of sector z sizes + ladderZ += 2. * box->GetDZ(); + } + // --- Subtract overlaps in y + ladderY -= Double_t(nSectors-1) * gkSectorOverlapY; + // --- Add gaps in z direction + ladderZ += Double_t(nSectors-1) * gkSectorGapZ; + + ladderY = TMath::Max(ladderLength - offsetY, ladderY); + + // --- Create and place modules + Double_t yPosSect = -0.5 * ladderY; + Double_t zPosMod = -0.5 * ladderZ; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + yPosSect += 0.5 * sectorY; // Position of sector in ladder + Double_t cableLength = 0.5 * ladderY - yPosSect - 0.5 * sectorY; + TString moduleName = name + "_" + Form("Module%02d", + sectorTypes[iSector]); + TGeoVolume* module = ConstructModule(moduleName.Data(), + sector, cableLength); + + TGeoBBox* shapeMod = (TGeoBBox*) module->GetShape(); + Double_t moduleX = 2. * shapeMod->GetDX(); + Double_t moduleY = 2. * shapeMod->GetDY(); + Double_t moduleZ = 2. * shapeMod->GetDZ(); + Double_t xPosMod = 0.; + if ( align == 'l' ) + xPosMod = 0.5 * (moduleX - ladderX); // left aligned + else if ( align == 'r' ) + xPosMod = 0.5 * (ladderX - moduleX); // right aligned + else + xPosMod = 0.; // centred in x + Double_t yPosMod = 0.5 * (ladderY - moduleY); // top aligned + zPosMod += 0.5 * moduleZ; + TGeoTranslation* trans = new TGeoTranslation("t", xPosMod, + yPosMod, zPosMod); + halfLadder->AddNode(module, iSector+1, trans); + halfLadder->GetShape()->ComputeBBox(); + yPosSect += 0.5 * sectorY - gkSectorOverlapY; + zPosMod += 0.5 * moduleZ + gkSectorGapZ; + } + + CheckVolume(halfLadder); + cout << endl; + + return halfLadder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Add a carbon support to a ladder + ** + ** Arguments: + ** LadderIndex ladder number + ** ladder pointer to ladder + ** xu size of halfladder + ** ladderY height of ladder along y + ** ladderZ thickness of ladder along z + **/ +void AddCarbonLadder(Int_t LadderIndex, + TGeoVolume* ladder, + Double_t xu, + Double_t ladderY, + Double_t ladderZ) { + + // --- Some variables + TString name = Form("LadderType%04d", LadderIndex); // v19k + Int_t i; + Double_t j; + + Int_t YnumOfFrameBoxes = round(ladderY / gkFrameStep); + + // cout << "DEXZ: lad " << LadderIndex << " inum " << YnumOfFrameBoxes << endl; + + Double_t ladderDZ = (xu/2. + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2)/2.; + cout << "DEFR: frame Z size " << 2 * ladderDZ << " cm" << endl; + + TGeoBBox* fullFrameShp = new TGeoBBox (name+"_CarbonElement_shp", xu/2., gkFrameStep/2., ladderDZ); + TGeoVolume* fullFrameBoxVol = new TGeoVolume(name+"_CarbonElement", fullFrameShp, gStsMedium); + + ConstructFrameElement("CarbonElement", fullFrameBoxVol, xu/2.); + TGeoRotation* fullFrameRot = new TGeoRotation; + fullFrameRot->RotateY(180); + + Int_t inum = YnumOfFrameBoxes; + for (i=1; i<=inum; i++) + { + j=-(inum-1)/2.+(i-1); + // -(10-1)/2. +0 +10-1 -> -4.5 .. +4.5 -> -0.5, +0.5 (= 2) + // -(11-1)/2. +0 +11-1 -> -5.0 .. +5.0 -> -1, 0, 1 (= 3) + // cout << "DE: i " << i << " j " << j << endl; + + if (LadderIndex % 100 <= 3) // central ladders in stations 1 to 3 + { + if ((j>=-1) && (j<=1)) // keep the inner 2 (even) or 3 (odd) elements free for the cone + continue; + } + else if (LadderIndex % 100 <= 8) // central ladders in stations 4 to 8 + { + if ((j>=-2) && (j<=2)) // keep the inner 4 elements free for the cone + continue; + } + + cout << "DELZ: ladderDZ " << ladderDZ << " cm " << -ladderZ/2. - ladderDZ << " cm " << endl; + ladder->AddNode(fullFrameBoxVol, i, new TGeoCombiTrans(name+"_CarbonElement_posrot", 0., j*gkFrameStep, -(ladderZ/2.+ladderDZ), fullFrameRot)); + } + + ladder->GetShape()->ComputeBBox(); + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Construct a ladder out of two half ladders with vertical gap + ** + ** The second half ladder will be rotated by 180 degrees + ** in the x-y plane. The two half ladders will be put on top of each + ** other with a vertical gap. + ** + ** Arguments: + ** name volume name + ** halfLadderU pointer to upper half ladder + ** halfLadderD pointer to lower half ladder + ** gapY vertical gap + ** shiftZ relative displacement along the z axis + **/ + + TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ, + Double_t pitchZ, + Int_t nSectors) { + + // --- Some variables + TGeoBBox* shape = NULL; + + // define additional offset to carbon ladder for half ladders with less than 5 sensors + Double_t offsetZ = (5 - nSectors) * pitchZ; + + // --- Dimensions of half ladders + shape = (TGeoBBox*) halfLadderU->GetShape(); // up + Double_t xu = 2. * shape->GetDX(); + Double_t yu = 2. * shape->GetDY(); + Double_t zu = 2. * shape->GetDZ(); + + shape = (TGeoBBox*) halfLadderD->GetShape(); // down + Double_t xd = 2. * shape->GetDX(); + Double_t yd = 2. * shape->GetDY(); + Double_t zd = 2. * shape->GetDZ(); + + // --- Create ladder volume assembly + TString name = Form("LadderType%04d", LadderIndex); // v19k + TGeoVolumeAssembly* ladder = new TGeoVolumeAssembly(name); + Double_t ladderX = TMath::Max(xu, xd); + Double_t ladderY = yu + yd + gapY; + Double_t ladderZ = TMath::Max(zu, zd + shiftZ + offsetZ); // there are 6 slots - 5 x 1.5 mm + 0.3 mm = 7.8 mm + // Double_t ladderZ = TMath::Max(zu, zd + shiftZ); + + cout << "DERR iladder " << LadderIndex << " nSec " << nSectors + << " zu " << zu << " zd " << zd + << " zd+shi " << zd+shiftZ << " ladderZ " << ladderZ + << " offsetZ " << offsetZ << endl; + + // --- Place half ladders + Double_t xPosU = 0.0; // centred in x + Double_t yPosU = 0.5 * ( ladderY - yu ); // top aligned + Double_t zPosU = 0; + zPosU = 0.5 * ( ladderZ - zu ); // front aligned + if (LadderIndex >= 1000) + zPosU = -0.5 * ( ladderZ - zu ) + offsetZ; // back aligned with possible offset + //zPosU = -zPosU; + + TGeoTranslation* tu = new TGeoTranslation("tu", xPosU, yPosU, zPosU); + ladder->AddNode(halfLadderU, 1, tu); + + Double_t xPosD = 0.0; // centred in x + Double_t yPosD = 0.5 * -( ladderY - yd ); // bottom aligned + Double_t zPosD = 0; + zPosD = 0.5 * -( ladderZ - zd ) + offsetZ; // back aligned with possible offset + if (LadderIndex >= 1000) + zPosD = -0.5 * -( ladderZ - zd ); // front aligned + //zPosD = -zPosD; + + TGeoRotation* rd = new TGeoRotation(); + rd->RotateZ(180.); + TGeoCombiTrans* cd = new TGeoCombiTrans(xPosD, yPosD, zPosD, rd); + ladder->AddNode(halfLadderD, 2, cd); + + ladder->GetShape()->ComputeBBox(); + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD0ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + cout << "DDDD ladder" << LadderIndex << endl; + cout << "DDDD1ladder" << LadderIndex << " ladderX " << ladderX << " ladderY " << ladderY << " ladderZ " << ladderZ << endl; + + // ---------------- Create and place frame boxes ------------------------ + + if (gkConstructFrames) + AddCarbonLadder(LadderIndex, ladder, ladderX, ladderY, ladderZ); + + // -------------------------------------------------------------------------- + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD2ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + return ladder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a unit + ** + ** The unit volume is the minimal box comprising all ladders + ** minus a tube accomodating the beam pipe. + ** + ** The ladders are arranged horizontally from left to right with + ** a given overlap in x. + ** Every second ladder is slightly displaced upstream from the centre + ** z plane and facing downstream, the others are slightly displaced + ** downstream and facing upstream (rotated around the y axis). + ** + ** Arguments: + ** name volume name + ** nLadders number of ladders + ** ladderTypes array of ladder types + **/ + + TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation) { + + Bool_t isFirstPartOfHalfUnit = kFALSE; + + // TString name = Form("Unit%02d", iUnit); // 0,1,2,3,4,5,6,7 - Unit00 missing in output + // TString name = Form("Unit%02d", iUnit+1); // 1,2,3,4,5,6,7,8 + + TGeoVolume* unit = gGeoMan->GetVolume(unitName[iUnit]); + if ( ! unit ) // if it does not yet exist, create a new one + { + unit = new TGeoVolumeAssembly(unitName[iUnit]); + isFirstPartOfHalfUnit = kTRUE; + } + + // --- Some local variables + TGeoBBox* ladderShape = NULL; + TGeoVolume* ladder = NULL; + TString ladderName; + Double_t subtractedVal; + + // --- Determine size of unit from ladders + Double_t statX = 0.; + // Double_t statY = 0.; + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) + { + Int_t ladderType = ladderTypes[iLadder]; // v19k + +// if (iSide == 0) cout << "DWER " << ladderTypes[iLadder] << " " << ladderType << endl; + + if (ladderType > 0) + { + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + if ( ! ladder ) Fatal("ConstructUnit", + Form("Volume %s not found", ladderName.Data())); + ladderShape = (TGeoBBox*) ladder->GetShape(); + statX += 2. * ladderShape->GetDX(); + } + else + statX += gkSensorSizeX; // empty ladder in unit + } + statX -= Double_t(nLadders-1) * gkLadderOverlapX; + +// if (iSide == 0) cout << "DWER -" << endl; + + // --- Place ladders in unit + cout << "xPos0: " << statX << endl; + Double_t xPos = -0.5 * statX; + cout << "xPos1: " << xPos << endl; + Double_t yPos = 0.; + Double_t zPos = 0.; + + Double_t maxdz = 0.; + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) // find maximum dz in this unit + { + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + if (maxdz < ladderShape->GetDZ()) + maxdz = ladderShape->GetDZ(); + } + } + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) + { + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + xPos += ladderShape->GetDX(); + cout << "xPos2: " << xPos << endl; + yPos = 0.; // vertically centred + TGeoRotation* rot = new TGeoRotation(); + + if (gkConstructFrames) + subtractedVal = ladderShape->GetDX() + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2; + else + subtractedVal = 0.; + + zPos = 0.5 * gkLadderGapZ + (2*maxdz-ladderShape->GetDZ()-subtractedVal/2.); // z-aligned ladders + +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " dx: " << ladderShape->GetDX() + << " dy: " << ladderShape->GetDY() + << " dz: " << ladderShape->GetDZ() + << " max dz: " << maxdz << endl; + +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " fra: " << gkFrameThickness/2. + << " sub: " << subtractedVal + << " zpo: " << zPos << endl << endl; + +// v19k + if (ladderTypes[iLadder]/1000 == 1) // flip some of the ladders to reproduce the CAD layout + rot->RotateY(180.); + else + zPos = -zPos; + + if (!isFirstPartOfHalfUnit) + zPos += 10.5; // v19d +// zPos += 10.0; // initial version + + TGeoCombiTrans* trans = new TGeoCombiTrans(xPos, yPos, zPos, rot); +// start +// cout << "DEEE** iLadder " << iLadder << " " << nLadders/2 << " " << nLadders << endl; + + if (iSide == 0) + { + if (iLadder < nLadders/2) // right side - only half unit -x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + else + { + if (iLadder >= nLadders/2) // left side - only half unit +x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + unit->GetShape()->ComputeBBox(); +// stop + xPos += ladderShape->GetDX() - gkLadderOverlapX; + cout << "xPos3: " << xPos << endl; + } + else + xPos += gkSensorSizeX - gkLadderOverlapX; + } + + return unit; + } +/** ======================================================================= **/ + + +/** =========================================================================== + ** Import and add the passive materials to the STS volume + **/ +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile) +{ + TString passiveName = TString("sts_passive_") + geoTag; + TString basePath = gSystem->Getenv("VMCWORKDIR"); + TString relPath = "/geometry/sts/passive/" + passiveName + ".gdml"; + TString passiveFileName = basePath + relPath; + infoFile << std::endl << std::endl; + infoFile << "Importing STS passive materials from GDML file '" << relPath << "'." << std::endl; + + TGDMLParse parser; + TGeoVolume* gdmlVolume = parser.GDMLReadFile(passiveFileName); + PostProcessGdml(gdmlVolume); + gdmlVolume->SetName(passiveName); + + TGeoTranslation* passiveTrans = new TGeoTranslation(0., 0., 4.68 - 2.); + infoFile << "Passive assembly is translated for Z=2.68 cm downstream with respect to parent volume" << std::endl << std::endl; + + gdmlVolume->GetShape()->ComputeBBox(); + CheckVolume(gdmlVolume, infoFile); + + infoFile << std::endl; + for (Int_t iNode = 0; iNode < gdmlVolume->GetNdaughters(); iNode++) { + CheckVolume(gdmlVolume->GetNode(iNode)->GetVolume(), infoFile, kFALSE); + } + + stsVolume->AddNode(gdmlVolume, stsVolume->GetNdaughters(), passiveTrans, ""); +} + +/** =========================================================================== + ** Assign visual properties to the imported gdml volumes + **/ +void PostProcessGdml(TGeoVolume* gdmlVolume) +{ + const UInt_t kPOBColor = kRed-6; + const UInt_t kPOBTransparency = 0;// 5; + + const UInt_t kFEBColor = kOrange-6; + const UInt_t kFEBTransparency = 0;// 5; + + const UInt_t kUnitColor = kCyan-10; + const UInt_t kUnitTransparency = 0;// 5; + + const UInt_t kCfColor = kGray+3; + const UInt_t kCfTransparency = 0;// 10; + + // name <Color, Transparency> + std::map<std::string, std::tuple<UInt_t,UInt_t> > props { + { "passive_POB", std::tuple<UInt_t,UInt_t> {kPOBColor, kPOBTransparency} }, + { "passive_FEB", std::tuple<UInt_t,UInt_t> {kFEBColor, kFEBTransparency} }, + { "passive_unit", std::tuple<UInt_t,UInt_t> {kUnitColor, kUnitTransparency} }, + { "passive_Box_Wall", std::tuple<UInt_t,UInt_t> {kCfColor, kCfTransparency} }, + { "passive_Box_Wall_Front_CF2", std::tuple<UInt_t,UInt_t> {kCfColor-3, kCfTransparency} }, + }; + + // Match volume name and apply visual properties + const TObjArray* volumes = gGeoManager->GetListOfVolumes(); + for (auto& entry : props) { + TIter next(volumes); + TGeoVolume *vol = nullptr; + while ((vol=(TGeoVolume*)next())) { + if (TString(vol->GetName()).Contains(entry.first.c_str())) { + vol->SetLineColor(std::get<0>(entry.second)); + vol->SetTransparency(std::get<1>(entry.second)); + } + } + } +} + +/** =========================================================================== + ** Volume information for debugging + **/ +void CheckVolume(TGeoVolume* volume) { + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + cout << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) cout << ", assembly"; + else { + if ( volume->GetMedium() ) + cout << ", medium " << volume->GetMedium()->GetName(); + else cout << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + cout << endl; + if ( volume->GetNdaughters() ) { + cout << "Daughters: " << endl; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) { + TGeoNode* node = volume->GetNode(iNode); + TGeoBBox* shape = (TGeoBBox*) node->GetVolume()->GetShape(); + cout << setw(15) << node->GetName() << ", size " + << fixed << setprecision(3) + << setw(6) << 2. * shape->GetDX() << " x " + << setw(6) << 2. * shape->GetDY() << " x " + << setw(6) << 2. * shape->GetDZ() << ", position ( "; + TGeoMatrix* matrix = node->GetMatrix(); + const Double_t* pos = matrix->GetTranslation(); + cout << setfill(' '); + cout << fixed << setw(8) << pos[0] << ", " + << setw(8) << pos[1] << ", " + << setw(8) << pos[2] << " )" << endl; + } + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Volume information for output to file + **/ +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren) { + if ( ! file ) return; + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + file << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) file << ", assembly"; + else { + if ( volume->GetMedium() ) + file << ", medium " << volume->GetMedium()->GetName(); + else file << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + file << endl; + if ( volume->GetNdaughters() && listChildren) { + file << "Contains: "; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) + file << volume->GetNode(iNode)->GetVolume()->GetName() << " "; + file << endl; + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Calculate beam pipe outer radius for a given z + **/ +Double_t BeamPipeRadius(Double_t z) { + if ( z < gkPipeZ2 ) return gkPipeR1; + Double_t slope = (gkPipeR3 - gkPipeR2 ) / (gkPipeZ3 - gkPipeZ2); + return gkPipeR2 + slope * (z - gkPipeZ2); +} +/** ======================================================================= **/ + + + +/** ======================================================================= **/ +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + TGeoBBox* frameVertPillarShp; + + Double_t t = gkFrameThickness/2.; + + // --- Main vertical pillars +// TGeoBBox* frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, gkFrameStep/2., t); // square crossection, along y +// TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); +// frameVertPillarVol->SetLineColor(kGreen); +// frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoTranslation(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2.)); +// frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoTranslation(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkCylindricalFrames) + // TGeoBBox* frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", 0, t, gkFrameStep/2.); // circle crossection, along z + frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", gkCylinderDiaInner/2., gkCylinderDiaOuter/2., gkFrameStep/2.); // circle crossection, along z + else + frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, t, gkFrameStep/2.); // square crossection, along z + TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); + frameVertPillarVol->SetLineColor(kGreen); + + TGeoRotation* xRot90 = new TGeoRotation; + xRot90->RotateX(90.); + frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoCombiTrans(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoCombiTrans(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + + // TGeoRotation* vertRot = new TGeoRotation(name + "_vertpillar_rot_1", 90., 45., -90.); + TGeoRotation* vertRot = new TGeoRotation; + vertRot->RotateX(90.); + vertRot->RotateY(45.); + frameBoxVol->AddNode(frameVertPillarVol, 3, new TGeoCombiTrans(name + "_vertpillar_pos_3", 0., 0., (x-sqrt(2.)*t)/2., vertRot)); + + // --- Small horizontal pillar + // TGeoBBox* frameHorPillarShp = new TGeoBBox(name + "_horpillar_shape", x-2.*t, gkThinFrameThickness/2., gkThinFrameThickness/2.); + // TGeoVolume* frameHorPillarVol = new TGeoVolume(name + "_horpillar", frameHorPillarShp, framesMaterial); + // frameHorPillarVol->SetLineColor(kCyan); + // frameBoxVol->AddNode(frameHorPillarVol, 1, new TGeoTranslation(name + "_horpillar_pos_1", 0., -gkFrameStep/2.+gkThinFrameThickness/2., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkConstructSmallFrames) { + + // --- Small sloping pillars + TGeoPara* frameSlopePillarShp = new TGeoPara(name + "_slopepillar_shape", + (x-2.*t)/TMath::Cos(31.4/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., 31.4, 0., 90.); + TGeoVolume* frameSlopePillarVol = new TGeoVolume(name + "_slopepillar", frameSlopePillarShp, framesMaterial); + frameSlopePillarVol->SetLineColor(kCyan); + TGeoRotation* slopeRot = new TGeoRotation(name + "_slopepillar_rot_1", 0., 0., 31.4); + TGeoRotation* slopeRot2 = new TGeoRotation(name + "_slopepillar_rot_2", 0., 0., -31.4); + TGeoCombiTrans* slopeTrRot = new TGeoCombiTrans(name + "_slopepillar_posrot_1", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot); + TGeoCombiTrans* slopeTrRot2 = new TGeoCombiTrans(name + "_slopepillar_posrot_2", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot2); + + frameBoxVol->AddNode(frameSlopePillarVol, 1, slopeTrRot); + frameBoxVol->AddNodeOverlap(frameSlopePillarVol, 2, slopeTrRot2); + + + Double_t angl = 23.; + // --- Small sub pillar + TGeoPara* frameSubPillarShp = new TGeoPara(name + "_subpillar_shape", + (sqrt(2)*(x/2.-t)-t/2.)/TMath::Cos(angl/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., angl, 0., 90.); + TGeoVolume* frameSubPillarVol = new TGeoVolume(name + "_subpillar", frameSubPillarShp, framesMaterial); + frameSubPillarVol->SetLineColor(kMagenta); + + Double_t posZ = t * (1. - 3. / ( 2.*sqrt(2.) )); + + // one side of X direction + TGeoRotation* subRot1 = new TGeoRotation(name + "_subpillar_rot_1", 90., 45., -90.+angl); + TGeoCombiTrans* subTrRot1 = new TGeoCombiTrans(name + "_subpillar_posrot_1", -(-x/2.+t-t/(2.*sqrt(2.))), 1., posZ, subRot1); + + TGeoRotation* subRot2 = new TGeoRotation(name + "_subpillar_rot_2", 90., -90.-45., -90.+angl); + TGeoCombiTrans* subTrRot2 = new TGeoCombiTrans(name + "_subpillar_posrot_2", -(-x/2.+t-t/(2.*sqrt(2.))), -1., posZ, subRot2); + + // other side of X direction + TGeoRotation* subRot3 = new TGeoRotation(name + "_subpillar_rot_3", 90., 90.+45., -90.+angl); + TGeoCombiTrans* subTrRot3 = new TGeoCombiTrans(name + "_subpillar_posrot_3", -x/2.+t-t/(2.*sqrt(2.)), 1., posZ, subRot3); + + TGeoRotation* subRot4 = new TGeoRotation(name + "_subpillar_rot_4", 90., -45., -90.+angl); + TGeoCombiTrans* subTrRot4 = new TGeoCombiTrans(name + "_subpillar_posrot_4", -x/2.+t-t/(2.*sqrt(2.)), -1., posZ, subRot4); + + frameBoxVol->AddNode(frameSubPillarVol, 1, subTrRot1); + frameBoxVol->AddNode(frameSubPillarVol, 2, subTrRot2); + frameBoxVol->AddNode(frameSubPillarVol, 3, subTrRot3); + frameBoxVol->AddNode(frameSubPillarVol, 4, subTrRot4); + // frameBoxVol->GetShape()->ComputeBBox(); + } + + return frameBoxVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructSmallCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 6., 7.6, 6., 6.04, 0., 180.); +// TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + Double_t radius = 3.0; + Double_t thickness = 0.04; // 0.4 mm +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 3., 3.2, 3., 3.2, 0., 180.); + TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, radius, radius+thickness, radius, radius+thickness, 0., 180.); + TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + TGeoCombiTrans* M = new TGeoCombiTrans ("M"); + M->RotateX (45.); + M->SetDy (-5.575); + M->SetDz (6.935); + M->RegisterYourself(); + + TGeoShape* coneShp = new TGeoCompositeShape ("Cone_shp", "A-B:M"); + TGeoVolume* coneVol = new TGeoVolume ("Cone", coneShp, framesMaterial); + coneVol->SetLineColor(kGreen); +// coneVol->RegisterYourself(); + +// // --- Inner cone +// Double_t thickness = 0.02; +// Double_t thickness2 = 0.022; +// // TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); +// TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 3.+thickness, 4.6-thickness2, 2.99+thickness, 3.05-thickness2, 0., 180.); +// +// TGeoCombiTrans* M2 = new TGeoCombiTrans ("M2"); +// M2->RotateX (45.); +// M2->SetDy (-5.575+thickness*sqrt(2.)); +// M2->SetDz (6.935); +// M2->RegisterYourself(); +// +// TGeoShape* coneShp2 = new TGeoCompositeShape ("Cone2_shp", "A2-B:M2"); +// TGeoVolume* coneVol2 = new TGeoVolume ("Cone2", coneShp2, gStsMedium); +// coneVol2->SetLineColor(kGreen); +//// coneVol2->RegisterYourself(); +// +// coneVol->AddNode(coneVol2, 1); + + return coneVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructBigCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone + TGeoConeSeg* bA = new TGeoConeSeg ("bA", coneDz, 6., 7.6, 6., 6.04, 0., 180.); + TGeoBBox* bB = new TGeoBBox ("bB", 8., 6., 10.); + + TGeoCombiTrans* bM = new TGeoCombiTrans ("bM"); + bM->RotateX (45.); + bM->SetDy (-5.575); + bM->SetDz (6.935); + bM->RegisterYourself(); + + TGeoShape* coneBigShp = new TGeoCompositeShape ("ConeBig_shp", "bA-bB:bM"); + TGeoVolume* coneBigVol = new TGeoVolume ("ConeBig", coneBigShp, framesMaterial); + coneBigVol->SetLineColor(kGreen); +// coneBigVol->RegisterYourself(); + + // --- Inner cone + Double_t thickness = 0.02; + Double_t thickness2 = 0.022; + TGeoConeSeg* bA2 = new TGeoConeSeg ("bA2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); + + TGeoCombiTrans* bM2 = new TGeoCombiTrans ("bM2"); + bM2->RotateX (45.); + bM2->SetDy (-5.575+thickness*sqrt(2.)); + bM2->SetDz (6.935); + bM2->RegisterYourself(); + + TGeoShape* coneBigShp2 = new TGeoCompositeShape ("ConeBig2_shp", "bA2-bB:bM2"); + TGeoVolume* coneBigVol2 = new TGeoVolume ("ConeBig2", coneBigShp2, gStsMedium); + coneBigVol2->SetLineColor(kGreen); +// coneBigVol2->RegisterYourself(); + + coneBigVol->AddNode(coneBigVol2, 1); + + return coneBigVol; +} + +/** ======================================================================= **/ diff --git a/macro/sts/geometry/create_stsgeo_v19s.C b/macro/sts/geometry/create_stsgeo_v19s.C new file mode 100644 index 0000000000000000000000000000000000000000..384785a9a66d7b9cf192ca487e8d7ccad0536761 --- /dev/null +++ b/macro/sts/geometry/create_stsgeo_v19s.C @@ -0,0 +1,2516 @@ +/****************************************************************************** + ** Creation of STS geometry in ROOT format (TGeo). + ** + ** @file create_stsgeo_v19s.C + ** @author Volker Friese <v.friese@gsi.de> + ** @since 15 June 2012 + ** @date 09.05.2014 + ** @author Tomas Balog <T.Balog@gsi.de> + ** + ** v19s: introducing pp-nn sensor orientation - visualisation using blue and red surfaces + ** v19r: bugfix of v19q - align all halfladders + ** v19q: based on v19l - align ladders to virtual plane in station center, closing the gaps in z + ** v19p: based on v19k - parameters : delta Z prime = 0.70 cm - delta Z pitch = 0.20 cm + ** v19o: based on v19k - parameters : delta Z prime = 0.30 cm - delta Z pitch = 0.20 cm + ** v19n: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.20 cm (bug fix of v19m) + ** v19m: based on v19k - parameters : delta Z prime = 0.55 cm - delta Z pitch = 0.20 cm (bug) + ** v19l: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.15 cm + ** v19k: ladders on upstream side of units get upper half ladders installed first, + ** ladders on downstream side of units get lower half ladders installed first, + ** this saves 1.5 mm space in z per station, 12 mm in total (LadderType went from 3 to 4 digits) + ** parameters : delta Z prime = 1.00 cm - delta Z pitch = 0.15 cm + ** v19j: use overlap and distance parameters from CAD model + ** v19h: put STS stations from v19d at z-positions = 260; 365; 470; 575; 680; 785; 890; 995 mm + ** v19g: place a box with services around v19e + ** v19f: place a box with services around v19d + ** v19e: increase spacing between stations by +10 mm from 100 mm + ** v19d: increase spacing between stations by + 5 mm from 100 mm + ** v19c: drop station 8 and increase spacing between remaining 7 stations from 10 cm to 12 c + ** v19b: introduce FEB orientation in ladder numbering (LadderType went from 2 to 3 digits) + ** v19a: import passive materials from gdml file + ** extend CF ladder structures and cables towards FEE plane + ** change CF ladder frame shape + ** v18d: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu (based on v18b) + ** v18c: fixed cut-out windows in cooling plates, improve the box shape/materials + ** v18b: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu + ** v18a: adds 9 cooling/holding plates and a box around the setup + ** v16g: v16g is the new standard geometry from November 2017 + ** v16g: switch from stations to units - left / right ("Unit01L", "Unit01R") + ** v16f: switch from stations to units + ** - split in upstream / downstream and left / right parts + ** - named Unit0xUR, Unit0xUL, Unit0xDR, Unit0xDL + ** v16e: switch from stations to units - upstream / downstream ("Unit01U", "Unit01D") + ** v16d: skip keeping volumes of sts and stations + ** v16c: like v16b, but senors of ladders beampipe next to beampipe + ** shifted closer to the pipe, like in the CAD model + ** v16b: like v16a, but yellow sensors removed + ** v16a: derived from v15c (no cones), but with sensor types renamed: + ** 2 -> 1, 3 -> 2, 4 -> 3, 5 -> 4, 1 -> 5 + ** + ** v15c: as v15b without cones + ** v15b: introduce modified carbon ladders from v13z + ** v15a: with flipped ladder orientation for stations 0,2,4,6 to match CAD design + ** + ** TODO: + ** + ** DONE: + ** v15b - use carbon macaroni as ladder support + ** v15b - introduce a small gap between lowest sensor and carbon ladder + ** v15b - build small cones for the first 2 stations + ** v15b - within a station the ladders of adjacent units should not touch eachother - set gkLadderGapZ to 10 mm + ** v15b - for all ladders set an even number of ladder elements + ** v15b - z offset of cones to ladders should not be 0.3 by default, but 0.26 + ** v15b - within a station the ladders should be aligned in z, defined either by the unit or the ladder with most sensors + ** v15b - get rid of cone overlap in stations 7 and 8 - done by adapting rHole size + ** + ** The geometry hierarachy is: + ** + ** 1. Sensors (see function CreateSensors) + ** The sensors are the active volumes and the lowest geometry level. + ** They are built as TGeoVolumes, shape box, material silicon. + ** x size is determined by strip pitch 58 mu and 1024 strips + ** plus guard ring of 1.3 mm at each border -> 6.1992 cm. + ** Sensor type 1 is half of that (3.0792 cm). + ** y size is determined by strip length (2.2 / 4.2 / 6.3 cm) plus + ** guard ring of 1.3 mm at top and bottom -> 2.46 / 4.46 / 6.46 cm. + ** z size is a parameter, to be set by gkSensorThickness. + ** + ** 2. Sectors (see function CreateSectors) + ** Sectors consist of several chained sensors. These are arranged + ** vertically on top of each other with a gap to be set by + ** gkChainGapY. Sectors are constructed as TGeoVolumeAssembly. + ** The sectors are auxiliary volumes used for proper placement + ** of the sensor(s) in the module. They do not show up in the + ** final geometry. + ** + ** 3. Modules (see function ConstructModule) + ** A module is a readout unit, consisting of one sensor or + ** a chain of sensors (see sector) and a cable. + ** The cable extends from the top of the sector vertically to the + ** top of the halfladder the module is placed in. The cable and module + ** volume thus depend on the vertical position of the sector in + ** the halfladder. The cables consist of silicon with a thickness to be + ** set by gkCableThickness. + ** Modules are constructed as TGeoVolume, shape box, medium gStsMedium. + ** The module construction can be switched off (gkConstructCables) + ** to reproduce older geometries. + ** + ** 4. Halfladders (see function ConstructHalfLadder) + ** A halfladder is a vertical assembly of several modules. The modules + ** are placed vertically such that their sectors overlap by + ** gkSectorOverlapY. They are displaced in z direction to allow for the + ** overlap in y by gkSectorGapZ. + ** The horizontal placement of modules in the halfladder can be choosen + ** to left aligned or right aligned, which only matters if sensors of + ** different x size are involved. + ** Halfladders are constructed as TGeoVolumeAssembly. + ** + ** 5. Ladders (see function CreateLadders and ConstructLadder) + ** A ladder is a vertical assembly of two halfladders, and is such the + ** vertical building block of a station. The second (bottom) half ladder + ** is rotated upside down. The vertical arrangement is such that the + ** inner sectors of the two halfladders have the overlap gkSectorOverlapY + ** (function CreateLadder) or that there is a vertical gap for the beam + ** hole (function CreateLadderWithGap). + ** Ladders are constructed as TGeoVolumeAssembly. + ** + ** 6. Stations (see function ConstructStation) + ** A station represents one layer of the STS geometry: one measurement + ** at (approximately) a given z position. It consist of several ladders + ** arranged horizontally to cover the acceptance. + ** The ladders are arranged such that there is a horizontal overlap + ** between neighbouring ladders (gkLadderOverLapX) and a vertical gap + ** to allow for this overlap (gkLadderGapZ). Each second ladder is + ** rotated around its y axis to face away from or into the beam. + ** Stations are constructed as TGeoVolumes, shape box minus tube (for + ** the beam hole), material gStsMedium. + ** + ** 7. STS + ** The STS is a volume hosting the entire detectors system. It consists + ** of several stations located at different z positions. + ** The STS is constructed as TGeoVolume, shape box minus cone (for the + ** beam pipe), material gStsMedium. The size of the box is computed to + ** enclose all stations. + *****************************************************************************/ + + +// Remark: With the proper steering variables, this should exactly reproduce +// the geometry version v11b of A. Kotynia's described in the ASCII format. +// The only exception is a minimal difference in the z position of the +// sectors/sensors. This is because of ladder types 2 and 4 containing the half +// sensors around the beam hole (stations 1,2 and 3). In v11b, the two ladders +// covering the beam hole cannot be transformed into each other by rotations, +// but only by a reflection. This means they are constructionally different. +// To avoid introducing another two ladder types, the difference in z position +// was accepted. + + +// Differences to v12: +// gkChainGap reduced from 1 mm to 0 +// gkCableThickness increased from 100 mum to 200 mum (2 cables per module) +// gkSectorOverlapY reduced from 3 mm to 2.4 mm +// New sensor types 05 and 06 +// New sector types 07 and 08 +// Re-definiton of ladders (17 types instead of 8) +// Re-definiton of station from new ladders + + +#include <iomanip> +#include <iostream> +#include "TGeoManager.h" + +#include "TGeoTube.h" +#include "TGeoPara.h" +#include "TGeoCone.h" +#include "TGeoTrd2.h" +#include "TGeoCompositeShape.h" +#include "TGeoXtru.h" +#include "TGeoPhysicalNode.h" + +// forward declarations +Int_t CreateSensors(); +Int_t CreateSectors(); +Int_t CreateLadders(); +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength); +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY, + Int_t start); +TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ, + Double_t pitchZ, + Int_t nSectors); +TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation); +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile); +void PostProcessGdml(TGeoVolume* gdmlTop); +void CheckVolume(TGeoVolume* volume); +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren = kTRUE); +Double_t BeamPipeRadius(Double_t z); +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x); +TGeoVolume* ConstructSmallCone(Double_t coneDz); +TGeoVolume* ConstructBigCone(Double_t coneDz); + +// ------------- Version highlight ----------------------------------- + +const std::string gVersionHighlight = R"( +Summary: + This version adds passive materials imported from GDML model to the STS geometry: + * Taken from and largely correspond to mechanical CAD drawings of the detector + * Thermal insulation box: + - made out of carbon sandwitch panel (2mm carbon fiber sheet + layer of carbon foam + 2mm carbon fiber sheet) + - front window of complex shape with interface to MVD / target chamber + - back window with large aperture (2000 x 1200 mm) square cut into carbon foam + * Structural units: + - made of 2 complex shape aluminum C-Frames, 15mm thick + - placed at 25, 35, ... ,105 cm absolute Z + - contain front-end and power distribution boxes with equivalent X_0 values + + Scripted geometry tweaks: + * Ladders and cables are extended towards the read-out planes having same lengths in respective rows + * Adjusted form and shape of carbon ladder structures from L-type to X-type + * Reduced verbosity of this file + + Sensor arrangement is the same as in version v16g + + !! Important for this version is the discrepancy from the mechanical CAD w.r.t. front wall. + The square window was replaced by a round one to avoid overlaps with present beam pipe designs, e.g. pipe_v16b_1e +)"; + +// ------------- Steering variables ----------------------------------- + +// ---> Horizontal width of sensors [cm] +const Double_t gkSensorSizeX = 6.2; // was 6.2092; // 6.2 - Oleg CAD 15/05/2020 + +// ---> Thickness of sensors [cm] +const Double_t gkSensorThickness = 0.03; + +// ---> Vertical gap between chained sensors [cm] +const Double_t gkChainGapY = 0.00; + +// ---> Thickness of cables [cm] +const Double_t gkCableThickness = 0.02; + +// ---> Horizontal overlap of neighbouring ladders [cm] +const Double_t gkLadderOverlapX = 0.25; // delta X - Oleg CAD 14/05/2020 + +// ---> Vertical overlap of neighbouring sectors in a ladder [cm] +const Double_t gkSectorOverlapY = 0.46; // delta Y - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring sectors in a ladder [cm] +const Double_t gkSectorGapZ = 0.12; // gap + thickness = pitch // delta Z pitch = 0.15 - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring ladders [cm] +const Double_t gkLadderGapZ = 0.50 - 0.15; // for asym // 0.5 for sym // delta Z prime + +// ---> Gap in z between lowest sector to carbon support structure [cm] +const Double_t gkSectorGapZFrame = 0.280 - 0.025; // Oleg CAD 05/05/2020 // there is a 2.8 mm gap between the bottom side of the sensor and the top ledge of the carbon ladder + +// ---> Switch to construct / not to construct readout cables +const Bool_t gkConstructCables = kTRUE; + +// ---> Switch to construct / not to construct frames +const Bool_t gkConstructCones = kFALSE; // kTRUE; // switch this false by default for v15c and v16x +const Bool_t gkConstructFrames = kTRUE; // kFALSE; // switch this true by default for v15c and v16x +const Bool_t gkConstructSmallFrames = kTRUE; // kFALSE; +const Bool_t gkCylindricalFrames = kTRUE; // kFALSE; + +// ---> Size of the frame +const Double_t gkFrameThickness = 0.2; +const Double_t gkThinFrameThickness = 0.05; +const Double_t gkFrameStep = 4.0; // size of frame cell along y direction + +const Double_t gkCylinderDiaInner = 0.07; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) +const Double_t gkCylinderDiaOuter = 0.15; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) + +// ---> Switch to import / not to import the Passive materials from GDML file +//const Bool_t gkImportPassive = kTRUE; +const Bool_t gkImportPassive = kFALSE; + +// ---------------------------------------------------------------------------- + + +// -------------- Parameters of beam pipe in the STS region -------------- +// ---> Needed to compute stations and STS such as to avoid overlaps +const Double_t gkPipeZ1 = 22.0; +const Double_t gkPipeR1 = 1.8; +const Double_t gkPipeZ2 = 50.0; +const Double_t gkPipeR2 = 1.8; +const Double_t gkPipeZ3 = 125.0; +const Double_t gkPipeR3 = 5.5; + +//DE const Double_t gkPipeZ1 = 27.0; +//DE const Double_t gkPipeR1 = 1.05; +//DE const Double_t gkPipeZ2 = 160.0; +//DE const Double_t gkPipeR2 = 3.25; +// ---------------------------------------------------------------------------- + +//TString unitName[16] = // names of units for v16e +// { "Unit00D", +// "Unit01U", "Unit01D", +// "Unit02U", "Unit02D", +// "Unit03U", "Unit03D", +// "Unit04U", "Unit04D", +// "Unit05U", "Unit05D", +// "Unit06U", "Unit06D", +// "Unit07U", "Unit07D", +// "Unit08U" }; + +//TString unitName[32] = // names of units for v16f +// { "Unit00DR", "Unit00DL", +// "Unit01UR", "Unit01UL", "Unit01DR", "Unit01DL", +// "Unit02UR", "Unit02UL", "Unit02DR", "Unit02DL", +// "Unit03UR", "Unit03UL", "Unit03DR", "Unit03DL", +// "Unit04UR", "Unit04UL", "Unit04DR", "Unit04DL", +// "Unit05UR", "Unit05UL", "Unit05DR", "Unit05DL", +// "Unit06UR", "Unit06UL", "Unit06DR", "Unit06DL", +// "Unit07UR", "Unit07UL", "Unit07DR", "Unit07DL", +// "Unit08UR", "Unit08UL" }; + +TString unitName[32] = // names of units for v16g - while merging D and U parts + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", "Unit01R", "Unit01L", + "Unit02R", "Unit02L", "Unit02R", "Unit02L", + "Unit03R", "Unit03L", "Unit03R", "Unit03L", + "Unit04R", "Unit04L", "Unit04R", "Unit04L", + "Unit05R", "Unit05L", "Unit05R", "Unit05L", + "Unit06R", "Unit06L", "Unit06R", "Unit06L", + "Unit07R", "Unit07L", "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +TString unitName18[18] = // names of units for v16g + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", + "Unit02R", "Unit02L", + "Unit03R", "Unit03L", + "Unit04R", "Unit04L", + "Unit05R", "Unit05L", + "Unit06R", "Unit06L", + "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +// ------------- Other global variables ----------------------------------- +// ---> STS medium (for every volume except silicon) +TGeoMedium* gStsMedium = NULL; // will be set later +// ---> TGeoManager (too lazy to write out 'Manager' all the time +TGeoManager* gGeoMan = NULL; // will be set later +// ---------------------------------------------------------------------------- + + + + +// ============================================================================ +// ====== Main function ===== +// ============================================================================ + +void create_stsgeo_v19s(const char* geoTag="v19s") +{ + + // ------- Geometry file name (output) ---------------------------------- + TString geoFileName = "sts_"; + geoFileName = geoFileName + geoTag + ".geo.root"; + // -------------------------------------------------------------------------- + + + // ------- Open info file ----------------------------------------------- + TString infoFileName = geoFileName; + infoFileName.ReplaceAll("root", "info"); + fstream infoFile; + infoFile.open(infoFileName.Data(), fstream::out); + infoFile << "STS geometry created with create_stsgeo_v19s.C" << endl; + infoFile << gVersionHighlight << endl; + infoFile << "Global variables: " << endl; + infoFile << "Sensor thickness = " << gkSensorThickness << " cm" << endl; + infoFile << "Vertical gap in sensor chain = " + << gkChainGapY << " cm" << endl; + infoFile << "Vertical overlap of sensors = " + << gkSectorOverlapY << " cm" << endl; + infoFile << "Gap in z between neighbour sensors = " + << gkSectorGapZ << " cm" << endl; + infoFile << "Horizontal overlap of sensors = " + << gkLadderOverlapX << " cm" << endl; + infoFile << "Gap in z between neighbour ladders = " + << gkLadderGapZ << " cm" << endl; + if ( gkConstructCables ) + infoFile << "Cable thickness = " << gkCableThickness << " cm" << endl; + else + infoFile << "No cables" << endl; + infoFile << endl; + infoFile << "Beam pipe: R1 = " << gkPipeR1 << " cm at z = " + << gkPipeZ1 << " cm" << endl; + infoFile << "Beam pipe: R2 = " << gkPipeR2 << " cm at z = " + << gkPipeZ2 << " cm" << endl; + infoFile << "Beam pipe: R3 = " << gkPipeR3 << " cm at z = " + << gkPipeZ3 << " cm" << endl; + // -------------------------------------------------------------------------- + + + // ------- Load media from media file ----------------------------------- + FairGeoLoader* geoLoad = new FairGeoLoader("TGeo","FairGeoLoader"); + FairGeoInterface* geoFace = geoLoad->getGeoInterface(); + TString geoPath = gSystem->Getenv("VMCWORKDIR"); + TString medFile = geoPath + "/geometry/media.geo"; + geoFace->setMediaFile(medFile); + geoFace->readMedia(); + gGeoMan = gGeoManager; + // -------------------------------------------------------------------------- + + + // ----------------- Get and create the required media ----------------- + FairGeoMedia* geoMedia = geoFace->getMedia(); + FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder(); + + // ---> air + FairGeoMedium* mAir = geoMedia->getMedium("air"); + if ( ! mAir ) Fatal("Main", "FairMedium air not found"); + geoBuild->createMedium(mAir); + TGeoMedium* air = gGeoMan->GetMedium("air"); + if ( ! air ) Fatal("Main", "Medium air not found"); + + // ---> silicon + FairGeoMedium* mSilicon = geoMedia->getMedium("silicon"); + if ( ! mSilicon ) Fatal("Main", "FairMedium silicon not found"); + geoBuild->createMedium(mSilicon); + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + if ( ! silicon ) Fatal("Main", "Medium silicon not found"); + + // ---> silicon1 + FairGeoMedium* mSilicon1 = geoMedia->getMedium("silicon1"); + // FairGeoMedium* mSilicon1 = geoMedia->getMedium("silicon"); + if ( ! mSilicon1 ) Fatal("Main", "FairMedium silicon1 not found"); + geoBuild->createMedium(mSilicon1); + TGeoMedium* silicon1 = gGeoMan->GetMedium("silicon1"); + if ( ! silicon1 ) Fatal("Main", "Medium silicon1 not found"); + +// // ---> silicon2 +// FairGeoMedium* mSilicon2 = geoMedia->getMedium("silicon2"); +// // FairGeoMedium* mSilicon2 = geoMedia->getMedium("silicon"); +// if ( ! mSilicon2 ) Fatal("Main", "FairMedium silicon2 not found"); +// geoBuild->createMedium(mSilicon2); +// TGeoMedium* silicon2 = gGeoMan->GetMedium("silicon2"); +// if ( ! silicon2 ) Fatal("Main", "Medium silicon2 not found"); + + // ---> carbon + FairGeoMedium* mCarbon = geoMedia->getMedium("carbon"); + if ( ! mCarbon ) Fatal("Main", "FairMedium carbon not found"); + geoBuild->createMedium(mCarbon); + TGeoMedium* carbon = gGeoMan->GetMedium("carbon"); + if ( ! carbon ) Fatal("Main", "Medium carbon not found"); + + // ---> STSBoxCarbonFoam + FairGeoMedium* mSTSBoxCarbonFoam = geoMedia->getMedium("STSBoxCarbonFoam"); + if ( ! mSTSBoxCarbonFoam ) Fatal("Main", "FairMedium STSBoxCarbonFoam not found"); + geoBuild->createMedium(mSTSBoxCarbonFoam); + TGeoMedium* STSBoxCarbonFoam = gGeoMan->GetMedium("STSBoxCarbonFoam"); + if ( ! STSBoxCarbonFoam ) Fatal("Main", "Medium STSBoxCarbonFoam not found"); + + // ---> STSBoxCarbonFibre + FairGeoMedium* mSTSBoxCarbonFibre = geoMedia->getMedium("STSBoxCarbonFibre"); + if ( ! mSTSBoxCarbonFibre ) Fatal("Main", "FairMedium STSBoxCarbonFibre not found"); + geoBuild->createMedium(mSTSBoxCarbonFibre); + TGeoMedium* STSBoxCarbonFibre = gGeoMan->GetMedium("STSBoxCarbonFibre"); + if ( ! STSBoxCarbonFibre ) Fatal("Main", "Medium STSBoxCarbonFibre not found"); + + // ---> STScable + FairGeoMedium* mSTScable = geoMedia->getMedium("STScable"); + if ( ! mSTScable ) Fatal("Main", "FairMedium STScable not found"); + geoBuild->createMedium(mSTScable); + TGeoMedium* STScable = gGeoMan->GetMedium("STScable"); + if ( ! STScable ) Fatal("Main", "Medium STScable not found"); + + // ---> Aluminium + FairGeoMedium* mAluminium = geoMedia->getMedium("aluminium"); + if ( ! mAluminium ) Fatal("Main", "FairMedium aluminium not found"); + geoBuild->createMedium(mAluminium); + TGeoMedium* aluminium = gGeoMan->GetMedium("aluminium"); + if ( ! aluminium ) Fatal("Main", "Medium aluminium not found"); + + // --- + gStsMedium = air; + // -------------------------------------------------------------------------- + + + // -------------- Create geometry and top volume ------------------------- + gGeoMan = (TGeoManager*)gROOT->FindObject("FAIRGeom"); +// gGeoMan->SetName("STSgeom"); + TGeoVolume* top = new TGeoVolumeAssembly("top"); +// TGeoBBox* topbox= new TGeoBBox("", 120., 120., 120.); +// TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air")); + gGeoMan->SetTopVolume(top); + // -------------------------------------------------------------------------- + + + // -------------- Create media ------------------------------------------ + /* + cout << endl; + cout << "===> Creating media...."; + cout << CreateMedia(); + cout << " media created" << endl; + TList* media = gGeoMan->GetListOfMedia(); + for (Int_t iMedium = 0; iMedium < media->GetSize(); iMedium++ ) { + cout << "Medium " << iMedium << ": " + << ((TGeoMedium*) media->At(iMedium))->GetName() << endl; + } + gStsMedium = gGeoMan->GetMedium("air"); + if ( ! gStsMedium ) Fatal("Main", "medium sts_air not found"); + */ + // -------------------------------------------------------------------------- + + + // --------------- Create sensors --------------------------------------- + cout << endl << endl; + cout << "===> Creating sensors...." << endl << endl; + infoFile << endl << "Sensors: " << endl; + Int_t nSensors = CreateSensors(); + for (Int_t iSensor = 1; iSensor <= nSensors; iSensor++) { + TString name = Form("Sensor%02d",iSensor); + TGeoVolume* sensor = gGeoMan->GetVolume(name); + TString name2 = Form("Sensor%02d",iSensor+10); + TGeoVolume* sensor2 = gGeoMan->GetVolume(name2); + + // add color to sensors + if (iSensor == 1) + sensor->SetLineColor(kRed); + if (iSensor == 1) + sensor2->SetLineColor(kBlue); + + if (iSensor == 2) + sensor->SetLineColor(kRed); + if (iSensor == 2) + sensor2->SetLineColor(kBlue); + + if (iSensor == 3) + sensor->SetLineColor(kRed); + if (iSensor == 3) + sensor2->SetLineColor(kBlue); + + if (iSensor == 4) + sensor->SetLineColor(kRed); + if (iSensor == 4) + sensor2->SetLineColor(kBlue); +/* + // add color to sensors + if (iSensor == 1) + sensor->SetLineColor(kRed-7); + if (iSensor == 1) + sensor2->SetLineColor(kBlue-7); + + if (iSensor == 2) + sensor->SetLineColor(kGreen); + if (iSensor == 2) + sensor2->SetLineColor(kOrange); + + if (iSensor == 3) + sensor2->SetLineColor(kRed); + if (iSensor == 3) + sensor->SetLineColor(kBlue); + + if (iSensor == 4) + sensor->SetLineColor(kMagenta); + if (iSensor == 4) + sensor2->SetLineColor(kAzure); +*/ +// if (iSensor == 5) +// sensor->SetLineColor(kYellow); +// if (iSensor == 6) +// sensor->SetLineColor(kYellow); +// if (iSensor == 7) +// sensor->SetLineColor(kYellow); + +// sensor = gGeoMan->GetVolume(name); +// if (iSensor == 11) +// sensor->SetLineColor(kRed); +// if (iSensor == 12) +// sensor->SetLineColor(kGreen); +// if (iSensor == 13) +// sensor->SetLineColor(kRed); +// if (iSensor == 14) +// sensor->SetLineColor(kAzure); + + + + CheckVolume(sensor); + CheckVolume(sensor, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create sectors -------------------------------------- + cout << endl << endl; + cout << "===> Creating sectors...." << endl; + // infoFile << endl << "Sectors: " << endl; + Int_t nSectors = CreateSectors(); + for (Int_t iSector = 1; iSector <= nSectors; iSector++) { + // cout << endl; + TString name = Form("Sector%02d", iSector); + TGeoVolume* sector = gGeoMan->GetVolume(name); + CheckVolume(sector); + // CheckVolume(sector, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create ladders -------------------------------------- + cout << endl << endl; + cout << "===> Creating ladders...." << endl; + infoFile << endl << "Ladders:" << endl; + + TString name = ""; + TGeoVolume* ladder; + + + Int_t nLadders = CreateLadders(); + + for (Int_t iLadder = 1; iLadder <= nLadders; iLadder++) { + cout << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType0%02d", iLadder); // v19b + name = Form("LadderType00%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF1: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType1%02d", iLadder); // v19b + name = Form("LadderType01%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF2: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType10%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF3: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType11%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF4: ladder name: " << name << endl << endl; + } + // -------------------------------------------------------------------------- + + + // ---------------- Create cones ---------------------------------------- + Double_t coneDz = 1.64; + TGeoVolume* coneSmallVolum = ConstructSmallCone(coneDz); + if (!coneSmallVolum) Fatal("ConstructSmallCone", "Volume Cone not found"); + TGeoVolume* coneBigVolum = ConstructBigCone(coneDz); + if (!coneBigVolum) Fatal("ConstructBigCone", "Volume Cone not found"); + // -------------------------------------------------------------------------- + + + // ---------------- Create stations ------------------------------------- + cout << endl << endl; + cout << "===> Creating stations...." << endl; + infoFile << endl << "Stations: " << endl; + Int_t angle = 0; + nLadders = 0; + Int_t ladderTypes[16]; // there are max 16 ladders in one layer + TGeoTranslation* statTrans = NULL; + + TGeoVolume *myunit[32]; // units + +// Int_t statPos[8] = { 30, 40, 50, 60, 70, 80, 90, 100 }; // z positions of stations +// Int_t statPos[16] = { 28, 32, 38, 42, 48, 52, 58, 62, +// 68, 72, 78, 82, 88, 92, 98,102 }; // z positions of units +// Int_t statPos[16] = { 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units +// Int_t statPos18[18] = { 30, 30, // expanded for placement of Unit00 +// 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units + // v19h + Double_t statPos[16] = { 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of units + Double_t statPos18[18] = { 26.0, 26.0, // expanded for placement of Unit00 + 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of unit + +// // v19d +// Double_t statPos[16] = { 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units +// Double_t statPos18[18] = { 30.0, 30.0, // expanded for placement of Unit00 +// 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units + +////Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.9 , 3.7 , 3.7 , 4.2 , 4.2 }; // size of cutouts in stations +// Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.43, 3.04, 3.35, 3.96, 4.2 }; // size of cutouts in stations, derived from gapXYZ[x][1]/2 + + Int_t cone_size[8] = { 0, 0, 0, 1, 1, 1, 1, 1 }; // size of cones: 0 = small, 1 = large + + Double_t cone_offset[2] = { 0.305, 0.285 }; + +// Int_t allLadderTypes[8][16]= +// { { -1, -1, -1, -1, 10, 109, 9, 101, 1, 109, 9, 110, -1, -1, -1, -1 }, // station 1 +// { -1, -1, 111, 10, 110, 9, 109, 2, 102, 9, 109, 10, 110, 11, -1, -1 }, // station 2 +// { -1, -1, 14, 113, 12, 112, 12, 103, 3, 112, 12, 112, 13, 114, -1, -1 }, // station 3 +// { -1, 15, 114, 13, 112, 12, 112, 4, 104, 12, 112, 12, 113, 14, 115, -1 }, // station 4 +// { -1, 119, 18, 117, 17, 116, 16, 105, 5, 116, 16, 117, 17, 118, 19, -1 }, // station 5 +// { -1, 19, 118, 17, 117, 16, 116, 6, 106, 16, 116, 17, 117, 18, 119, -1 }, // station 6 +// { 21, 119, 18, 120, 20, 120, 20, 107, 7, 120, 20, 120, 20, 118, 19, 121 }, // station 7 +// { 119, 17, 123, 22, 122, 22, 122, 8, 108, 22, 122, 22, 122, 23, 117, 19 } }; // station 8 + +//============================================================================================== + +// explanation: type xyzz +// where x = carbon ladder orientation +// where y = FEB box orientation +// where zz = sensor arrangement on ladder +// with FEB orientation - v19b + Int_t allUnitTypes[16][16]= + { { -1, -1, -1, -1, 10, 0, 9, 0, 101, 0, 109, 0, -1, -1, -1, -1 }, // unit00D Station01 00 + { -1, -1, -1, -1, 0, 1109, 0, 1101, 0, 1009, 0, 1010, -1, -1, -1, -1 }, // unit01U Station01 01 + + { -1, -1, 0, 10, 0, 9, 0, 2, 0, 109, 0, 110, 0, 111, -1, -1 }, // unit01D Station02 02 + { -1, -1, 1111, 0, 1110, 0, 1109, 0, 1002, 0, 1009, 0, 1010, 0, -1, -1 }, // unit02U Station02 03 + + { -1, -1, 14, 0, 12, 0, 12, 0, 103, 0, 112, 0, 113, 0, -1, -1 }, // unit02D Station03 04 + { -1, -1, 0, 1113, 0, 1112, 0, 1103, 0, 1012, 0, 1012, 0, 1014, -1, -1 }, // unit03U Station03 05 + + { -1, 15, 0, 13, 0, 12, 0, 4, 0, 112, 0, 112, 0, 114, 0, -1 }, // unit03D Station04 06 + { -1, 0, 1114, 0, 1112, 0, 1112, 0, 1004, 0, 1012, 0, 1013, 0, 1015, -1 }, // unit04U Station04 07 + + { -1, 0, 18, 0, 17, 0, 16, 0, 105, 0, 116, 0, 117, 0, 119, -1 }, // unit04D Station05 08 + { -1, 1119, 0, 1117, 0, 1116, 0, 1105, 0, 1016, 0, 1017, 0, 1018, 0, -1 }, // unit05U Station05 09 + + { -1, 19, 0, 17, 0, 16, 0, 6, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05D Station06 10 + { -1, 0, 1118, 0, 1117, 0, 1116, 0, 1006, 0, 1016, 0, 1017, 0, 1019, -1 }, // unit06U Station06 11 + + { 21, 0, 25, 0, 20, 0, 20, 0, 107, 0, 120, 0, 120, 0, 127, 0 }, // unit06D Station07 12 + { 0, 1127, 0, 1120, 0, 1120, 0, 1107, 0, 1020, 0, 1020, 0, 1025, 0, 1021 }, // unit07U Station07 13 + + { 0, 24, 0, 22, 0, 22, 0, 8, 0, 122, 0, 122, 0, 123, 0, 126 }, // unit07D Station08 14 + { 1126, 0, 1123, 0, 1122, 0, 1122, 0, 1008, 0, 1022, 0, 1022, 0, 1024, 0 } }; // unit08U Station08 15 + +//============================================================================================== + +// without FEB orientation - v19a +// v19a Int_t allUnitTypes[16][16]= +// v19a { { -1, -1, -1, -1, 10, 0, 9, 0, 1, 0, 9, 0, -1, -1, -1, -1 }, // unit00D Station01 00 +// v19a { -1, -1, -1, -1, 0, 109, 0, 101, 0, 109, 0, 110, -1, -1, -1, -1 }, // unit01U Station01 01 +// v19a { -1, -1, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, -1, -1 }, // unit01D Station02 02 +// v19a { -1, -1, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, -1, -1 }, // unit02U Station02 03 +// v19a { -1, -1, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, -1, -1 }, // unit02D Station03 04 +// v19a { -1, -1, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, -1, -1 }, // unit03U Station03 05 +// v19a { -1, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, -1 }, // unit03D Station04 06 +// v19a { -1, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, -1 }, // unit04U Station04 07 +// v19a { -1, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, -1 }, // unit04D Station05 08 +// v19a { -1, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05U Station05 09 +// v19a { -1, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, -1 }, // unit05D Station06 10 +// v19a { -1, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, -1 }, // unit06U Station06 11 +// v19a { 21, 0, 25, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 27, 0 }, // unit06D Station07 12 +// v19a { 0, 127, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 125, 0, 121 }, // unit07U Station07 13 +// v19a { 0, 24, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 26 }, // unit07D Station08 14 +// v19a { 126, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 124, 0 } }; // unit08U Station08 15 + + +// unitTypes[0] = { 0, 0, 0, 0, 10, 0, 9, 0, 1, 0, 9, 0, 0, 0, 0, 0 }; // unit 0D +// unitTypes[1] = { 0, 0, 0, 0, 0, 109, 0, 101, 0, 109, 0, 110, 0, 0, 0, 0 }; // unit 1U +// unitTypes[2] = { 0, 0, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, 0, 0 }; // unit 1D +// unitTypes[3] = { 0, 0, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, 0, 0 }; // unit 2U +// unitTypes[4] = { 0, 0, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, 0, 0 }; // unit 2D +// unitTypes[5] = { 0, 0, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, 0, 0 }; // unit 3U +// unitTypes[6] = { 0, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, 0 }; // unit 3D +// unitTypes[7] = { 0, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, 0 }; // unit 4U +// unitTypes[8] = { 0, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, 0 }; // unit 4D +// unitTypes[9] = { 0, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, 0 }; // unit 5U +// unitTypes[10] = { 0, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, 0 }; // unit 5D +// unitTypes[11] = { 0, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, 0 }; // unit 6U +// unitTypes[12] = { 21, 0, 18, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 19, 0 }; // unit 6D +// unitTypes[13] = { 0, 119, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 118, 0, 121 }; // unit 7U +// unitTypes[14] = { 0, 17, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 19 }; // unit 7D +// unitTypes[15] = { 119, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 117, 0 }; // unit 8U + + +// // generate unit +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) +// for (Int_t iLadder = 0; iLadder < 16; iLadder++) +// { +// allUnitTypes[iUnit][iLadder] = 0; +// if ((iUnit % 2 == 0) && (allLadderTypes[iUnit/2][iLadder] < 100)) // if carbon structure is oriented upstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// if ((iUnit % 2 == 1) && (allLadderTypes[iUnit/2][iLadder] >= 100)) // if carbon structure is oriented downstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// } + + + // dump unit + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << "DE unitTypes[" << iUnit << "] = { "; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + { + cout << allUnitTypes[iUnit][iLadder]; + if (iLadder < 15) + cout << ", "; + else + cout << " };"; + } + cout << endl; + } + + + // --- Units 01 - 16 + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << endl; + + nLadders = 0; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + if (allUnitTypes[iUnit][iLadder] >= 0) + { + ladderTypes[nLadders] = allUnitTypes[iUnit][iLadder]; + cout << "DE ladderTypes[" << nLadders << "] = " << allUnitTypes[iUnit][iLadder] << ";" << endl; + nLadders++; + } + myunit[iUnit*2+0] = ConstructUnit(0, iUnit*2+0, nLadders, ladderTypes, iUnit/2+1); + myunit[iUnit*2+1] = ConstructUnit(1, iUnit*2+1, nLadders, ladderTypes, iUnit/2+1); + +// if (gkConstructCones) { +// if (iUnit%2 == 0) +// angle = 90; +// else +// angle = -90; +// +// // upstream +// TGeoRotation* coneRot11 = new TGeoRotation; +// coneRot11->RotateZ(angle); +// coneRot11->RotateY(180); +// TGeoCombiTrans* conePosRot11 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-cone_offset[cone_size[iUnit]]-gkLadderGapZ/2., coneRot11); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 1, conePosRot11); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 1, conePosRot11); +// +// // downstream +// TGeoRotation* coneRot12 = new TGeoRotation; +// coneRot12->RotateZ(angle); +// TGeoCombiTrans* conePosRot12 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+cone_offset[cone_size[iUnit]]+gkLadderGapZ/2., coneRot12); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 2, conePosRot12); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 2, conePosRot12); +// +// myunit[iUnit]->GetShape()->ComputeBBox(); +// } + +// CheckVolume(myunit[iUnit]); +// CheckVolume(myunit[iUnit], infoFile); + if ((iUnit%2 == 0)||(iUnit == 15)) + { + CheckVolume(myunit[iUnit*2+0]); + CheckVolume(myunit[iUnit*2+0], infoFile); + CheckVolume(myunit[iUnit*2+1]); + CheckVolume(myunit[iUnit*2+1], infoFile); + } + infoFile << "Position z = " << statPos[iUnit] << endl; + } + // -------------------------------------------------------------------------- + + + // --------------- Create STS volume ------------------------------------ + cout << endl << endl; + cout << "===> Creating STS...." << endl; + +// // --- Determine size of STS box +// Double_t stsX = 0.; +// Double_t stsY = 0.; +// Double_t stsZ = 0.; +// Double_t stsBorder = 2*5.; // 5 cm space for carbon ladders on each side +// for (Int_t iStation = 1; iStation<=8; iStation++) { +// TString statName = Form("Station%02d", iStation); +// TGeoVolume* station = gGeoMan->GetVolume(statName); +// TGeoBBox* shape = (TGeoBBox*) station->GetShape(); +// stsX = TMath::Max(stsX, 2.* shape->GetDX() ); +// stsY = TMath::Max(stsY, 2.* shape->GetDY() ); +// cout << "Station " << iStation << ": Y " << stsY << endl; +// } +// // --- Some border around the stations +// stsX += stsBorder; +// stsY += stsBorder; +// stsZ = ( statPos[7] - statPos[0] ) + stsBorder; +// +// // --- Create box around the stations +// new TGeoBBox("stsBox", stsX/2., stsY/2., stsZ/2.); +// cout << "size of STS box: x " << stsX << " - y " << stsY << " - z " << stsZ << endl; +// +// // --- Create cone hosting the beam pipe +// // --- One straight section with constant radius followed by a cone +// Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +// Double_t z2 = gkPipeZ2; +// Double_t z3 = statPos[7] + 0.5 * stsBorder; // end of STS box +// Double_t r1 = BeamPipeRadius(z1); +// Double_t r2 = BeamPipeRadius(z2); +// Double_t r3 = BeamPipeRadius(z3); +// r1 += 0.01; // safety margin +// r2 += 0.01; // safety margin +// r3 += 0.01; // safety margin +// +// cout << endl; +// cout << z1 << " " << r1 << endl; +// cout << z2 << " " << r2 << endl; +// cout << z3 << " " << r3 << endl; +// +// cout << endl; +// cout << "station1 : " << BeamPipeRadius(statPos[0]) << endl; +// cout << "station2 : " << BeamPipeRadius(statPos[1]) << endl; +// cout << "station3 : " << BeamPipeRadius(statPos[2]) << endl; +// cout << "station4 : " << BeamPipeRadius(statPos[3]) << endl; +// cout << "station5 : " << BeamPipeRadius(statPos[4]) << endl; +// cout << "station6 : " << BeamPipeRadius(statPos[5]) << endl; +// cout << "station7 : " << BeamPipeRadius(statPos[6]) << endl; +// cout << "station8 : " << BeamPipeRadius(statPos[7]) << endl; +// +// // TGeoPcon* cutout = new TGeoPcon("stsCone", 0., 360., 3); // 2.*TMath::Pi(), 3); +// // cutout->DefineSection(0, z1, 0., r1); +// // cutout->DefineSection(1, z2, 0., r2); +// // cutout->DefineSection(2, z3, 0., r3); +// new TGeoTrd2("stsCone1", r1, r2, r1, r2, (z2-z1)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans1 = new TGeoTranslation("trans1", 0., 0., -(z3-z1)/2.+(z2-z1)/2.); +// trans1->RegisterYourself(); +// new TGeoTrd2("stsCone2", r2, r3, r2, r3, (z3-z2)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans2 = new TGeoTranslation("trans2", 0., 0., +(z3-z1)/2.-(z3-z2)/2.); +// trans2->RegisterYourself(); +// +////DE Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +////DE Double_t z2 = statPos[7] + 0.5 * stsBorder; // end of STS box +////DE Double_t slope = (gkPipeR2 - gkPipeR1) / (gkPipeZ2 - gkPipeZ1); +////DE Double_t r1 = gkPipeR1 + slope * (z1 - gkPipeZ1); // at start of STS +////DE Double_t r2 = gkPipeR1 + slope * (z2 - gkPipeZ1); // at end of STS +////DE r1 += 0.1; // safety margin +////DE r2 += 0.1; // safety margin +////DE // new TGeoCone("stsCone", stsZ/2., 0., r1, 0., r2); +////DE new TGeoTrd2("stsCone", r1, r2, r1, r2, stsZ/2.); + + + // // Create holding/cooling plates + // static std::vector< std::vector<Double_t> > plateSizes = { + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // }; + + // // 8-vertex cut-outs { minWidth, maxWidth, minHeight, maxHeight } + // static std::vector< std::vector<Double_t> > plateCutOuts = { + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 17.6, 47.6 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 49.0, 79.0 }, + // { 85.5,115.5, 51.5, 82.8 }, + // { 85.5,115.5, 59.0, 91.4 }, + // { 85.5,115.5, 68.0, 99.0 }, + // }; + + // for (Int_t iPlate = 0; iPlate < 9; iPlate++) { + // Int_t iUnit = iPlate * 2; + // TGeoBBox* outerPlate = new TGeoBBox(Form("outerPlate%02d",iPlate), + // plateSizes[iPlate][0], plateSizes[iPlate][1], plateSizes[iPlate][2]); + + // TGeoBBox* unitShapeR = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+0])->GetShape(); + // TGeoBBox* unitShapeL = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+1])->GetShape(); + + // Double_t maxDx = (unitShapeR->GetDX() + unitShapeL->GetDX()) / 2.; + // Double_t maxDy = TMath::Max(unitShapeR->GetDY(), unitShapeL->GetDY()); + // cout << maxDy << endl; + + // Double_t* cutOutX = new Double_t[8]; + // Double_t* cutOutY = new Double_t[8]; + + // cutOutX[0] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[0] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[1] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[1] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[2] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[2] = 1/2. * plateCutOuts[iPlate][2]; + // cutOutX[3] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[3] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[4] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[4] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[5] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[5] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[6] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[6] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[7] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[7] = 1/2. * plateCutOuts[iPlate][2]; + + // TGeoXtru* cutOutShape = new TGeoXtru(2); + // cutOutShape->SetName(Form("innerPlate%02d", iPlate)); + // cutOutShape->DefinePolygon(8, cutOutX, cutOutY); + // cutOutShape->DefineSection(0, -1*plateSizes[iPlate][2]-1e-7); + // cutOutShape->DefineSection(1, +1*plateSizes[iPlate][2]+1e-7); + + // TGeoShape* plateShape = new TGeoCompositeShape(Form("PlateShape%02d",iPlate), Form("outerPlate%02d-innerPlate%02d",iPlate,iPlate)); + // TGeoVolume* plate = new TGeoVolume(Form("Plate%02d", iPlate), plateShape, gGeoManager->GetMedium("aluminium")); + // plate->SetLineColor(kRed); + // plate->SetTransparency(65); + // plate->GetShape()->ComputeBBox(); + // } + + // --- Create STS volume + TString stsName = "sts_"; + stsName += geoTag; + +// TGeoShape* stsShape = new TGeoCompositeShape("stsShape", +// "stsBox-stsCone1:trans1-stsCone2:trans2"); +// TGeoVolume* sts = new TGeoVolume(stsName.Data(), stsShape, gStsMedium); + + Double_t stsBorder = 2 * 5.; + + TGeoVolume* sts = new TGeoVolumeAssembly(stsName.Data()); + + // --- Place stations in the STS + Double_t stsPosZ = 0.5 * ( statPos[15] + statPos[0] ); // todo units: update statPos[7] + // cout << "stsPosZ " << stsPosZ << " " << statPos[15] << " " << statPos[0] << "*****" << endl; + +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) { + for (Int_t iUnit = 0; iUnit < 18; iUnit++) { +// for (Int_t iUnit = 0; iUnit < 32; iUnit++) { + TGeoVolume* station = gGeoMan->GetVolume(unitName18[iUnit]); +// Double_t posZ = statPos[iUnit] - stsPosZ; + Double_t posZ = statPos18[iUnit] - stsPosZ; +// Double_t posZ = statPos[iUnit/2] - stsPosZ; + TGeoTranslation* trans = new TGeoTranslation(0., 0., posZ); + sts->AddNode(station, iUnit+1, trans); + sts->GetShape()->ComputeBBox(); + } + + // --- Import passive elements from GDML file + if (gkImportPassive) { + ImportPassive(sts, geoTag, infoFile); + } + + cout << endl; + CheckVolume(sts); + // -------------------------------------------------------------------------- + + + // --------------- Finish ----------------------------------------------- + TGeoTranslation* stsTrans = new TGeoTranslation(0., 0., stsPosZ); + top->AddNode(sts, 1, stsTrans); + top->GetShape()->ComputeBBox(); + cout << endl << endl; + + CheckVolume(top); + cout << endl << endl; + gGeoMan->CloseGeometry(); +// gGeoMan->CheckOverlaps(0.0001); +// gGeoMan->PrintOverlaps(); +// gGeoMan->CheckOverlaps(0.0001, "s"); +// gGeoMan->PrintOverlaps(); + gGeoMan->Test(); + + TFile* geoFile = new TFile(geoFileName, "RECREATE"); + top->Write(); + cout << endl; + cout << "Geometry " << top->GetName() << " written to " + << geoFileName << endl; + geoFile->Close(); + + TString geoFileName_ = "sts_"; + geoFileName_ = geoFileName_ + geoTag + "_geo.root"; + + geoFile = new TFile(geoFileName_, "RECREATE"); + gGeoMan->Write(); // use this is you want GeoManager format in the output + geoFile->Close(); + + TString geoFileName__ = "sts_"; + geoFileName_ = geoFileName__ + geoTag + "-geo.root"; + sts->Export(geoFileName_); + + geoFile = new TFile(geoFileName_, "UPDATE"); + stsTrans->Write(); + geoFile->Close(); + + // gGeoManager->FindVolumeFast("LadderType10_CarbonElement")->Draw("ogl"); + top->Draw("ogl"); + gGeoManager->SetVisLevel(8); + + infoFile.close(); + +} +// ============================================================================ +// ====== End of main function ===== +// ============================================================================ + + + + + +// **************************************************************************** +// ***** Definition of media, sensors, sectors and ladders ***** +// ***** ***** +// ***** Decoupled from main function for better readability ***** +// **************************************************************************** + + +/** =========================================================================== + ** Create media + ** + ** Currently created: air, active silicon, passive silion + ** + ** Not used for the time being + **/ +Int_t CreateMedia() { + + Int_t nMedia = 0; + Double_t density = 0.; + + // --- Material air + density = 1.205e-3; // [g/cm^3] + TGeoMixture* matAir = new TGeoMixture("sts_air", 3, density); + matAir->AddElement(14.0067, 7, 0.755); // Nitrogen + matAir->AddElement(15.999, 8, 0.231); // Oxygen + matAir->AddElement(39.948, 18, 0.014); // Argon + + // --- Material silicon + density = 2.33; // [g/cm^3] + TGeoElement* elSi = gGeoMan->GetElementTable()->GetElement(14); + TGeoMaterial* matSi = new TGeoMaterial("matSi", elSi, density); + + + // --- Air (passive) + TGeoMedium* medAir = new TGeoMedium("air", nMedia++, matAir); + medAir->SetParam(0, 0.); // is passive + medAir->SetParam(1, 1.); // is in magnetic field + medAir->SetParam(2, 20.); // max. field [kG] + medAir->SetParam(6, 0.001); // boundary crossing precision [cm] + + + // --- Active silicon for sensors + TGeoMedium* medSiAct = new TGeoMedium("silicon", + nMedia++, matSi); + medSiAct->SetParam(0, 1.); // is active + medSiAct->SetParam(1, 1.); // is in magnetic field + medSiAct->SetParam(2, 20.); // max. field [kG] + medSiAct->SetParam(6, 0.001); // boundary crossing precisison [cm] + + // --- Passive silicon for cables + TGeoMedium* medSiPas = new TGeoMedium("carbon", + nMedia++, matSi); + medSiPas->SetParam(0, 0.); // is passive + medSiPas->SetParam(1, 1.); // is in magnetic field + medSiPas->SetParam(2, 20.); // max. field [kG] + medSiPas->SetParam(6, 0.001); // boundary crossing precisison [cm] + + return nMedia; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sensors + ** + ** Sensors are created as volumes with box shape and active silicon as medium. + ** Four kinds of sensors: 3.2x2.2, 6.2x2.2, 6.2x4.2, 6.2x6.2 + **/ +Int_t CreateSensors() { + + Int_t nSensors = 0; + + Double_t xSize = 0.; + Double_t ySize = 0.; + // Double_t zSize = gkSensorThickness; + Double_t zSize = gkSensorThickness/2.; + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + TGeoMedium* silicon1 = gGeoMan->GetMedium("silicon1"); + // TGeoMedium* silicon2 = gGeoMan->GetMedium("silicon2"); + + + // --- Sensor type 01: Small sensor (6.2 cm x 2.2 cm) + xSize = gkSensorSizeX; + ySize = 2.2; + TGeoBBox* shape_sensor01 = new TGeoBBox("sensor01", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor01", shape_sensor01, silicon); + new TGeoVolume("Sensor11", shape_sensor01, silicon1); + nSensors++; + + + // --- Sensor type 02: Medium sensor (6.2 cm x 4.2 cm) + xSize = gkSensorSizeX; + ySize = 4.2; + TGeoBBox* shape_sensor02 = new TGeoBBox("sensor02", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor02", shape_sensor02, silicon); + new TGeoVolume("Sensor12", shape_sensor02, silicon1); + nSensors++; + + + // --- Sensor type 03: Big sensor (6.2 cm x 6.2 cm) + xSize = gkSensorSizeX; + ySize = 6.2; + TGeoBBox* shape_sensor03 = new TGeoBBox("sensor03", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor03", shape_sensor03, silicon); + new TGeoVolume("Sensor13", shape_sensor03, silicon1); + nSensors++; + + // --- Sensor type 04: Big sensor (6.2 cm x 12.4 cm) + xSize = gkSensorSizeX; + ySize = 12.4; + TGeoBBox* shape_sensor04 = new TGeoBBox("sensor04", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor04", shape_sensor04, silicon); + new TGeoVolume("Sensor14", shape_sensor04, silicon1); + nSensors++; + + +// // below are extra small sensors, those are not available in the CAD model +// +// // --- Sensor Type 05: Half small sensor (4 cm x 2.5 cm) +// xSize = 4.0; +// ySize = 2.5; +// TGeoBBox* shape_sensor05 = new TGeoBBox("sensor05", +// xSize/2., ySize/2., zSize/2.); +// new TGeoVolume("Sensor05", shape_sensor05, silicon); +// nSensors++; +// +// +// // --- Sensor type 06: Additional "in hole" sensor (3.1 cm x 4.2 cm) +// xSize = 3.1; +// ySize = 4.2; +// TGeoBBox* shape_sensor06 = new TGeoBBox("sensor06", +// xSize/2., ySize/2., zSize/2.); +// new TGeoVolume("Sensor06", shape_sensor06, silicon); +// nSensors++; +// +// +// // --- Sensor type 07: Mini Medium sensor (1.5 cm x 4.2 cm) +// xSize = 1.5; +// ySize = 4.2; +// TGeoBBox* shape_sensor07 = new TGeoBBox("sensor07", +// xSize/2., ySize/2., zSize/2.); +// new TGeoVolume("Sensor07", shape_sensor07, silicon); +// nSensors++; + + + return nSensors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sectors + ** + ** A sector is either a single sensor or several chained sensors. + ** It is implemented as TGeoVolumeAssembly. + ** Currently available: + ** - single sensors of type 1 - 4 + ** - two chained sensors of type 4 + ** - three chained sensors of type 4 + **/ +Int_t CreateSectors() { + + Int_t nSectors = 0; + + TGeoVolume* sensor01 = gGeoMan->GetVolume("Sensor01"); + TGeoVolume* sensor02 = gGeoMan->GetVolume("Sensor02"); + TGeoVolume* sensor03 = gGeoMan->GetVolume("Sensor03"); + TGeoVolume* sensor04 = gGeoMan->GetVolume("Sensor04"); + TGeoVolume* sensor05 = gGeoMan->GetVolume("Sensor05"); + TGeoVolume* sensor06 = gGeoMan->GetVolume("Sensor06"); + TGeoVolume* sensor07 = gGeoMan->GetVolume("Sensor07"); + + TGeoVolume* sensor11 = gGeoMan->GetVolume("Sensor11"); + TGeoVolume* sensor12 = gGeoMan->GetVolume("Sensor12"); + TGeoVolume* sensor13 = gGeoMan->GetVolume("Sensor13"); + TGeoVolume* sensor14 = gGeoMan->GetVolume("Sensor14"); + TGeoVolume* sensor15 = gGeoMan->GetVolume("Sensor15"); + TGeoVolume* sensor16 = gGeoMan->GetVolume("Sensor16"); + TGeoVolume* sensor17 = gGeoMan->GetVolume("Sensor17"); + + Double_t shiftZ = gkSensorThickness / 2. /2.; + cout << "DESS " << shiftZ << endl; + + TGeoTranslation* transZU = new TGeoTranslation("zu", 0., 0.,-shiftZ); + TGeoTranslation* transZD = new TGeoTranslation("zd", 0., 0., shiftZ); + + // TGeoBBox* box3 = (TGeoBBox*) sensor03->GetShape(); + // Double_t shift3 = box3->GetDZ(); + // cout << "DESS " << shiftZ << " ; " << -shiftZ << " ; " << shift33 << endl; + + // --- Sector type 1: two half thickness sensor of type 1 + TGeoVolumeAssembly* sector01 = new TGeoVolumeAssembly("Sector01"); +//sector01->AddNode(sensor01, 1); + sector01->AddNode(sensor01, 1, transZU); + sector01->AddNode(sensor11, 2, transZD); + sector01->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 2: two half thickness sensor of type 2 + TGeoVolumeAssembly* sector02 = new TGeoVolumeAssembly("Sector02"); +//sector02->AddNode(sensor02, 1); + sector02->AddNode(sensor02, 1, transZU); + sector02->AddNode(sensor12, 2, transZD); + sector02->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 3: two half thickness sensors of type 3 + TGeoVolumeAssembly* sector03 = new TGeoVolumeAssembly("Sector03"); +//sector03->AddNode(sensor03, 1); + sector03->AddNode(sensor03, 1, transZU); + sector03->AddNode(sensor13, 2, transZD); + sector03->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 4: two half thickness sensor of type 4 + TGeoVolumeAssembly* sector04 = new TGeoVolumeAssembly("Sector04"); +//sector04->AddNode(sensor04, 1); + sector04->AddNode(sensor04, 1, transZU); + sector04->AddNode(sensor14, 2, transZD); + sector04->GetShape()->ComputeBBox(); + nSectors++; + +// // --- Sector type 5: two half thickness sensor of type 5 +// TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); +// sector05->AddNode(sensor05, 1); +// sector05->GetShape()->ComputeBBox(); +// nSectors++; +// +// // --- Sector type 6: two half thickness sensor of type 6 +// TGeoVolumeAssembly* sector06 = new TGeoVolumeAssembly("Sector06"); +// sector06->AddNode(sensor06, 1); +// sector06->GetShape()->ComputeBBox(); +// nSectors++; +// +// // --- Sector type 7: two half thickness sensor of type 7 +// TGeoVolumeAssembly* sector07 = new TGeoVolumeAssembly("Sector07"); +// sector07->AddNode(sensor07, 1); +// sector07->GetShape()->ComputeBBox(); +// nSectors++; + +// // --- Sector type 3: two half thickness sensor of type 3 +// TGeoVolumeAssembly* sector03 = new TGeoVolumeAssembly("Sector03"); +// sector03->AddNode(sensor03, 1); +// sector03->GetShape()->ComputeBBox(); +// nSectors++; + +// TGeoBBox* box = (TGeoBBox*) sector03->GetShape(); +// Double_t sectorX = 2. * box->GetDX(); +// Double_t sectorY = 2. * box->GetDY(); +// Double_t sectorZ = 2. * box->GetDZ(); +// cout << "DESS " << sectorX << " ; " << sectorY << " ; " << sectorZ << endl; + + +// // --- Sector type 5: two sensors of type 4 +// TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); +// Double_t shift5 = 0.5 * gkChainGapY + box4->GetDY(); +// TGeoTranslation* transD5 = +// new TGeoTranslation("td", 0., -1. * shift5, 0.); +// TGeoTranslation* transU5 = +// new TGeoTranslation("tu", 0., shift5, 0.); +// sector05->AddNode(sensor04, 1, transD5); +// sector05->AddNode(sensor04, 2, transU5); +// sector05->GetShape()->ComputeBBox(); +// nSectors++; + + return nSectors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create ladders + ** + ** Ladders are the building blocks of the stations. They contain + ** several modules placed one after the other along the z axis + ** such that the sectors are arranged vertically (with overlap). + ** + ** A ladder is constructed out of two half ladders, the second of which + ** is rotated in the x-y plane by 180 degrees and displaced + ** in z direction. + **/ +Int_t CreateLadders() { + + Int_t nLadders = 0; + + // --- Some variables + Int_t nSectors = 0; + Int_t sectorTypes[10]; + TGeoBBox* shape = NULL; + TString s0name; + TString hlname; + char align; + TGeoVolume* s0vol = NULL; + TGeoVolume* halfLadderU = NULL; + TGeoVolume* halfLadderD = NULL; + + // --- Ladders 01-23 + Int_t allSectorTypes[27][6] = { { 1, 2, 3, 3, 0, -1 }, // ladder 01 - 5 - last column defines alignment of small sensors + { 1, 2, 3, 3, 0, 0 }, // ladder 02 - 5 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, -1 }, // ladder 03 - 6 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 04 - 6 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, -1 }, // ladder 05 - 7 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 06 - 7 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 07 - last column defines alignment of small sensors + { 3, 4, 4, 4, 0, 0 }, // ladder 08 - last column defines alignment of small sensors + + { 1, 1, 2, 3, 3, 0 }, // ladder 09 - last column defines alignment of small sensors + { 1, 1, 2, 2, 3, 0 }, // ladder 10 - last column defines alignment of small sensors + { 2, 2, 0, 0, 0, 0 }, // ladder 11 - last column defines alignment of small sensors + { 2, 2, 2, 3, 4, 0 }, // ladder 12 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 13 - last column defines alignment of small sensors + + { 2, 3, 4, 0, 0, 0 }, // ladder 14 - last column defines alignment of small sensors + { 3, 3, 0, 0, 0, 0 }, // ladder 15 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 16 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 17 - last column defines alignment of small sensors + { 3, 4, 4, 0, 0, 0 }, // ladder 18 - last column defines alignment of small sensors + + { 4, 4, 0, 0, 0, 0 }, // ladder 19 - last column defines alignment of small sensors + { 1, 2, 4, 4, 4, 0 }, // ladder 20 - last column defines alignment of small sensors + { 4, 0, 0, 0, 0, 0 }, // ladder 21 - last column defines alignment of small sensors + { 2, 3, 4, 4, 4, 0 }, // ladder 22 - last column defines alignment of small sensors + { 2, 3, 3, 4, 4, 0 }, // ladder 23 - last column defines alignment of small sensors + + { 2, 3, 4, 4, 0, 0 }, // ladder 24 - copy of 17 with different total length + { 3, 4, 4, 0, 0, 0 }, // ladder 25 - copy of 18 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 26 - copy of 19 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 27 - copy of 19 with different total length + }; // 8 full - 19 partial ladders + +// Issue #405 +// Counting from the most upstream ladder, the gaps between sensors are as follows: +// 01 (most upstream): 41.3mm +// 02: 41.3mm +// 03: 42.0mm +// 04: 48.6mm +// 05: 60.8mm +// 06: 67.0mm +// 07: 79.2mm +// 08 (most downstream): 88.0mm + + Double_t pitchZ = 0; + Double_t gapXYZ[27][3] = { + { 0., 4.13, 0. }, // ladder 01 + { 0., 4.13, 0. }, // ladder 02 + { 0., 4.20, 0. }, // ladder 03 + { 0., 4.86, 0. }, // ladder 04 + { 0., 6.08, 0. }, // ladder 05 + { 0., 6.70, 0. }, // ladder 06 + { 0., 7.92, 0. }, // ladder 07 + { 0., 8.80, 0. }, // ladder 08 + { 0., -gkSectorOverlapY, 0. }, // ladder 09 + { 0., -gkSectorOverlapY, 0. }, // ladder 10 + { 0., -gkSectorOverlapY, 0. }, // ladder 11 + { 0., -gkSectorOverlapY, 0. }, // ladder 12 + { 0., -gkSectorOverlapY, 0. }, // ladder 13 + { 0., -gkSectorOverlapY, 0. }, // ladder 14 + { 0., -gkSectorOverlapY, 0. }, // ladder 15 + { 0., -gkSectorOverlapY, 0. }, // ladder 16 + { 0., -gkSectorOverlapY, 0. }, // ladder 17 + { 0., -gkSectorOverlapY, 0. }, // ladder 18 + { 0., -gkSectorOverlapY, 0. }, // ladder 19 + { 0., -gkSectorOverlapY, 0. }, // ladder 20 + { 0., -gkSectorOverlapY, 0. }, // ladder 21 + { 0., -gkSectorOverlapY, 0. }, // ladder 22 + { 0., -gkSectorOverlapY, 0. }, // ladder 23 + + { 0., -gkSectorOverlapY, 0. }, // ladder 24 - copy of 17 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 25 - copy of 18 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 26 - copy of 19 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 27 - copy of 19 with different total length + }; + + Double_t ladderLength[27] = { + 48.0, // ladder 01 + 48.0, // ladder 02 + 64.0, // ladder 03 + 64.0, // ladder 04 + 80.0, // ladder 05 + 80.0, // ladder 06 + 92.0, // ladder 07 + 96.0, // ladder 08 + 48.0, // ladder 09 + 48.0, // ladder 10 + 48.0, // ladder 11 + 64.0, // ladder 12 + 64.0, // ladder 13 + 64.0, // ladder 14 + 64.0, // ladder 15 + 80.0, // ladder 16 + 80.0, // ladder 17 + 80.0, // ladder 18 + 80.0, // ladder 19 + 92.0, // ladder 20 + 92.0, // ladder 21 + 96.0, // ladder 22 + 96.0, // ladder 23 + + 96.0, // ladder 24 - copy of 17 with different total length + 92.0, // ladder 25 - copy of 18 with different total length + 96.0, // ladder 26 - copy of 19 with different total length + 92.0, // ladder 27 - copy of 19 with different total length + }; +// ======================================================================== + + // calculate Z shift for ladders with and without gaps in the center + s0name = Form("Sector%02d", allSectorTypes[0][0]); + s0vol = gGeoMan->GetVolume(s0name); + shape = (TGeoBBox*) s0vol->GetShape(); + +// ======================================================================== + + for (Int_t iLadder = 0; iLadder < 27; iLadder++) + { + cout << endl; + nSectors = 0; + for (Int_t i=0; i < 5; i++) + if (allSectorTypes[iLadder][i] != 0) + { + sectorTypes[nSectors] = allSectorTypes[iLadder][i]; // copy sectors for this ladder + cout << "DE iLadder " << iLadder+1 << " sectorTypes[" << nSectors << "] = " << allSectorTypes[iLadder][i] << ";" << endl; + nSectors++; // count how many sectors are in this ladder + } + + // always set displacement in z between upper and lower half ladder + gapXYZ[iLadder][2] = 2. * shape->GetDZ() + gkSectorGapZ; + + // define additional offset to carbon ladder for half ladders with less than 5 sensors + pitchZ = 2. * shape->GetDZ() + gkSectorGapZ; + + if (allSectorTypes[iLadder][5] == 0) + align = 'l'; + else + align = 'r'; + hlname = Form("HalfLadder%02du", iLadder+1); + // build upper half ladder + Int_t Ustart = 1; // v19t + // Int_t Ustart = 0; // v19u + if (iLadder < 8) + Ustart = 0; // v19t + // Ustart = 1; // v19u + halfLadderU = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2., Ustart); // mirrored + + if (allSectorTypes[iLadder][5] == 0) + align = 'r'; + else + align = 'l'; + hlname = Form("HalfLadder%02dd", iLadder+1); + // build lower half ladder + Int_t Dstart = 0; // v19t + // Int_t Dstart = 1; // v19u + if (iLadder < 8) + Dstart = 1; // v19t + // Dstart = 0; // v19u + halfLadderD = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2., Dstart); // mirrored + + // at this point half ladders are constructed + + // build all 4 possible ladders types for this sensor arrangement + ConstructLadder( iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19a + ConstructLadder( 100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19b + + ConstructLadder(1000+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19k + ConstructLadder(1100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19k + + nLadders++; + } + + return nLadders; +} +/** ======================================================================= **/ + + + +// **************************************************************************** +// ***** ***** +// ***** Generic functions for the construction of STS elements ***** +// ***** ***** +// ***** module: volume (made of a sector and a cable) ***** +// ***** haf ladder: assembly (made of modules) ***** +// ***** ladder: assembly (made of two half ladders) ***** +// ***** station: volume (made of ladders) ***** +// ***** ***** +// **************************************************************************** + + + +/** =========================================================================== + ** Construct a module + ** + ** A module is a sector plus the readout cable extending from the + ** top of the sector. The cable is made from passive silicon. + ** The cable has the same x size as the sector. + ** Its thickness is given by the global variable gkCableThickness. + ** The cable length is a parameter. + ** The sensor(s) of the sector is/are placed directly in the module; + ** the sector is just auxiliary for the proper placement. + ** + ** Arguments: + ** name volume name + ** sector pointer to sector volume + ** cableLength length of cable + **/ +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength) { + + // --- Check sector volume + if ( ! sector ) Fatal("CreateModule", "Sector volume not found!"); + + // --- Get size of sector + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + + // --- Get size of cable + Double_t cableX = sectorX; + Double_t cableY = cableLength; + Double_t cableZ = gkCableThickness; + + // --- Create module volume + Double_t moduleX = TMath::Max(sectorX, cableX); + Double_t moduleY = sectorY + cableLength; + + Double_t moduleZ = TMath::Max(sectorZ, cableZ); + + TGeoVolume* module = gGeoManager->MakeBox(name, gStsMedium, + moduleX/2., + moduleY/2., + moduleZ/2.); + + // --- Position of sector in module + // --- Sector is centred in x and z and aligned to the bottom + Double_t sectorXpos = 0.; + Double_t sectorYpos = 0.5 * (sectorY - moduleY); + Double_t sectorZpos = 0.; + + + // --- Get sensor(s) from sector + Int_t nSensors = sector->GetNdaughters(); + for (Int_t iSensor = 0; iSensor < nSensors; iSensor++) { + TGeoNode* sensor = sector->GetNode(iSensor); + + // --- Calculate position of sensor in module + const Double_t* xSensTrans = sensor->GetMatrix()->GetTranslation(); + Double_t sensorXpos = sectorXpos + xSensTrans[0]; + Double_t sensorYpos = sectorYpos + xSensTrans[1]; + Double_t sensorZpos = sectorZpos + xSensTrans[2]; + TGeoTranslation* sensTrans = new TGeoTranslation("sensTrans", + sensorXpos, + sensorYpos, + sensorZpos); + + // --- Add sensor volume to module + TGeoVolume* sensVol = sensor->GetVolume(); + module->AddNode(sensor->GetVolume(), iSensor+1, sensTrans); + module->GetShape()->ComputeBBox(); + } + + + // --- Create cable volume, if necessary, and place it in module + // --- Cable is centred in x and z and aligned to the top + if ( gkConstructCables && cableLength > 0.0001 ) { + TString cableName = TString(name) + "_cable"; + TGeoMedium* cableMedium = gGeoMan->GetMedium("STScable"); + if ( ! cableMedium ) Fatal("CreateModule", "Medium STScable not found!"); + TGeoVolume* cable = gGeoManager->MakeBox(cableName.Data(), + cableMedium, + cableX / 2., + cableY / 2., + cableZ / 2.); + // add color to cables + cable->SetLineColor(kOrange); + cable->SetTransparency(90); + // cable->SetTransparency(60); + Double_t cableXpos = 0.; + Double_t cableYpos = sectorY + 0.5 * cableY - 0.5 * moduleY; + Double_t cableZpos = 0.; + TGeoTranslation* cableTrans = new TGeoTranslation("cableTrans", + cableXpos, + cableYpos, + cableZpos); + module->AddNode(cable, 1, cableTrans); + module->GetShape()->ComputeBBox(); + } + + return module; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a half ladder + ** + ** A half ladder is a virtual volume (TGeoVolumeAssembly) consisting + ** of several modules arranged on top of each other. The modules + ** have a given overlap in y and a displacement in z to allow for the + ** overlap. + ** + ** The typ of sectors / modules to be placed must be specified: + ** 1 = sensor01 + ** 2 = sensor02 + ** 3 = sensor03 + ** 4 = sensor04 + ** 5 = 2 x sensor04 (chained) + ** 6 = 3 x sensor04 (chained) + ** The cable is added automatically from the top of each sensor to + ** the top of the half ladder. + ** The alignment can be left (l) or right (r), which matters in the + ** case of different x sizes of sensors (e.g. SensorType01). + ** + ** Arguments: + ** name volume name + ** nSectors number of sectors + ** sectorTypes array with sector types + ** align horizontal alignment of sectors + * ladderLength full length of the ladder towards FEE + * offsetY gap in the beam-pipe region + **/ +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY, + Int_t start) { + + // --- Create half ladder volume assembly + TGeoVolumeAssembly* halfLadder = new TGeoVolumeAssembly(name); + + // --- Determine size of ladder + Double_t ladderX = 0.; + Double_t ladderY = 0.; + Double_t ladderZ = 0.; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + if ( ! sector ) + Fatal("ConstructHalfLadder", Form("Volume %s not found", sectorName.Data())); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + // --- Ladder x size equals largest sector x size + ladderX = TMath::Max(ladderX, 2. * box->GetDX()); + // --- Ladder y size is sum of sector ysizes + ladderY += 2. * box->GetDY(); + // --- Ladder z size is sum of sector z sizes + ladderZ += 2. * box->GetDZ(); + + cout << "DETT " << ladderX << " ; " << ladderY << " ; " << ladderZ << endl; + } + // --- Subtract overlaps in y + ladderY -= Double_t(nSectors-1) * gkSectorOverlapY; + // --- Add gaps in z direction + ladderZ += Double_t(nSectors-1) * gkSectorGapZ; + + ladderY = TMath::Max(ladderLength - offsetY, ladderY); + + // --- Create and place modules + Double_t yPosSect = -0.5 * ladderY; + Double_t zPosMod = -0.5 * ladderZ; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + yPosSect += 0.5 * sectorY; // Position of sector in ladder + Double_t cableLength = 0.5 * ladderY - yPosSect - 0.5 * sectorY; + TString moduleName = name + "_" + Form("Module%02d", + sectorTypes[iSector]); + TGeoVolume* module = ConstructModule(moduleName.Data(), + sector, cableLength); + + TGeoBBox* shapeMod = (TGeoBBox*) module->GetShape(); + Double_t moduleX = 2. * shapeMod->GetDX(); + Double_t moduleY = 2. * shapeMod->GetDY(); + Double_t moduleZ = 2. * shapeMod->GetDZ(); + Double_t xPosMod = 0.; + if ( align == 'l' ) + xPosMod = 0.5 * (moduleX - ladderX); // left aligned + else if ( align == 'r' ) + xPosMod = 0.5 * (ladderX - moduleX); // right aligned + else + xPosMod = 0.; // centred in x + Double_t yPosMod = 0.5 * (ladderY - moduleY); // top aligned + zPosMod += 0.5 * moduleZ; + +// Int_t angle = 0; // set default rotation angle to 0 +// if (iSector%2 == 1) // set rotation angle for every 2nd sensor +// angle = 180; + + Int_t angle = start * 180; + start = (start + 1) % 2; + + TGeoRotation* rmod = new TGeoRotation(); + rmod->RotateY(angle); // v19t, v19u + // rmod->RotateY(180); // v19v + // rmod->RotateY(0); // v19w + TGeoCombiTrans* cmod = new TGeoCombiTrans (xPosMod, yPosMod, zPosMod, rmod); + halfLadder->AddNode(module, iSector+1, cmod); + +// old style +// TGeoTranslation* trans = new TGeoTranslation("t", xPosMod, yPosMod, zPosMod); +// halfLadder->AddNode(module, iSector+1, trans); + + halfLadder->GetShape()->ComputeBBox(); + yPosSect += 0.5 * sectorY - gkSectorOverlapY; + zPosMod += 0.5 * moduleZ + gkSectorGapZ; + } + + CheckVolume(halfLadder); + cout << endl; + + return halfLadder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Add a carbon support to a ladder + ** + ** Arguments: + ** LadderIndex ladder number + ** ladder pointer to ladder + ** xu size of halfladder + ** ladderY height of ladder along y + ** ladderZ thickness of ladder along z + **/ +void AddCarbonLadder(Int_t LadderIndex, + TGeoVolume* ladder, + Double_t xu, + Double_t ladderY, + Double_t ladderZ) { + + // --- Some variables + TString name = Form("LadderType%04d", LadderIndex); // v19k + Int_t i; + Double_t j; + + Int_t YnumOfFrameBoxes = round(ladderY / gkFrameStep); + + // cout << "DEXZ: lad " << LadderIndex << " inum " << YnumOfFrameBoxes << endl; + + Double_t ladderDZ = (xu/2. + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2)/2.; + cout << "DEFR: frame Z size " << 2 * ladderDZ << " cm" << endl; + + TGeoBBox* fullFrameShp = new TGeoBBox (name+"_CarbonElement_shp", xu/2., gkFrameStep/2., ladderDZ); + TGeoVolume* fullFrameBoxVol = new TGeoVolume(name+"_CarbonElement", fullFrameShp, gStsMedium); + + ConstructFrameElement("CarbonElement", fullFrameBoxVol, xu/2.); + TGeoRotation* fullFrameRot = new TGeoRotation; + fullFrameRot->RotateY(180); + + Int_t inum = YnumOfFrameBoxes; + for (i=1; i<=inum; i++) + { + j=-(inum-1)/2.+(i-1); + // -(10-1)/2. +0 +10-1 -> -4.5 .. +4.5 -> -0.5, +0.5 (= 2) + // -(11-1)/2. +0 +11-1 -> -5.0 .. +5.0 -> -1, 0, 1 (= 3) + // cout << "DE: i " << i << " j " << j << endl; + + if (LadderIndex % 100 <= 3) // central ladders in stations 1 to 3 + { + if ((j>=-1) && (j<=1)) // keep the inner 2 (even) or 3 (odd) elements free for the cone + continue; + } + else if (LadderIndex % 100 <= 8) // central ladders in stations 4 to 8 + { + if ((j>=-2) && (j<=2)) // keep the inner 4 elements free for the cone + continue; + } + + cout << "DELZ: ladderDZ " << ladderDZ << " cm " << -ladderZ/2. - ladderDZ << " cm " << endl; + ladder->AddNode(fullFrameBoxVol, i, new TGeoCombiTrans(name+"_CarbonElement_posrot", 0., j*gkFrameStep, -(ladderZ/2.+ladderDZ), fullFrameRot)); + } + + ladder->GetShape()->ComputeBBox(); + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Construct a ladder out of two half ladders with vertical gap + ** + ** The second half ladder will be rotated by 180 degrees + ** in the x-y plane. The two half ladders will be put on top of each + ** other with a vertical gap. + ** + ** Arguments: + ** name volume name + ** halfLadderU pointer to upper half ladder + ** halfLadderD pointer to lower half ladder + ** gapY vertical gap + ** shiftZ relative displacement along the z axis + **/ + + TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ, + Double_t pitchZ, + Int_t nSectors) { + + // --- Some variables + TGeoBBox* shape = NULL; + + // define additional offset to carbon ladder for half ladders with less than 5 sensors + Double_t offsetZ = (5 - nSectors) * pitchZ; + + // --- Dimensions of half ladders + shape = (TGeoBBox*) halfLadderU->GetShape(); // up + Double_t xu = 2. * shape->GetDX(); + Double_t yu = 2. * shape->GetDY(); + Double_t zu = 2. * shape->GetDZ(); + + shape = (TGeoBBox*) halfLadderD->GetShape(); // down + Double_t xd = 2. * shape->GetDX(); + Double_t yd = 2. * shape->GetDY(); + Double_t zd = 2. * shape->GetDZ(); + + // --- Create ladder volume assembly + TString name = Form("LadderType%04d", LadderIndex); // v19k + TGeoVolumeAssembly* ladder = new TGeoVolumeAssembly(name); + Double_t ladderX = TMath::Max(xu, xd); + Double_t ladderY = yu + yd + gapY; + Double_t ladderZ = TMath::Max(zu, zd + shiftZ + offsetZ); // there are 6 slots - 5 x 1.5 mm + 0.3 mm = 7.8 mm + // Double_t ladderZ = TMath::Max(zu, zd + shiftZ); + + cout << "DERR iladder " << LadderIndex << " nSec " << nSectors + << " zu " << zu << " zd " << zd + << " zd+shi " << zd+shiftZ << " ladderZ " << ladderZ + << " offsetZ " << offsetZ << endl; + + // --- Place half ladders + Double_t xPosU = 0.0; // centred in x + Double_t yPosU = 0.5 * ( ladderY - yu ); // top aligned + Double_t zPosU = 0; + zPosU = 0.5 * ( ladderZ - zu ); // front aligned + if (LadderIndex >= 1000) + zPosU = -0.5 * ( ladderZ - zu ) + offsetZ; // back aligned with possible offset + //zPosU = -zPosU; + + TGeoTranslation* tu = new TGeoTranslation("tu", xPosU, yPosU, zPosU); + ladder->AddNode(halfLadderU, 1, tu); + + Double_t xPosD = 0.0; // centred in x + Double_t yPosD = 0.5 * -( ladderY - yd ); // bottom aligned + Double_t zPosD = 0; + zPosD = 0.5 * -( ladderZ - zd ) + offsetZ; // back aligned with possible offset + if (LadderIndex >= 1000) + zPosD = -0.5 * -( ladderZ - zd ); // front aligned + //zPosD = -zPosD; + + TGeoRotation* rd = new TGeoRotation(); + rd->RotateZ(180.); + TGeoCombiTrans* cd = new TGeoCombiTrans(xPosD, yPosD, zPosD, rd); + ladder->AddNode(halfLadderD, 2, cd); + + ladder->GetShape()->ComputeBBox(); + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD0ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + cout << "DDDD ladder" << LadderIndex << endl; + cout << "DDDD1ladder" << LadderIndex << " ladderX " << ladderX << " ladderY " << ladderY << " ladderZ " << ladderZ << endl; + + // ---------------- Create and place frame boxes ------------------------ + + if (gkConstructFrames) + AddCarbonLadder(LadderIndex, ladder, ladderX, ladderY, ladderZ); + + // -------------------------------------------------------------------------- + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD2ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + return ladder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a unit + ** + ** The unit volume is the minimal box comprising all ladders + ** minus a tube accomodating the beam pipe. + ** + ** The ladders are arranged horizontally from left to right with + ** a given overlap in x. + ** Every second ladder is slightly displaced upstream from the centre + ** z plane and facing downstream, the others are slightly displaced + ** downstream and facing upstream (rotated around the y axis). + ** + ** Arguments: + ** name volume name + ** nLadders number of ladders + ** ladderTypes array of ladder types + **/ + + TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation) { + + Bool_t isFirstPartOfHalfUnit = kFALSE; + + // TString name = Form("Unit%02d", iUnit); // 0,1,2,3,4,5,6,7 - Unit00 missing in output + // TString name = Form("Unit%02d", iUnit+1); // 1,2,3,4,5,6,7,8 + + TGeoVolume* unit = gGeoMan->GetVolume(unitName[iUnit]); + if ( ! unit ) // if it does not yet exist, create a new one + { + unit = new TGeoVolumeAssembly(unitName[iUnit]); + isFirstPartOfHalfUnit = kTRUE; + } + + // --- Some local variables + TGeoBBox* ladderShape = NULL; + TGeoVolume* ladder = NULL; + TString ladderName; + Double_t subtractedVal; + + // --- Determine size of unit from ladders + Double_t statX = 0.; + // Double_t statY = 0.; + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) + { + Int_t ladderType = ladderTypes[iLadder]; // v19k + +// if (iSide == 0) cout << "DWER " << ladderTypes[iLadder] << " " << ladderType << endl; + + if (ladderType > 0) + { + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + if ( ! ladder ) Fatal("ConstructUnit", + Form("Volume %s not found", ladderName.Data())); + ladderShape = (TGeoBBox*) ladder->GetShape(); + statX += 2. * ladderShape->GetDX(); + } + else + statX += gkSensorSizeX; // empty ladder in unit + } + statX -= Double_t(nLadders-1) * gkLadderOverlapX; + +// if (iSide == 0) cout << "DWER -" << endl; + + // --- Place ladders in unit + cout << "xPos0: " << statX << endl; + Double_t xPos = -0.5 * statX; + cout << "xPos1: " << xPos << endl; + Double_t yPos = 0.; + Double_t zPos = 0.; + + Double_t maxdz = 0.; + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) // find maximum dz in this unit + { + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + if (maxdz < ladderShape->GetDZ()) + maxdz = ladderShape->GetDZ(); + } + } + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) + { + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + xPos += ladderShape->GetDX(); + cout << "xPos2: " << xPos << endl; + yPos = 0.; // vertically centred + TGeoRotation* rot = new TGeoRotation(); + + if (gkConstructFrames) + subtractedVal = ladderShape->GetDX() + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2; + else + subtractedVal = 0.; + + zPos = 0.5 * gkLadderGapZ + (2*maxdz-ladderShape->GetDZ()-subtractedVal/2.); // z-aligned ladders + +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " dx: " << ladderShape->GetDX() + << " dy: " << ladderShape->GetDY() + << " dz: " << ladderShape->GetDZ() + << " max dz: " << maxdz << endl; + +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " fra: " << gkFrameThickness/2. + << " sub: " << subtractedVal + << " zpo: " << zPos << endl << endl; + +// v19k + if (ladderTypes[iLadder]/1000 == 1) // flip some of the ladders to reproduce the CAD layout + rot->RotateY(180.); + else + zPos = -zPos; + + if (!isFirstPartOfHalfUnit) + zPos += 10.5; // v19d +// zPos += 10.0; // initial version + + TGeoCombiTrans* trans = new TGeoCombiTrans(xPos, yPos, zPos, rot); +// start +// cout << "DEEE** iLadder " << iLadder << " " << nLadders/2 << " " << nLadders << endl; + + if (iSide == 0) + { + if (iLadder < nLadders/2) // right side - only half unit -x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + else + { + if (iLadder >= nLadders/2) // left side - only half unit +x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + unit->GetShape()->ComputeBBox(); +// stop + xPos += ladderShape->GetDX() - gkLadderOverlapX; + cout << "xPos3: " << xPos << endl; + } + else + xPos += gkSensorSizeX - gkLadderOverlapX; + } + + return unit; + } +/** ======================================================================= **/ + + +/** =========================================================================== + ** Import and add the passive materials to the STS volume + **/ +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile) +{ + TString passiveName = TString("sts_passive_") + geoTag; + TString basePath = gSystem->Getenv("VMCWORKDIR"); + TString relPath = "/geometry/sts/passive/" + passiveName + ".gdml"; + TString passiveFileName = basePath + relPath; + infoFile << std::endl << std::endl; + infoFile << "Importing STS passive materials from GDML file '" << relPath << "'." << std::endl; + + TGDMLParse parser; + TGeoVolume* gdmlVolume = parser.GDMLReadFile(passiveFileName); + PostProcessGdml(gdmlVolume); + gdmlVolume->SetName(passiveName); + + TGeoTranslation* passiveTrans = new TGeoTranslation(0., 0., 4.68 - 2.); + infoFile << "Passive assembly is translated for Z=2.68 cm downstream with respect to parent volume" << std::endl << std::endl; + + gdmlVolume->GetShape()->ComputeBBox(); + CheckVolume(gdmlVolume, infoFile); + + infoFile << std::endl; + for (Int_t iNode = 0; iNode < gdmlVolume->GetNdaughters(); iNode++) { + CheckVolume(gdmlVolume->GetNode(iNode)->GetVolume(), infoFile, kFALSE); + } + + stsVolume->AddNode(gdmlVolume, stsVolume->GetNdaughters(), passiveTrans, ""); +} + +/** =========================================================================== + ** Assign visual properties to the imported gdml volumes + **/ +void PostProcessGdml(TGeoVolume* gdmlVolume) +{ + const UInt_t kPOBColor = kRed-6; + const UInt_t kPOBTransparency = 0;// 5; + + const UInt_t kFEBColor = kOrange-6; + const UInt_t kFEBTransparency = 0;// 5; + + const UInt_t kUnitColor = kCyan-10; + const UInt_t kUnitTransparency = 0;// 5; + + const UInt_t kCfColor = kGray+3; + const UInt_t kCfTransparency = 0;// 10; + + // name <Color, Transparency> + std::map<std::string, std::tuple<UInt_t,UInt_t> > props { + { "passive_POB", std::tuple<UInt_t,UInt_t> {kPOBColor, kPOBTransparency} }, + { "passive_FEB", std::tuple<UInt_t,UInt_t> {kFEBColor, kFEBTransparency} }, + { "passive_unit", std::tuple<UInt_t,UInt_t> {kUnitColor, kUnitTransparency} }, + { "passive_Box_Wall", std::tuple<UInt_t,UInt_t> {kCfColor, kCfTransparency} }, + { "passive_Box_Wall_Front_CF2", std::tuple<UInt_t,UInt_t> {kCfColor-3, kCfTransparency} }, + }; + + // Match volume name and apply visual properties + const TObjArray* volumes = gGeoManager->GetListOfVolumes(); + for (auto& entry : props) { + TIter next(volumes); + TGeoVolume *vol = nullptr; + while ((vol=(TGeoVolume*)next())) { + if (TString(vol->GetName()).Contains(entry.first.c_str())) { + vol->SetLineColor(std::get<0>(entry.second)); + vol->SetTransparency(std::get<1>(entry.second)); + } + } + } +} + +/** =========================================================================== + ** Volume information for debugging + **/ +void CheckVolume(TGeoVolume* volume) { + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + cout << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) cout << ", assembly"; + else { + if ( volume->GetMedium() ) + cout << ", medium " << volume->GetMedium()->GetName(); + else cout << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + cout << endl; + if ( volume->GetNdaughters() ) { + cout << "Daughters: " << endl; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) { + TGeoNode* node = volume->GetNode(iNode); + TGeoBBox* shape = (TGeoBBox*) node->GetVolume()->GetShape(); + cout << setw(15) << node->GetName() << ", size " + << fixed << setprecision(3) + << setw(6) << 2. * shape->GetDX() << " x " + << setw(6) << 2. * shape->GetDY() << " x " + << setw(6) << 2. * shape->GetDZ() << ", position ( "; + TGeoMatrix* matrix = node->GetMatrix(); + const Double_t* pos = matrix->GetTranslation(); + cout << setfill(' '); + cout << fixed << setw(8) << pos[0] << ", " + << setw(8) << pos[1] << ", " + << setw(8) << pos[2] << " )" << endl; + } + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Volume information for output to file + **/ +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren) { + if ( ! file ) return; + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + file << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) file << ", assembly"; + else { + if ( volume->GetMedium() ) + file << ", medium " << volume->GetMedium()->GetName(); + else file << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + file << endl; + if ( volume->GetNdaughters() && listChildren) { + file << "Contains: "; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) + file << volume->GetNode(iNode)->GetVolume()->GetName() << " "; + file << endl; + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Calculate beam pipe outer radius for a given z + **/ +Double_t BeamPipeRadius(Double_t z) { + if ( z < gkPipeZ2 ) return gkPipeR1; + Double_t slope = (gkPipeR3 - gkPipeR2 ) / (gkPipeZ3 - gkPipeZ2); + return gkPipeR2 + slope * (z - gkPipeZ2); +} +/** ======================================================================= **/ + + + +/** ======================================================================= **/ +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + TGeoBBox* frameVertPillarShp; + + Double_t t = gkFrameThickness/2.; + + // --- Main vertical pillars +// TGeoBBox* frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, gkFrameStep/2., t); // square crossection, along y +// TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); +// frameVertPillarVol->SetLineColor(kGreen); +// frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoTranslation(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2.)); +// frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoTranslation(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkCylindricalFrames) + // TGeoBBox* frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", 0, t, gkFrameStep/2.); // circle crossection, along z + frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", gkCylinderDiaInner/2., gkCylinderDiaOuter/2., gkFrameStep/2.); // circle crossection, along z + else + frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, t, gkFrameStep/2.); // square crossection, along z + TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); + frameVertPillarVol->SetLineColor(kGreen); + + TGeoRotation* xRot90 = new TGeoRotation; + xRot90->RotateX(90.); + frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoCombiTrans(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoCombiTrans(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + + // TGeoRotation* vertRot = new TGeoRotation(name + "_vertpillar_rot_1", 90., 45., -90.); + TGeoRotation* vertRot = new TGeoRotation; + vertRot->RotateX(90.); + vertRot->RotateY(45.); + frameBoxVol->AddNode(frameVertPillarVol, 3, new TGeoCombiTrans(name + "_vertpillar_pos_3", 0., 0., (x-sqrt(2.)*t)/2., vertRot)); + + // --- Small horizontal pillar + // TGeoBBox* frameHorPillarShp = new TGeoBBox(name + "_horpillar_shape", x-2.*t, gkThinFrameThickness/2., gkThinFrameThickness/2.); + // TGeoVolume* frameHorPillarVol = new TGeoVolume(name + "_horpillar", frameHorPillarShp, framesMaterial); + // frameHorPillarVol->SetLineColor(kCyan); + // frameBoxVol->AddNode(frameHorPillarVol, 1, new TGeoTranslation(name + "_horpillar_pos_1", 0., -gkFrameStep/2.+gkThinFrameThickness/2., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkConstructSmallFrames) { + + // --- Small sloping pillars + TGeoPara* frameSlopePillarShp = new TGeoPara(name + "_slopepillar_shape", + (x-2.*t)/TMath::Cos(31.4/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., 31.4, 0., 90.); + TGeoVolume* frameSlopePillarVol = new TGeoVolume(name + "_slopepillar", frameSlopePillarShp, framesMaterial); + frameSlopePillarVol->SetLineColor(kCyan); + TGeoRotation* slopeRot = new TGeoRotation(name + "_slopepillar_rot_1", 0., 0., 31.4); + TGeoRotation* slopeRot2 = new TGeoRotation(name + "_slopepillar_rot_2", 0., 0., -31.4); + TGeoCombiTrans* slopeTrRot = new TGeoCombiTrans(name + "_slopepillar_posrot_1", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot); + TGeoCombiTrans* slopeTrRot2 = new TGeoCombiTrans(name + "_slopepillar_posrot_2", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot2); + + frameBoxVol->AddNode(frameSlopePillarVol, 1, slopeTrRot); + frameBoxVol->AddNodeOverlap(frameSlopePillarVol, 2, slopeTrRot2); + + + Double_t angl = 23.; + // --- Small sub pillar + TGeoPara* frameSubPillarShp = new TGeoPara(name + "_subpillar_shape", + (sqrt(2)*(x/2.-t)-t/2.)/TMath::Cos(angl/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., angl, 0., 90.); + TGeoVolume* frameSubPillarVol = new TGeoVolume(name + "_subpillar", frameSubPillarShp, framesMaterial); + frameSubPillarVol->SetLineColor(kMagenta); + + Double_t posZ = t * (1. - 3. / ( 2.*sqrt(2.) )); + + // one side of X direction + TGeoRotation* subRot1 = new TGeoRotation(name + "_subpillar_rot_1", 90., 45., -90.+angl); + TGeoCombiTrans* subTrRot1 = new TGeoCombiTrans(name + "_subpillar_posrot_1", -(-x/2.+t-t/(2.*sqrt(2.))), 1., posZ, subRot1); + + TGeoRotation* subRot2 = new TGeoRotation(name + "_subpillar_rot_2", 90., -90.-45., -90.+angl); + TGeoCombiTrans* subTrRot2 = new TGeoCombiTrans(name + "_subpillar_posrot_2", -(-x/2.+t-t/(2.*sqrt(2.))), -1., posZ, subRot2); + + // other side of X direction + TGeoRotation* subRot3 = new TGeoRotation(name + "_subpillar_rot_3", 90., 90.+45., -90.+angl); + TGeoCombiTrans* subTrRot3 = new TGeoCombiTrans(name + "_subpillar_posrot_3", -x/2.+t-t/(2.*sqrt(2.)), 1., posZ, subRot3); + + TGeoRotation* subRot4 = new TGeoRotation(name + "_subpillar_rot_4", 90., -45., -90.+angl); + TGeoCombiTrans* subTrRot4 = new TGeoCombiTrans(name + "_subpillar_posrot_4", -x/2.+t-t/(2.*sqrt(2.)), -1., posZ, subRot4); + + frameBoxVol->AddNode(frameSubPillarVol, 1, subTrRot1); + frameBoxVol->AddNode(frameSubPillarVol, 2, subTrRot2); + frameBoxVol->AddNode(frameSubPillarVol, 3, subTrRot3); + frameBoxVol->AddNode(frameSubPillarVol, 4, subTrRot4); + // frameBoxVol->GetShape()->ComputeBBox(); + } + + return frameBoxVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructSmallCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 6., 7.6, 6., 6.04, 0., 180.); +// TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + Double_t radius = 3.0; + Double_t thickness = 0.04; // 0.4 mm +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 3., 3.2, 3., 3.2, 0., 180.); + TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, radius, radius+thickness, radius, radius+thickness, 0., 180.); + TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + TGeoCombiTrans* M = new TGeoCombiTrans ("M"); + M->RotateX (45.); + M->SetDy (-5.575); + M->SetDz (6.935); + M->RegisterYourself(); + + TGeoShape* coneShp = new TGeoCompositeShape ("Cone_shp", "A-B:M"); + TGeoVolume* coneVol = new TGeoVolume ("Cone", coneShp, framesMaterial); + coneVol->SetLineColor(kGreen); +// coneVol->RegisterYourself(); + +// // --- Inner cone +// Double_t thickness = 0.02; +// Double_t thickness2 = 0.022; +// // TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); +// TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 3.+thickness, 4.6-thickness2, 2.99+thickness, 3.05-thickness2, 0., 180.); +// +// TGeoCombiTrans* M2 = new TGeoCombiTrans ("M2"); +// M2->RotateX (45.); +// M2->SetDy (-5.575+thickness*sqrt(2.)); +// M2->SetDz (6.935); +// M2->RegisterYourself(); +// +// TGeoShape* coneShp2 = new TGeoCompositeShape ("Cone2_shp", "A2-B:M2"); +// TGeoVolume* coneVol2 = new TGeoVolume ("Cone2", coneShp2, gStsMedium); +// coneVol2->SetLineColor(kGreen); +//// coneVol2->RegisterYourself(); +// +// coneVol->AddNode(coneVol2, 1); + + return coneVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructBigCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone + TGeoConeSeg* bA = new TGeoConeSeg ("bA", coneDz, 6., 7.6, 6., 6.04, 0., 180.); + TGeoBBox* bB = new TGeoBBox ("bB", 8., 6., 10.); + + TGeoCombiTrans* bM = new TGeoCombiTrans ("bM"); + bM->RotateX (45.); + bM->SetDy (-5.575); + bM->SetDz (6.935); + bM->RegisterYourself(); + + TGeoShape* coneBigShp = new TGeoCompositeShape ("ConeBig_shp", "bA-bB:bM"); + TGeoVolume* coneBigVol = new TGeoVolume ("ConeBig", coneBigShp, framesMaterial); + coneBigVol->SetLineColor(kGreen); +// coneBigVol->RegisterYourself(); + + // --- Inner cone + Double_t thickness = 0.02; + Double_t thickness2 = 0.022; + TGeoConeSeg* bA2 = new TGeoConeSeg ("bA2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); + + TGeoCombiTrans* bM2 = new TGeoCombiTrans ("bM2"); + bM2->RotateX (45.); + bM2->SetDy (-5.575+thickness*sqrt(2.)); + bM2->SetDz (6.935); + bM2->RegisterYourself(); + + TGeoShape* coneBigShp2 = new TGeoCompositeShape ("ConeBig2_shp", "bA2-bB:bM2"); + TGeoVolume* coneBigVol2 = new TGeoVolume ("ConeBig2", coneBigShp2, gStsMedium); + coneBigVol2->SetLineColor(kGreen); +// coneBigVol2->RegisterYourself(); + + coneBigVol->AddNode(coneBigVol2, 1); + + return coneBigVol; +} + +/** ======================================================================= **/ diff --git a/macro/sts/geometry/create_stsgeo_v19t.C b/macro/sts/geometry/create_stsgeo_v19t.C new file mode 100644 index 0000000000000000000000000000000000000000..0fc9139354b6d94a0440881bed5d5640bfda947e --- /dev/null +++ b/macro/sts/geometry/create_stsgeo_v19t.C @@ -0,0 +1,2403 @@ +/****************************************************************************** + ** Creation of STS geometry in ROOT format (TGeo). + ** + ** @file create_stsgeo_v19t.C + ** @author Volker Friese <v.friese@gsi.de> + ** @since 15 June 2012 + ** @date 09.05.2014 + ** @author Tomas Balog <T.Balog@gsi.de> + ** + ** v19t: application of pp-nn sensor orientation to v19r (as tested in v19s) + ** v19s: introducing pp-nn sensor orientation - only for visualisation using blue and red surfaces + ** v19r: bugfix of v19q - align all halfladders + ** v19q: based on v19l - align ladders to virtual plane in station center, closing the gaps in z + ** v19p: based on v19k - parameters : delta Z prime = 0.70 cm - delta Z pitch = 0.20 cm + ** v19o: based on v19k - parameters : delta Z prime = 0.30 cm - delta Z pitch = 0.20 cm + ** v19n: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.20 cm (bug fix of v19m) + ** v19m: based on v19k - parameters : delta Z prime = 0.55 cm - delta Z pitch = 0.20 cm (bug) + ** v19l: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.15 cm + ** v19k: ladders on upstream side of units get upper half ladders installed first, + ** ladders on downstream side of units get lower half ladders installed first, + ** this saves 1.5 mm space in z per station, 12 mm in total (LadderType went from 3 to 4 digits) + ** parameters : delta Z prime = 1.00 cm - delta Z pitch = 0.15 cm + ** v19j: use overlap and distance parameters from CAD model + ** v19h: put STS stations from v19d at z-positions = 260; 365; 470; 575; 680; 785; 890; 995 mm + ** v19g: place a box with services around v19e + ** v19f: place a box with services around v19d + ** v19e: increase spacing between stations by +10 mm from 100 mm + ** v19d: increase spacing between stations by + 5 mm from 100 mm + ** v19c: drop station 8 and increase spacing between remaining 7 stations from 10 cm to 12 c + ** v19b: introduce FEB orientation in ladder numbering (LadderType went from 2 to 3 digits) + ** v19a: import passive materials from gdml file + ** extend CF ladder structures and cables towards FEE plane + ** change CF ladder frame shape + ** v18d: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu (based on v18b) + ** v18c: fixed cut-out windows in cooling plates, improve the box shape/materials + ** v18b: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu + ** v18a: adds 9 cooling/holding plates and a box around the setup + ** v16g: v16g is the new standard geometry from November 2017 + ** v16g: switch from stations to units - left / right ("Unit01L", "Unit01R") + ** v16f: switch from stations to units + ** - split in upstream / downstream and left / right parts + ** - named Unit0xUR, Unit0xUL, Unit0xDR, Unit0xDL + ** v16e: switch from stations to units - upstream / downstream ("Unit01U", "Unit01D") + ** v16d: skip keeping volumes of sts and stations + ** v16c: like v16b, but senors of ladders beampipe next to beampipe + ** shifted closer to the pipe, like in the CAD model + ** v16b: like v16a, but yellow sensors removed + ** v16a: derived from v15c (no cones), but with sensor types renamed: + ** 2 -> 1, 3 -> 2, 4 -> 3, 5 -> 4, 1 -> 5 + ** + ** v15c: as v15b without cones + ** v15b: introduce modified carbon ladders from v13z + ** v15a: with flipped ladder orientation for stations 0,2,4,6 to match CAD design + ** + ** TODO: + ** + ** DONE: + ** v15b - use carbon macaroni as ladder support + ** v15b - introduce a small gap between lowest sensor and carbon ladder + ** v15b - build small cones for the first 2 stations + ** v15b - within a station the ladders of adjacent units should not touch eachother - set gkLadderGapZ to 10 mm + ** v15b - for all ladders set an even number of ladder elements + ** v15b - z offset of cones to ladders should not be 0.3 by default, but 0.26 + ** v15b - within a station the ladders should be aligned in z, defined either by the unit or the ladder with most sensors + ** v15b - get rid of cone overlap in stations 7 and 8 - done by adapting rHole size + ** + ** The geometry hierarachy is: + ** + ** 1. Sensors (see function CreateSensors) + ** The sensors are the active volumes and the lowest geometry level. + ** They are built as TGeoVolumes, shape box, material silicon. + ** x size is determined by strip pitch 58 mu and 1024 strips + ** plus guard ring of 1.3 mm at each border -> 6.1992 cm. + ** Sensor type 1 is half of that (3.0792 cm). + ** y size is determined by strip length (2.2 / 4.2 / 6.3 cm) plus + ** guard ring of 1.3 mm at top and bottom -> 2.46 / 4.46 / 6.46 cm. + ** z size is a parameter, to be set by gkSensorThickness. + ** + ** 2. Sectors (see function CreateSectors) + ** Sectors consist of several chained sensors. These are arranged + ** vertically on top of each other with a gap to be set by + ** gkChainGapY. Sectors are constructed as TGeoVolumeAssembly. + ** The sectors are auxiliary volumes used for proper placement + ** of the sensor(s) in the module. They do not show up in the + ** final geometry. + ** + ** 3. Modules (see function ConstructModule) + ** A module is a readout unit, consisting of one sensor or + ** a chain of sensors (see sector) and a cable. + ** The cable extends from the top of the sector vertically to the + ** top of the halfladder the module is placed in. The cable and module + ** volume thus depend on the vertical position of the sector in + ** the halfladder. The cables consist of silicon with a thickness to be + ** set by gkCableThickness. + ** Modules are constructed as TGeoVolume, shape box, medium gStsMedium. + ** The module construction can be switched off (gkConstructCables) + ** to reproduce older geometries. + ** + ** 4. Halfladders (see function ConstructHalfLadder) + ** A halfladder is a vertical assembly of several modules. The modules + ** are placed vertically such that their sectors overlap by + ** gkSectorOverlapY. They are displaced in z direction to allow for the + ** overlap in y by gkSectorGapZ. + ** The horizontal placement of modules in the halfladder can be choosen + ** to left aligned or right aligned, which only matters if sensors of + ** different x size are involved. + ** Halfladders are constructed as TGeoVolumeAssembly. + ** + ** 5. Ladders (see function CreateLadders and ConstructLadder) + ** A ladder is a vertical assembly of two halfladders, and is such the + ** vertical building block of a station. The second (bottom) half ladder + ** is rotated upside down. The vertical arrangement is such that the + ** inner sectors of the two halfladders have the overlap gkSectorOverlapY + ** (function CreateLadder) or that there is a vertical gap for the beam + ** hole (function CreateLadderWithGap). + ** Ladders are constructed as TGeoVolumeAssembly. + ** + ** 6. Stations (see function ConstructStation) + ** A station represents one layer of the STS geometry: one measurement + ** at (approximately) a given z position. It consist of several ladders + ** arranged horizontally to cover the acceptance. + ** The ladders are arranged such that there is a horizontal overlap + ** between neighbouring ladders (gkLadderOverLapX) and a vertical gap + ** to allow for this overlap (gkLadderGapZ). Each second ladder is + ** rotated around its y axis to face away from or into the beam. + ** Stations are constructed as TGeoVolumes, shape box minus tube (for + ** the beam hole), material gStsMedium. + ** + ** 7. STS + ** The STS is a volume hosting the entire detectors system. It consists + ** of several stations located at different z positions. + ** The STS is constructed as TGeoVolume, shape box minus cone (for the + ** beam pipe), material gStsMedium. The size of the box is computed to + ** enclose all stations. + *****************************************************************************/ + + +// Remark: With the proper steering variables, this should exactly reproduce +// the geometry version v11b of A. Kotynia's described in the ASCII format. +// The only exception is a minimal difference in the z position of the +// sectors/sensors. This is because of ladder types 2 and 4 containing the half +// sensors around the beam hole (stations 1,2 and 3). In v11b, the two ladders +// covering the beam hole cannot be transformed into each other by rotations, +// but only by a reflection. This means they are constructionally different. +// To avoid introducing another two ladder types, the difference in z position +// was accepted. + + +// Differences to v12: +// gkChainGap reduced from 1 mm to 0 +// gkCableThickness increased from 100 mum to 200 mum (2 cables per module) +// gkSectorOverlapY reduced from 3 mm to 2.4 mm +// New sensor types 05 and 06 +// New sector types 07 and 08 +// Re-definiton of ladders (17 types instead of 8) +// Re-definiton of station from new ladders + + +#include <iomanip> +#include <iostream> +#include "TGeoManager.h" + +#include "TGeoTube.h" +#include "TGeoPara.h" +#include "TGeoCone.h" +#include "TGeoTrd2.h" +#include "TGeoCompositeShape.h" +#include "TGeoXtru.h" +#include "TGeoPhysicalNode.h" + +// forward declarations +Int_t CreateSensors(); +Int_t CreateSectors(); +Int_t CreateLadders(); +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength); +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY, + Int_t start); +TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ, + Double_t pitchZ, + Int_t nSectors); +TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation); +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile); +void PostProcessGdml(TGeoVolume* gdmlTop); +void CheckVolume(TGeoVolume* volume); +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren = kTRUE); +Double_t BeamPipeRadius(Double_t z); +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x); +TGeoVolume* ConstructSmallCone(Double_t coneDz); +TGeoVolume* ConstructBigCone(Double_t coneDz); + +// ------------- Version highlight ----------------------------------- + +const std::string gVersionHighlight = R"( +Summary: + This version adds passive materials imported from GDML model to the STS geometry: + * Taken from and largely correspond to mechanical CAD drawings of the detector + * Thermal insulation box: + - made out of carbon sandwitch panel (2mm carbon fiber sheet + layer of carbon foam + 2mm carbon fiber sheet) + - front window of complex shape with interface to MVD / target chamber + - back window with large aperture (2000 x 1200 mm) square cut into carbon foam + * Structural units: + - made of 2 complex shape aluminum C-Frames, 15mm thick + - placed at 25, 35, ... ,105 cm absolute Z + - contain front-end and power distribution boxes with equivalent X_0 values + + Scripted geometry tweaks: + * Ladders and cables are extended towards the read-out planes having same lengths in respective rows + * Adjusted form and shape of carbon ladder structures from L-type to X-type + * Reduced verbosity of this file + + Sensor arrangement is the same as in version v16g + + !! Important for this version is the discrepancy from the mechanical CAD w.r.t. front wall. + The square window was replaced by a round one to avoid overlaps with present beam pipe designs, e.g. pipe_v16b_1e +)"; + +// ------------- Steering variables ----------------------------------- + +// ---> Horizontal width of sensors [cm] +const Double_t gkSensorSizeX = 6.2; // was 6.2092; // 6.2 - Oleg CAD 15/05/2020 + +// ---> Thickness of sensors [cm] +const Double_t gkSensorThickness = 0.03; + +// ---> Vertical gap between chained sensors [cm] +const Double_t gkChainGapY = 0.00; + +// ---> Thickness of cables [cm] +const Double_t gkCableThickness = 0.02; + +// ---> Horizontal overlap of neighbouring ladders [cm] +const Double_t gkLadderOverlapX = 0.25; // delta X - Oleg CAD 14/05/2020 + +// ---> Vertical overlap of neighbouring sectors in a ladder [cm] +const Double_t gkSectorOverlapY = 0.46; // delta Y - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring sectors in a ladder [cm] +const Double_t gkSectorGapZ = 0.12; // gap + thickness = pitch // delta Z pitch = 0.15 - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring ladders [cm] +const Double_t gkLadderGapZ = 0.50 - 0.15; // for asym // 0.5 for sym // delta Z prime + +// ---> Gap in z between lowest sector to carbon support structure [cm] +const Double_t gkSectorGapZFrame = 0.280 - 0.025; // Oleg CAD 05/05/2020 // there is a 2.8 mm gap between the bottom side of the sensor and the top ledge of the carbon ladder + +// ---> Switch to construct / not to construct readout cables +const Bool_t gkConstructCables = kTRUE; + +// ---> Switch to construct / not to construct frames +const Bool_t gkConstructCones = kFALSE; // kTRUE; // switch this false by default for v15c and v16x +const Bool_t gkConstructFrames = kTRUE; // kFALSE; // switch this true by default for v15c and v16x +const Bool_t gkConstructSmallFrames = kTRUE; // kFALSE; +const Bool_t gkCylindricalFrames = kTRUE; // kFALSE; + +// ---> Size of the frame +const Double_t gkFrameThickness = 0.2; +const Double_t gkThinFrameThickness = 0.05; +const Double_t gkFrameStep = 4.0; // size of frame cell along y direction + +const Double_t gkCylinderDiaInner = 0.07; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) +const Double_t gkCylinderDiaOuter = 0.15; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) + +// ---> Switch to import / not to import the Passive materials from GDML file +//const Bool_t gkImportPassive = kTRUE; +const Bool_t gkImportPassive = kFALSE; + +// ---------------------------------------------------------------------------- + + +// -------------- Parameters of beam pipe in the STS region -------------- +// ---> Needed to compute stations and STS such as to avoid overlaps +const Double_t gkPipeZ1 = 22.0; +const Double_t gkPipeR1 = 1.8; +const Double_t gkPipeZ2 = 50.0; +const Double_t gkPipeR2 = 1.8; +const Double_t gkPipeZ3 = 125.0; +const Double_t gkPipeR3 = 5.5; + +//DE const Double_t gkPipeZ1 = 27.0; +//DE const Double_t gkPipeR1 = 1.05; +//DE const Double_t gkPipeZ2 = 160.0; +//DE const Double_t gkPipeR2 = 3.25; +// ---------------------------------------------------------------------------- + +//TString unitName[16] = // names of units for v16e +// { "Unit00D", +// "Unit01U", "Unit01D", +// "Unit02U", "Unit02D", +// "Unit03U", "Unit03D", +// "Unit04U", "Unit04D", +// "Unit05U", "Unit05D", +// "Unit06U", "Unit06D", +// "Unit07U", "Unit07D", +// "Unit08U" }; + +//TString unitName[32] = // names of units for v16f +// { "Unit00DR", "Unit00DL", +// "Unit01UR", "Unit01UL", "Unit01DR", "Unit01DL", +// "Unit02UR", "Unit02UL", "Unit02DR", "Unit02DL", +// "Unit03UR", "Unit03UL", "Unit03DR", "Unit03DL", +// "Unit04UR", "Unit04UL", "Unit04DR", "Unit04DL", +// "Unit05UR", "Unit05UL", "Unit05DR", "Unit05DL", +// "Unit06UR", "Unit06UL", "Unit06DR", "Unit06DL", +// "Unit07UR", "Unit07UL", "Unit07DR", "Unit07DL", +// "Unit08UR", "Unit08UL" }; + +TString unitName[32] = // names of units for v16g - while merging D and U parts + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", "Unit01R", "Unit01L", + "Unit02R", "Unit02L", "Unit02R", "Unit02L", + "Unit03R", "Unit03L", "Unit03R", "Unit03L", + "Unit04R", "Unit04L", "Unit04R", "Unit04L", + "Unit05R", "Unit05L", "Unit05R", "Unit05L", + "Unit06R", "Unit06L", "Unit06R", "Unit06L", + "Unit07R", "Unit07L", "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +TString unitName18[18] = // names of units for v16g + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", + "Unit02R", "Unit02L", + "Unit03R", "Unit03L", + "Unit04R", "Unit04L", + "Unit05R", "Unit05L", + "Unit06R", "Unit06L", + "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +// ------------- Other global variables ----------------------------------- +// ---> STS medium (for every volume except silicon) +TGeoMedium* gStsMedium = NULL; // will be set later +// ---> TGeoManager (too lazy to write out 'Manager' all the time +TGeoManager* gGeoMan = NULL; // will be set later +// ---------------------------------------------------------------------------- + + + + +// ============================================================================ +// ====== Main function ===== +// ============================================================================ + +void create_stsgeo_v19t(const char* geoTag="v19t") +{ + + // ------- Geometry file name (output) ---------------------------------- + TString geoFileName = "sts_"; + geoFileName = geoFileName + geoTag + ".geo.root"; + // -------------------------------------------------------------------------- + + + // ------- Open info file ----------------------------------------------- + TString infoFileName = geoFileName; + infoFileName.ReplaceAll("root", "info"); + fstream infoFile; + infoFile.open(infoFileName.Data(), fstream::out); + infoFile << "STS geometry created with create_stsgeo_v19t.C" << endl; + infoFile << gVersionHighlight << endl; + infoFile << "Global variables: " << endl; + infoFile << "Sensor thickness = " << gkSensorThickness << " cm" << endl; + infoFile << "Vertical gap in sensor chain = " + << gkChainGapY << " cm" << endl; + infoFile << "Vertical overlap of sensors = " + << gkSectorOverlapY << " cm" << endl; + infoFile << "Gap in z between neighbour sensors = " + << gkSectorGapZ << " cm" << endl; + infoFile << "Horizontal overlap of sensors = " + << gkLadderOverlapX << " cm" << endl; + infoFile << "Gap in z between neighbour ladders = " + << gkLadderGapZ << " cm" << endl; + if ( gkConstructCables ) + infoFile << "Cable thickness = " << gkCableThickness << " cm" << endl; + else + infoFile << "No cables" << endl; + infoFile << endl; + infoFile << "Beam pipe: R1 = " << gkPipeR1 << " cm at z = " + << gkPipeZ1 << " cm" << endl; + infoFile << "Beam pipe: R2 = " << gkPipeR2 << " cm at z = " + << gkPipeZ2 << " cm" << endl; + infoFile << "Beam pipe: R3 = " << gkPipeR3 << " cm at z = " + << gkPipeZ3 << " cm" << endl; + // -------------------------------------------------------------------------- + + + // ------- Load media from media file ----------------------------------- + FairGeoLoader* geoLoad = new FairGeoLoader("TGeo","FairGeoLoader"); + FairGeoInterface* geoFace = geoLoad->getGeoInterface(); + TString geoPath = gSystem->Getenv("VMCWORKDIR"); + TString medFile = geoPath + "/geometry/media.geo"; + geoFace->setMediaFile(medFile); + geoFace->readMedia(); + gGeoMan = gGeoManager; + // -------------------------------------------------------------------------- + + + // ----------------- Get and create the required media ----------------- + FairGeoMedia* geoMedia = geoFace->getMedia(); + FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder(); + + // ---> air + FairGeoMedium* mAir = geoMedia->getMedium("air"); + if ( ! mAir ) Fatal("Main", "FairMedium air not found"); + geoBuild->createMedium(mAir); + TGeoMedium* air = gGeoMan->GetMedium("air"); + if ( ! air ) Fatal("Main", "Medium air not found"); + + // ---> silicon + FairGeoMedium* mSilicon = geoMedia->getMedium("silicon"); + if ( ! mSilicon ) Fatal("Main", "FairMedium silicon not found"); + geoBuild->createMedium(mSilicon); + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + if ( ! silicon ) Fatal("Main", "Medium silicon not found"); + + // ---> carbon + FairGeoMedium* mCarbon = geoMedia->getMedium("carbon"); + if ( ! mCarbon ) Fatal("Main", "FairMedium carbon not found"); + geoBuild->createMedium(mCarbon); + TGeoMedium* carbon = gGeoMan->GetMedium("carbon"); + if ( ! carbon ) Fatal("Main", "Medium carbon not found"); + + // ---> STSBoxCarbonFoam + FairGeoMedium* mSTSBoxCarbonFoam = geoMedia->getMedium("STSBoxCarbonFoam"); + if ( ! mSTSBoxCarbonFoam ) Fatal("Main", "FairMedium STSBoxCarbonFoam not found"); + geoBuild->createMedium(mSTSBoxCarbonFoam); + TGeoMedium* STSBoxCarbonFoam = gGeoMan->GetMedium("STSBoxCarbonFoam"); + if ( ! STSBoxCarbonFoam ) Fatal("Main", "Medium STSBoxCarbonFoam not found"); + + // ---> STSBoxCarbonFibre + FairGeoMedium* mSTSBoxCarbonFibre = geoMedia->getMedium("STSBoxCarbonFibre"); + if ( ! mSTSBoxCarbonFibre ) Fatal("Main", "FairMedium STSBoxCarbonFibre not found"); + geoBuild->createMedium(mSTSBoxCarbonFibre); + TGeoMedium* STSBoxCarbonFibre = gGeoMan->GetMedium("STSBoxCarbonFibre"); + if ( ! STSBoxCarbonFibre ) Fatal("Main", "Medium STSBoxCarbonFibre not found"); + + // ---> STScable + FairGeoMedium* mSTScable = geoMedia->getMedium("STScable"); + if ( ! mSTScable ) Fatal("Main", "FairMedium STScable not found"); + geoBuild->createMedium(mSTScable); + TGeoMedium* STScable = gGeoMan->GetMedium("STScable"); + if ( ! STScable ) Fatal("Main", "Medium STScable not found"); + + // ---> Aluminium + FairGeoMedium* mAluminium = geoMedia->getMedium("aluminium"); + if ( ! mAluminium ) Fatal("Main", "FairMedium aluminium not found"); + geoBuild->createMedium(mAluminium); + TGeoMedium* aluminium = gGeoMan->GetMedium("aluminium"); + if ( ! aluminium ) Fatal("Main", "Medium aluminium not found"); + + // --- + gStsMedium = air; + // -------------------------------------------------------------------------- + + + // -------------- Create geometry and top volume ------------------------- + gGeoMan = (TGeoManager*)gROOT->FindObject("FAIRGeom"); +// gGeoMan->SetName("STSgeom"); + TGeoVolume* top = new TGeoVolumeAssembly("top"); +// TGeoBBox* topbox= new TGeoBBox("", 120., 120., 120.); +// TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air")); + gGeoMan->SetTopVolume(top); + // -------------------------------------------------------------------------- + + + // -------------- Create media ------------------------------------------ + /* + cout << endl; + cout << "===> Creating media...."; + cout << CreateMedia(); + cout << " media created" << endl; + TList* media = gGeoMan->GetListOfMedia(); + for (Int_t iMedium = 0; iMedium < media->GetSize(); iMedium++ ) { + cout << "Medium " << iMedium << ": " + << ((TGeoMedium*) media->At(iMedium))->GetName() << endl; + } + gStsMedium = gGeoMan->GetMedium("air"); + if ( ! gStsMedium ) Fatal("Main", "medium sts_air not found"); + */ + // -------------------------------------------------------------------------- + + + // --------------- Create sensors --------------------------------------- + cout << endl << endl; + cout << "===> Creating sensors...." << endl << endl; + infoFile << endl << "Sensors: " << endl; + Int_t nSensors = CreateSensors(); + for (Int_t iSensor = 1; iSensor <= nSensors; iSensor++) { + TString name = Form("Sensor%02d",iSensor); + TGeoVolume* sensor = gGeoMan->GetVolume(name); + + // add color to sensors + if (iSensor == 1) + sensor->SetLineColor(kRed); + if (iSensor == 2) + sensor->SetLineColor(kGreen); + if (iSensor == 3) + sensor->SetLineColor(kBlue); + if (iSensor == 4) + sensor->SetLineColor(kAzure); + if (iSensor == 5) + sensor->SetLineColor(kYellow); + if (iSensor == 6) + sensor->SetLineColor(kYellow); + if (iSensor == 7) + sensor->SetLineColor(kYellow); + + CheckVolume(sensor); + CheckVolume(sensor, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create sectors -------------------------------------- + cout << endl << endl; + cout << "===> Creating sectors...." << endl; + // infoFile << endl << "Sectors: " << endl; + Int_t nSectors = CreateSectors(); + for (Int_t iSector = 1; iSector <= nSectors; iSector++) { + // cout << endl; + TString name = Form("Sector%02d", iSector); + TGeoVolume* sector = gGeoMan->GetVolume(name); + CheckVolume(sector); + // CheckVolume(sector, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create ladders -------------------------------------- + cout << endl << endl; + cout << "===> Creating ladders...." << endl; + infoFile << endl << "Ladders:" << endl; + + TString name = ""; + TGeoVolume* ladder; + + + Int_t nLadders = CreateLadders(); + + for (Int_t iLadder = 1; iLadder <= nLadders; iLadder++) { + cout << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType0%02d", iLadder); // v19b + name = Form("LadderType00%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF1: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType1%02d", iLadder); // v19b + name = Form("LadderType01%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF2: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType10%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF3: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType11%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF4: ladder name: " << name << endl << endl; + } + // -------------------------------------------------------------------------- + + + // ---------------- Create cones ---------------------------------------- + Double_t coneDz = 1.64; + TGeoVolume* coneSmallVolum = ConstructSmallCone(coneDz); + if (!coneSmallVolum) Fatal("ConstructSmallCone", "Volume Cone not found"); + TGeoVolume* coneBigVolum = ConstructBigCone(coneDz); + if (!coneBigVolum) Fatal("ConstructBigCone", "Volume Cone not found"); + // -------------------------------------------------------------------------- + + + // ---------------- Create stations ------------------------------------- + cout << endl << endl; + cout << "===> Creating stations...." << endl; + infoFile << endl << "Stations: " << endl; + Int_t angle = 0; + nLadders = 0; + Int_t ladderTypes[16]; // there are max 16 ladders in one layer + TGeoTranslation* statTrans = NULL; + + TGeoVolume *myunit[32]; // units + +// Int_t statPos[8] = { 30, 40, 50, 60, 70, 80, 90, 100 }; // z positions of stations +// Int_t statPos[16] = { 28, 32, 38, 42, 48, 52, 58, 62, +// 68, 72, 78, 82, 88, 92, 98,102 }; // z positions of units +// Int_t statPos[16] = { 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units +// Int_t statPos18[18] = { 30, 30, // expanded for placement of Unit00 +// 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units + // v19h + Double_t statPos[16] = { 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of units + Double_t statPos18[18] = { 26.0, 26.0, // expanded for placement of Unit00 + 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of unit + +// // v19d +// Double_t statPos[16] = { 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units +// Double_t statPos18[18] = { 30.0, 30.0, // expanded for placement of Unit00 +// 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units + +////Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.9 , 3.7 , 3.7 , 4.2 , 4.2 }; // size of cutouts in stations +// Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.43, 3.04, 3.35, 3.96, 4.2 }; // size of cutouts in stations, derived from gapXYZ[x][1]/2 + + Int_t cone_size[8] = { 0, 0, 0, 1, 1, 1, 1, 1 }; // size of cones: 0 = small, 1 = large + + Double_t cone_offset[2] = { 0.305, 0.285 }; + +// Int_t allLadderTypes[8][16]= +// { { -1, -1, -1, -1, 10, 109, 9, 101, 1, 109, 9, 110, -1, -1, -1, -1 }, // station 1 +// { -1, -1, 111, 10, 110, 9, 109, 2, 102, 9, 109, 10, 110, 11, -1, -1 }, // station 2 +// { -1, -1, 14, 113, 12, 112, 12, 103, 3, 112, 12, 112, 13, 114, -1, -1 }, // station 3 +// { -1, 15, 114, 13, 112, 12, 112, 4, 104, 12, 112, 12, 113, 14, 115, -1 }, // station 4 +// { -1, 119, 18, 117, 17, 116, 16, 105, 5, 116, 16, 117, 17, 118, 19, -1 }, // station 5 +// { -1, 19, 118, 17, 117, 16, 116, 6, 106, 16, 116, 17, 117, 18, 119, -1 }, // station 6 +// { 21, 119, 18, 120, 20, 120, 20, 107, 7, 120, 20, 120, 20, 118, 19, 121 }, // station 7 +// { 119, 17, 123, 22, 122, 22, 122, 8, 108, 22, 122, 22, 122, 23, 117, 19 } }; // station 8 + +//============================================================================================== + +// explanation: type xyzz +// where x = carbon ladder orientation +// where y = FEB box orientation +// where zz = sensor arrangement on ladder +// with FEB orientation - v19b + Int_t allUnitTypes[16][16]= + { { -1, -1, -1, -1, 10, 0, 9, 0, 101, 0, 109, 0, -1, -1, -1, -1 }, // unit00D Station01 00 + { -1, -1, -1, -1, 0, 1109, 0, 1101, 0, 1009, 0, 1010, -1, -1, -1, -1 }, // unit01U Station01 01 + + { -1, -1, 0, 10, 0, 9, 0, 2, 0, 109, 0, 110, 0, 111, -1, -1 }, // unit01D Station02 02 + { -1, -1, 1111, 0, 1110, 0, 1109, 0, 1002, 0, 1009, 0, 1010, 0, -1, -1 }, // unit02U Station02 03 + + { -1, -1, 14, 0, 12, 0, 12, 0, 103, 0, 112, 0, 113, 0, -1, -1 }, // unit02D Station03 04 + { -1, -1, 0, 1113, 0, 1112, 0, 1103, 0, 1012, 0, 1012, 0, 1014, -1, -1 }, // unit03U Station03 05 + + { -1, 15, 0, 13, 0, 12, 0, 4, 0, 112, 0, 112, 0, 114, 0, -1 }, // unit03D Station04 06 + { -1, 0, 1114, 0, 1112, 0, 1112, 0, 1004, 0, 1012, 0, 1013, 0, 1015, -1 }, // unit04U Station04 07 + + { -1, 0, 18, 0, 17, 0, 16, 0, 105, 0, 116, 0, 117, 0, 119, -1 }, // unit04D Station05 08 + { -1, 1119, 0, 1117, 0, 1116, 0, 1105, 0, 1016, 0, 1017, 0, 1018, 0, -1 }, // unit05U Station05 09 + + { -1, 19, 0, 17, 0, 16, 0, 6, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05D Station06 10 + { -1, 0, 1118, 0, 1117, 0, 1116, 0, 1006, 0, 1016, 0, 1017, 0, 1019, -1 }, // unit06U Station06 11 + + { 21, 0, 25, 0, 20, 0, 20, 0, 107, 0, 120, 0, 120, 0, 127, 0 }, // unit06D Station07 12 + { 0, 1127, 0, 1120, 0, 1120, 0, 1107, 0, 1020, 0, 1020, 0, 1025, 0, 1021 }, // unit07U Station07 13 + + { 0, 24, 0, 22, 0, 22, 0, 8, 0, 122, 0, 122, 0, 123, 0, 126 }, // unit07D Station08 14 + { 1126, 0, 1123, 0, 1122, 0, 1122, 0, 1008, 0, 1022, 0, 1022, 0, 1024, 0 } }; // unit08U Station08 15 + +//============================================================================================== + +// without FEB orientation - v19a +// v19a Int_t allUnitTypes[16][16]= +// v19a { { -1, -1, -1, -1, 10, 0, 9, 0, 1, 0, 9, 0, -1, -1, -1, -1 }, // unit00D Station01 00 +// v19a { -1, -1, -1, -1, 0, 109, 0, 101, 0, 109, 0, 110, -1, -1, -1, -1 }, // unit01U Station01 01 +// v19a { -1, -1, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, -1, -1 }, // unit01D Station02 02 +// v19a { -1, -1, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, -1, -1 }, // unit02U Station02 03 +// v19a { -1, -1, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, -1, -1 }, // unit02D Station03 04 +// v19a { -1, -1, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, -1, -1 }, // unit03U Station03 05 +// v19a { -1, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, -1 }, // unit03D Station04 06 +// v19a { -1, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, -1 }, // unit04U Station04 07 +// v19a { -1, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, -1 }, // unit04D Station05 08 +// v19a { -1, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05U Station05 09 +// v19a { -1, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, -1 }, // unit05D Station06 10 +// v19a { -1, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, -1 }, // unit06U Station06 11 +// v19a { 21, 0, 25, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 27, 0 }, // unit06D Station07 12 +// v19a { 0, 127, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 125, 0, 121 }, // unit07U Station07 13 +// v19a { 0, 24, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 26 }, // unit07D Station08 14 +// v19a { 126, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 124, 0 } }; // unit08U Station08 15 + + +// unitTypes[0] = { 0, 0, 0, 0, 10, 0, 9, 0, 1, 0, 9, 0, 0, 0, 0, 0 }; // unit 0D +// unitTypes[1] = { 0, 0, 0, 0, 0, 109, 0, 101, 0, 109, 0, 110, 0, 0, 0, 0 }; // unit 1U +// unitTypes[2] = { 0, 0, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, 0, 0 }; // unit 1D +// unitTypes[3] = { 0, 0, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, 0, 0 }; // unit 2U +// unitTypes[4] = { 0, 0, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, 0, 0 }; // unit 2D +// unitTypes[5] = { 0, 0, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, 0, 0 }; // unit 3U +// unitTypes[6] = { 0, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, 0 }; // unit 3D +// unitTypes[7] = { 0, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, 0 }; // unit 4U +// unitTypes[8] = { 0, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, 0 }; // unit 4D +// unitTypes[9] = { 0, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, 0 }; // unit 5U +// unitTypes[10] = { 0, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, 0 }; // unit 5D +// unitTypes[11] = { 0, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, 0 }; // unit 6U +// unitTypes[12] = { 21, 0, 18, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 19, 0 }; // unit 6D +// unitTypes[13] = { 0, 119, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 118, 0, 121 }; // unit 7U +// unitTypes[14] = { 0, 17, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 19 }; // unit 7D +// unitTypes[15] = { 119, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 117, 0 }; // unit 8U + + +// // generate unit +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) +// for (Int_t iLadder = 0; iLadder < 16; iLadder++) +// { +// allUnitTypes[iUnit][iLadder] = 0; +// if ((iUnit % 2 == 0) && (allLadderTypes[iUnit/2][iLadder] < 100)) // if carbon structure is oriented upstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// if ((iUnit % 2 == 1) && (allLadderTypes[iUnit/2][iLadder] >= 100)) // if carbon structure is oriented downstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// } + + + // dump unit + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << "DE unitTypes[" << iUnit << "] = { "; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + { + cout << allUnitTypes[iUnit][iLadder]; + if (iLadder < 15) + cout << ", "; + else + cout << " };"; + } + cout << endl; + } + + + // --- Units 01 - 16 + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << endl; + + nLadders = 0; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + if (allUnitTypes[iUnit][iLadder] >= 0) + { + ladderTypes[nLadders] = allUnitTypes[iUnit][iLadder]; + cout << "DE ladderTypes[" << nLadders << "] = " << allUnitTypes[iUnit][iLadder] << ";" << endl; + nLadders++; + } + myunit[iUnit*2+0] = ConstructUnit(0, iUnit*2+0, nLadders, ladderTypes, iUnit/2+1); + myunit[iUnit*2+1] = ConstructUnit(1, iUnit*2+1, nLadders, ladderTypes, iUnit/2+1); + +// if (gkConstructCones) { +// if (iUnit%2 == 0) +// angle = 90; +// else +// angle = -90; +// +// // upstream +// TGeoRotation* coneRot11 = new TGeoRotation; +// coneRot11->RotateZ(angle); +// coneRot11->RotateY(180); +// TGeoCombiTrans* conePosRot11 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-cone_offset[cone_size[iUnit]]-gkLadderGapZ/2., coneRot11); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 1, conePosRot11); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 1, conePosRot11); +// +// // downstream +// TGeoRotation* coneRot12 = new TGeoRotation; +// coneRot12->RotateZ(angle); +// TGeoCombiTrans* conePosRot12 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+cone_offset[cone_size[iUnit]]+gkLadderGapZ/2., coneRot12); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 2, conePosRot12); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 2, conePosRot12); +// +// myunit[iUnit]->GetShape()->ComputeBBox(); +// } + +// CheckVolume(myunit[iUnit]); +// CheckVolume(myunit[iUnit], infoFile); + if ((iUnit%2 == 0)||(iUnit == 15)) + { + CheckVolume(myunit[iUnit*2+0]); + CheckVolume(myunit[iUnit*2+0], infoFile); + CheckVolume(myunit[iUnit*2+1]); + CheckVolume(myunit[iUnit*2+1], infoFile); + } + infoFile << "Position z = " << statPos[iUnit] << endl; + } + // -------------------------------------------------------------------------- + + + // --------------- Create STS volume ------------------------------------ + cout << endl << endl; + cout << "===> Creating STS...." << endl; + +// // --- Determine size of STS box +// Double_t stsX = 0.; +// Double_t stsY = 0.; +// Double_t stsZ = 0.; +// Double_t stsBorder = 2*5.; // 5 cm space for carbon ladders on each side +// for (Int_t iStation = 1; iStation<=8; iStation++) { +// TString statName = Form("Station%02d", iStation); +// TGeoVolume* station = gGeoMan->GetVolume(statName); +// TGeoBBox* shape = (TGeoBBox*) station->GetShape(); +// stsX = TMath::Max(stsX, 2.* shape->GetDX() ); +// stsY = TMath::Max(stsY, 2.* shape->GetDY() ); +// cout << "Station " << iStation << ": Y " << stsY << endl; +// } +// // --- Some border around the stations +// stsX += stsBorder; +// stsY += stsBorder; +// stsZ = ( statPos[7] - statPos[0] ) + stsBorder; +// +// // --- Create box around the stations +// new TGeoBBox("stsBox", stsX/2., stsY/2., stsZ/2.); +// cout << "size of STS box: x " << stsX << " - y " << stsY << " - z " << stsZ << endl; +// +// // --- Create cone hosting the beam pipe +// // --- One straight section with constant radius followed by a cone +// Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +// Double_t z2 = gkPipeZ2; +// Double_t z3 = statPos[7] + 0.5 * stsBorder; // end of STS box +// Double_t r1 = BeamPipeRadius(z1); +// Double_t r2 = BeamPipeRadius(z2); +// Double_t r3 = BeamPipeRadius(z3); +// r1 += 0.01; // safety margin +// r2 += 0.01; // safety margin +// r3 += 0.01; // safety margin +// +// cout << endl; +// cout << z1 << " " << r1 << endl; +// cout << z2 << " " << r2 << endl; +// cout << z3 << " " << r3 << endl; +// +// cout << endl; +// cout << "station1 : " << BeamPipeRadius(statPos[0]) << endl; +// cout << "station2 : " << BeamPipeRadius(statPos[1]) << endl; +// cout << "station3 : " << BeamPipeRadius(statPos[2]) << endl; +// cout << "station4 : " << BeamPipeRadius(statPos[3]) << endl; +// cout << "station5 : " << BeamPipeRadius(statPos[4]) << endl; +// cout << "station6 : " << BeamPipeRadius(statPos[5]) << endl; +// cout << "station7 : " << BeamPipeRadius(statPos[6]) << endl; +// cout << "station8 : " << BeamPipeRadius(statPos[7]) << endl; +// +// // TGeoPcon* cutout = new TGeoPcon("stsCone", 0., 360., 3); // 2.*TMath::Pi(), 3); +// // cutout->DefineSection(0, z1, 0., r1); +// // cutout->DefineSection(1, z2, 0., r2); +// // cutout->DefineSection(2, z3, 0., r3); +// new TGeoTrd2("stsCone1", r1, r2, r1, r2, (z2-z1)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans1 = new TGeoTranslation("trans1", 0., 0., -(z3-z1)/2.+(z2-z1)/2.); +// trans1->RegisterYourself(); +// new TGeoTrd2("stsCone2", r2, r3, r2, r3, (z3-z2)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans2 = new TGeoTranslation("trans2", 0., 0., +(z3-z1)/2.-(z3-z2)/2.); +// trans2->RegisterYourself(); +// +////DE Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +////DE Double_t z2 = statPos[7] + 0.5 * stsBorder; // end of STS box +////DE Double_t slope = (gkPipeR2 - gkPipeR1) / (gkPipeZ2 - gkPipeZ1); +////DE Double_t r1 = gkPipeR1 + slope * (z1 - gkPipeZ1); // at start of STS +////DE Double_t r2 = gkPipeR1 + slope * (z2 - gkPipeZ1); // at end of STS +////DE r1 += 0.1; // safety margin +////DE r2 += 0.1; // safety margin +////DE // new TGeoCone("stsCone", stsZ/2., 0., r1, 0., r2); +////DE new TGeoTrd2("stsCone", r1, r2, r1, r2, stsZ/2.); + + + // // Create holding/cooling plates + // static std::vector< std::vector<Double_t> > plateSizes = { + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // }; + + // // 8-vertex cut-outs { minWidth, maxWidth, minHeight, maxHeight } + // static std::vector< std::vector<Double_t> > plateCutOuts = { + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 17.6, 47.6 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 49.0, 79.0 }, + // { 85.5,115.5, 51.5, 82.8 }, + // { 85.5,115.5, 59.0, 91.4 }, + // { 85.5,115.5, 68.0, 99.0 }, + // }; + + // for (Int_t iPlate = 0; iPlate < 9; iPlate++) { + // Int_t iUnit = iPlate * 2; + // TGeoBBox* outerPlate = new TGeoBBox(Form("outerPlate%02d",iPlate), + // plateSizes[iPlate][0], plateSizes[iPlate][1], plateSizes[iPlate][2]); + + // TGeoBBox* unitShapeR = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+0])->GetShape(); + // TGeoBBox* unitShapeL = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+1])->GetShape(); + + // Double_t maxDx = (unitShapeR->GetDX() + unitShapeL->GetDX()) / 2.; + // Double_t maxDy = TMath::Max(unitShapeR->GetDY(), unitShapeL->GetDY()); + // cout << maxDy << endl; + + // Double_t* cutOutX = new Double_t[8]; + // Double_t* cutOutY = new Double_t[8]; + + // cutOutX[0] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[0] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[1] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[1] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[2] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[2] = 1/2. * plateCutOuts[iPlate][2]; + // cutOutX[3] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[3] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[4] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[4] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[5] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[5] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[6] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[6] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[7] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[7] = 1/2. * plateCutOuts[iPlate][2]; + + // TGeoXtru* cutOutShape = new TGeoXtru(2); + // cutOutShape->SetName(Form("innerPlate%02d", iPlate)); + // cutOutShape->DefinePolygon(8, cutOutX, cutOutY); + // cutOutShape->DefineSection(0, -1*plateSizes[iPlate][2]-1e-7); + // cutOutShape->DefineSection(1, +1*plateSizes[iPlate][2]+1e-7); + + // TGeoShape* plateShape = new TGeoCompositeShape(Form("PlateShape%02d",iPlate), Form("outerPlate%02d-innerPlate%02d",iPlate,iPlate)); + // TGeoVolume* plate = new TGeoVolume(Form("Plate%02d", iPlate), plateShape, gGeoManager->GetMedium("aluminium")); + // plate->SetLineColor(kRed); + // plate->SetTransparency(65); + // plate->GetShape()->ComputeBBox(); + // } + + // --- Create STS volume + TString stsName = "sts_"; + stsName += geoTag; + +// TGeoShape* stsShape = new TGeoCompositeShape("stsShape", +// "stsBox-stsCone1:trans1-stsCone2:trans2"); +// TGeoVolume* sts = new TGeoVolume(stsName.Data(), stsShape, gStsMedium); + + Double_t stsBorder = 2 * 5.; + + TGeoVolume* sts = new TGeoVolumeAssembly(stsName.Data()); + + // --- Place stations in the STS + Double_t stsPosZ = 0.5 * ( statPos[15] + statPos[0] ); // todo units: update statPos[7] + // cout << "stsPosZ " << stsPosZ << " " << statPos[15] << " " << statPos[0] << "*****" << endl; + +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) { + for (Int_t iUnit = 0; iUnit < 18; iUnit++) { +// for (Int_t iUnit = 0; iUnit < 32; iUnit++) { + TGeoVolume* station = gGeoMan->GetVolume(unitName18[iUnit]); +// Double_t posZ = statPos[iUnit] - stsPosZ; + Double_t posZ = statPos18[iUnit] - stsPosZ; +// Double_t posZ = statPos[iUnit/2] - stsPosZ; + TGeoTranslation* trans = new TGeoTranslation(0., 0., posZ); + sts->AddNode(station, iUnit+1, trans); + sts->GetShape()->ComputeBBox(); + } + + // --- Import passive elements from GDML file + if (gkImportPassive) { + ImportPassive(sts, geoTag, infoFile); + } + + cout << endl; + CheckVolume(sts); + // -------------------------------------------------------------------------- + + + // --------------- Finish ----------------------------------------------- + TGeoTranslation* stsTrans = new TGeoTranslation(0., 0., stsPosZ); + top->AddNode(sts, 1, stsTrans); + top->GetShape()->ComputeBBox(); + cout << endl << endl; + + CheckVolume(top); + cout << endl << endl; + gGeoMan->CloseGeometry(); + gGeoMan->CheckOverlaps(0.0001); + gGeoMan->PrintOverlaps(); + gGeoMan->CheckOverlaps(0.0001, "s"); + gGeoMan->PrintOverlaps(); + gGeoMan->Test(); + + TFile* geoFile = new TFile(geoFileName, "RECREATE"); + top->Write(); + cout << endl; + cout << "Geometry " << top->GetName() << " written to " + << geoFileName << endl; + geoFile->Close(); + + TString geoFileName_ = "sts_"; + geoFileName_ = geoFileName_ + geoTag + "_geo.root"; + + geoFile = new TFile(geoFileName_, "RECREATE"); + gGeoMan->Write(); // use this is you want GeoManager format in the output + geoFile->Close(); + + TString geoFileName__ = "sts_"; + geoFileName_ = geoFileName__ + geoTag + "-geo.root"; + sts->Export(geoFileName_); + + geoFile = new TFile(geoFileName_, "UPDATE"); + stsTrans->Write(); + geoFile->Close(); + + // gGeoManager->FindVolumeFast("LadderType10_CarbonElement")->Draw("ogl"); + top->Draw("ogl"); + gGeoManager->SetVisLevel(8); + + infoFile.close(); + +} +// ============================================================================ +// ====== End of main function ===== +// ============================================================================ + + + + + +// **************************************************************************** +// ***** Definition of media, sensors, sectors and ladders ***** +// ***** ***** +// ***** Decoupled from main function for better readability ***** +// **************************************************************************** + + +/** =========================================================================== + ** Create media + ** + ** Currently created: air, active silicon, passive silion + ** + ** Not used for the time being + **/ +Int_t CreateMedia() { + + Int_t nMedia = 0; + Double_t density = 0.; + + // --- Material air + density = 1.205e-3; // [g/cm^3] + TGeoMixture* matAir = new TGeoMixture("sts_air", 3, density); + matAir->AddElement(14.0067, 7, 0.755); // Nitrogen + matAir->AddElement(15.999, 8, 0.231); // Oxygen + matAir->AddElement(39.948, 18, 0.014); // Argon + + // --- Material silicon + density = 2.33; // [g/cm^3] + TGeoElement* elSi = gGeoMan->GetElementTable()->GetElement(14); + TGeoMaterial* matSi = new TGeoMaterial("matSi", elSi, density); + + + // --- Air (passive) + TGeoMedium* medAir = new TGeoMedium("air", nMedia++, matAir); + medAir->SetParam(0, 0.); // is passive + medAir->SetParam(1, 1.); // is in magnetic field + medAir->SetParam(2, 20.); // max. field [kG] + medAir->SetParam(6, 0.001); // boundary crossing precision [cm] + + + // --- Active silicon for sensors + TGeoMedium* medSiAct = new TGeoMedium("silicon", + nMedia++, matSi); + medSiAct->SetParam(0, 1.); // is active + medSiAct->SetParam(1, 1.); // is in magnetic field + medSiAct->SetParam(2, 20.); // max. field [kG] + medSiAct->SetParam(6, 0.001); // boundary crossing precisison [cm] + + // --- Passive silicon for cables + TGeoMedium* medSiPas = new TGeoMedium("carbon", + nMedia++, matSi); + medSiPas->SetParam(0, 0.); // is passive + medSiPas->SetParam(1, 1.); // is in magnetic field + medSiPas->SetParam(2, 20.); // max. field [kG] + medSiPas->SetParam(6, 0.001); // boundary crossing precisison [cm] + + return nMedia; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sensors + ** + ** Sensors are created as volumes with box shape and active silicon as medium. + ** Four kinds of sensors: 3.2x2.2, 6.2x2.2, 6.2x4.2, 6.2x6.2 + **/ +Int_t CreateSensors() { + + Int_t nSensors = 0; + + Double_t xSize = 0.; + Double_t ySize = 0.; + Double_t zSize = gkSensorThickness; + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + + + // --- Sensor type 01: Small sensor (6.2 cm x 2.2 cm) + xSize = gkSensorSizeX; + ySize = 2.2; + TGeoBBox* shape_sensor01 = new TGeoBBox("sensor01", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor01", shape_sensor01, silicon); + nSensors++; + + + // --- Sensor type 02: Medium sensor (6.2 cm x 4.2 cm) + xSize = gkSensorSizeX; + ySize = 4.2; + TGeoBBox* shape_sensor02 = new TGeoBBox("sensor02", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor02", shape_sensor02, silicon); + nSensors++; + + + // --- Sensor type 03: Big sensor (6.2 cm x 6.2 cm) + xSize = gkSensorSizeX; + ySize = 6.2; + TGeoBBox* shape_sensor03 = new TGeoBBox("sensor03", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor03", shape_sensor03, silicon); + nSensors++; + + + // --- Sensor type 04: Big sensor (6.2 cm x 12.4 cm) + xSize = gkSensorSizeX; + ySize = 12.4; + TGeoBBox* shape_sensor04 = new TGeoBBox("sensor04", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor04", shape_sensor04, silicon); + nSensors++; + + + // below are extra small sensors, those are not available in the CAD model + + // --- Sensor Type 05: Half small sensor (4 cm x 2.5 cm) + xSize = 4.0; + ySize = 2.5; + TGeoBBox* shape_sensor05 = new TGeoBBox("sensor05", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor05", shape_sensor05, silicon); + nSensors++; + + + // --- Sensor type 06: Additional "in hole" sensor (3.1 cm x 4.2 cm) + xSize = 3.1; + ySize = 4.2; + TGeoBBox* shape_sensor06 = new TGeoBBox("sensor06", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor06", shape_sensor06, silicon); + nSensors++; + + + // --- Sensor type 07: Mini Medium sensor (1.5 cm x 4.2 cm) + xSize = 1.5; + ySize = 4.2; + TGeoBBox* shape_sensor07 = new TGeoBBox("sensor07", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor07", shape_sensor07, silicon); + nSensors++; + + + return nSensors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sectors + ** + ** A sector is either a single sensor or several chained sensors. + ** It is implemented as TGeoVolumeAssembly. + ** Currently available: + ** - single sensors of type 1 - 4 + ** - two chained sensors of type 4 + ** - three chained sensors of type 4 + **/ +Int_t CreateSectors() { + + Int_t nSectors = 0; + + TGeoVolume* sensor01 = gGeoMan->GetVolume("Sensor01"); + TGeoVolume* sensor02 = gGeoMan->GetVolume("Sensor02"); + TGeoVolume* sensor03 = gGeoMan->GetVolume("Sensor03"); + TGeoVolume* sensor04 = gGeoMan->GetVolume("Sensor04"); + TGeoVolume* sensor05 = gGeoMan->GetVolume("Sensor05"); + TGeoVolume* sensor06 = gGeoMan->GetVolume("Sensor06"); + TGeoVolume* sensor07 = gGeoMan->GetVolume("Sensor07"); + // TGeoBBox* box4 = (TGeoBBox*) sensor04->GetShape(); + + // --- Sector type 1: single sensor of type 1 + TGeoVolumeAssembly* sector01 = new TGeoVolumeAssembly("Sector01"); + sector01->AddNode(sensor01, 1); + sector01->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 2: single sensor of type 2 + TGeoVolumeAssembly* sector02 = new TGeoVolumeAssembly("Sector02"); + sector02->AddNode(sensor02, 1); + sector02->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 3: single sensor of type 3 + TGeoVolumeAssembly* sector03 = new TGeoVolumeAssembly("Sector03"); + sector03->AddNode(sensor03, 1); + sector03->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 4: single sensor of type 4 + TGeoVolumeAssembly* sector04 = new TGeoVolumeAssembly("Sector04"); + sector04->AddNode(sensor04, 1); + sector04->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 5: single sensor of type 5 + TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); + sector05->AddNode(sensor05, 1); + sector05->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 6: single sensor of type 6 + TGeoVolumeAssembly* sector06 = new TGeoVolumeAssembly("Sector06"); + sector06->AddNode(sensor06, 1); + sector06->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 7: single sensor of type 7 + TGeoVolumeAssembly* sector07 = new TGeoVolumeAssembly("Sector07"); + sector07->AddNode(sensor07, 1); + sector07->GetShape()->ComputeBBox(); + nSectors++; + +// // --- Sector type 5: two sensors of type 4 +// TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); +// Double_t shift5 = 0.5 * gkChainGapY + box4->GetDY(); +// TGeoTranslation* transD5 = +// new TGeoTranslation("td", 0., -1. * shift5, 0.); +// TGeoTranslation* transU5 = +// new TGeoTranslation("tu", 0., shift5, 0.); +// sector05->AddNode(sensor04, 1, transD5); +// sector05->AddNode(sensor04, 2, transU5); +// sector05->GetShape()->ComputeBBox(); +// nSectors++; + + return nSectors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create ladders + ** + ** Ladders are the building blocks of the stations. They contain + ** several modules placed one after the other along the z axis + ** such that the sectors are arranged vertically (with overlap). + ** + ** A ladder is constructed out of two half ladders, the second of which + ** is rotated in the x-y plane by 180 degrees and displaced + ** in z direction. + **/ +Int_t CreateLadders() { + + Int_t nLadders = 0; + + // --- Some variables + Int_t nSectors = 0; + Int_t sectorTypes[10]; + TGeoBBox* shape = NULL; + TString s0name; + TString hlname; + char align; + TGeoVolume* s0vol = NULL; + TGeoVolume* halfLadderU = NULL; + TGeoVolume* halfLadderD = NULL; + + // --- Ladders 01-23 + Int_t allSectorTypes[27][6] = { { 1, 2, 3, 3, 0, -1 }, // ladder 01 - 5 - last column defines alignment of small sensors + { 1, 2, 3, 3, 0, 0 }, // ladder 02 - 5 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, -1 }, // ladder 03 - 6 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 04 - 6 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, -1 }, // ladder 05 - 7 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 06 - 7 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 07 - last column defines alignment of small sensors + { 3, 4, 4, 4, 0, 0 }, // ladder 08 - last column defines alignment of small sensors + + { 1, 1, 2, 3, 3, 0 }, // ladder 09 - last column defines alignment of small sensors + { 1, 1, 2, 2, 3, 0 }, // ladder 10 - last column defines alignment of small sensors + { 2, 2, 0, 0, 0, 0 }, // ladder 11 - last column defines alignment of small sensors + { 2, 2, 2, 3, 4, 0 }, // ladder 12 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 13 - last column defines alignment of small sensors + + { 2, 3, 4, 0, 0, 0 }, // ladder 14 - last column defines alignment of small sensors + { 3, 3, 0, 0, 0, 0 }, // ladder 15 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 16 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 17 - last column defines alignment of small sensors + { 3, 4, 4, 0, 0, 0 }, // ladder 18 - last column defines alignment of small sensors + + { 4, 4, 0, 0, 0, 0 }, // ladder 19 - last column defines alignment of small sensors + { 1, 2, 4, 4, 4, 0 }, // ladder 20 - last column defines alignment of small sensors + { 4, 0, 0, 0, 0, 0 }, // ladder 21 - last column defines alignment of small sensors + { 2, 3, 4, 4, 4, 0 }, // ladder 22 - last column defines alignment of small sensors + { 2, 3, 3, 4, 4, 0 }, // ladder 23 - last column defines alignment of small sensors + + { 2, 3, 4, 4, 0, 0 }, // ladder 24 - copy of 17 with different total length + { 3, 4, 4, 0, 0, 0 }, // ladder 25 - copy of 18 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 26 - copy of 19 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 27 - copy of 19 with different total length + }; // 8 full - 19 partial ladders + +// Issue #405 +// Counting from the most upstream ladder, the gaps between sensors are as follows: +// 01 (most upstream): 41.3mm +// 02: 41.3mm +// 03: 42.0mm +// 04: 48.6mm +// 05: 60.8mm +// 06: 67.0mm +// 07: 79.2mm +// 08 (most downstream): 88.0mm + + Double_t pitchZ = 0; + Double_t gapXYZ[27][3] = { + { 0., 4.13, 0. }, // ladder 01 + { 0., 4.13, 0. }, // ladder 02 + { 0., 4.20, 0. }, // ladder 03 + { 0., 4.86, 0. }, // ladder 04 + { 0., 6.08, 0. }, // ladder 05 + { 0., 6.70, 0. }, // ladder 06 + { 0., 7.92, 0. }, // ladder 07 + { 0., 8.80, 0. }, // ladder 08 + { 0., -gkSectorOverlapY, 0. }, // ladder 09 + { 0., -gkSectorOverlapY, 0. }, // ladder 10 + { 0., -gkSectorOverlapY, 0. }, // ladder 11 + { 0., -gkSectorOverlapY, 0. }, // ladder 12 + { 0., -gkSectorOverlapY, 0. }, // ladder 13 + { 0., -gkSectorOverlapY, 0. }, // ladder 14 + { 0., -gkSectorOverlapY, 0. }, // ladder 15 + { 0., -gkSectorOverlapY, 0. }, // ladder 16 + { 0., -gkSectorOverlapY, 0. }, // ladder 17 + { 0., -gkSectorOverlapY, 0. }, // ladder 18 + { 0., -gkSectorOverlapY, 0. }, // ladder 19 + { 0., -gkSectorOverlapY, 0. }, // ladder 20 + { 0., -gkSectorOverlapY, 0. }, // ladder 21 + { 0., -gkSectorOverlapY, 0. }, // ladder 22 + { 0., -gkSectorOverlapY, 0. }, // ladder 23 + + { 0., -gkSectorOverlapY, 0. }, // ladder 24 - copy of 17 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 25 - copy of 18 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 26 - copy of 19 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 27 - copy of 19 with different total length + }; + + Double_t ladderLength[27] = { + 48.0, // ladder 01 + 48.0, // ladder 02 + 64.0, // ladder 03 + 64.0, // ladder 04 + 80.0, // ladder 05 + 80.0, // ladder 06 + 92.0, // ladder 07 + 96.0, // ladder 08 + 48.0, // ladder 09 + 48.0, // ladder 10 + 48.0, // ladder 11 + 64.0, // ladder 12 + 64.0, // ladder 13 + 64.0, // ladder 14 + 64.0, // ladder 15 + 80.0, // ladder 16 + 80.0, // ladder 17 + 80.0, // ladder 18 + 80.0, // ladder 19 + 92.0, // ladder 20 + 92.0, // ladder 21 + 96.0, // ladder 22 + 96.0, // ladder 23 + + 96.0, // ladder 24 - copy of 17 with different total length + 92.0, // ladder 25 - copy of 18 with different total length + 96.0, // ladder 26 - copy of 19 with different total length + 92.0, // ladder 27 - copy of 19 with different total length + }; +// ======================================================================== + + // calculate Z shift for ladders with and without gaps in the center + s0name = Form("Sector%02d", allSectorTypes[0][0]); + s0vol = gGeoMan->GetVolume(s0name); + shape = (TGeoBBox*) s0vol->GetShape(); + +// ======================================================================== + + for (Int_t iLadder = 0; iLadder < 27; iLadder++) + { + cout << endl; + nSectors = 0; + for (Int_t i=0; i < 5; i++) + if (allSectorTypes[iLadder][i] != 0) + { + sectorTypes[nSectors] = allSectorTypes[iLadder][i]; // copy sectors for this ladder + cout << "DE iLadder " << iLadder+1 << " sectorTypes[" << nSectors << "] = " << allSectorTypes[iLadder][i] << ";" << endl; + nSectors++; // count how many sectors are in this ladder + } + + // always set displacement in z between upper and lower half ladder + gapXYZ[iLadder][2] = 2. * shape->GetDZ() + gkSectorGapZ; + + // define additional offset to carbon ladder for half ladders with less than 5 sensors + pitchZ = 2. * shape->GetDZ() + gkSectorGapZ; + + if (allSectorTypes[iLadder][5] == 0) + align = 'l'; + else + align = 'r'; + hlname = Form("HalfLadder%02du", iLadder+1); + // build upper half ladder + Int_t Ustart = 1; + if (iLadder < 8) + Ustart = 0; + halfLadderU = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2., Ustart); // mirrored + + if (allSectorTypes[iLadder][5] == 0) + align = 'r'; + else + align = 'l'; + hlname = Form("HalfLadder%02dd", iLadder+1); + // build lower half ladder + Int_t Dstart = 0; + if (iLadder < 8) + Dstart = 1; + halfLadderD = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2., Dstart); // mirrored + + // at this point half ladders are constructed + + // build all 4 possible ladders types for this sensor arrangement + ConstructLadder( iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19a + ConstructLadder( 100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19b + + ConstructLadder(1000+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19k + ConstructLadder(1100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19k + + nLadders++; + } + + return nLadders; +} +/** ======================================================================= **/ + + + +// **************************************************************************** +// ***** ***** +// ***** Generic functions for the construction of STS elements ***** +// ***** ***** +// ***** module: volume (made of a sector and a cable) ***** +// ***** haf ladder: assembly (made of modules) ***** +// ***** ladder: assembly (made of two half ladders) ***** +// ***** station: volume (made of ladders) ***** +// ***** ***** +// **************************************************************************** + + + +/** =========================================================================== + ** Construct a module + ** + ** A module is a sector plus the readout cable extending from the + ** top of the sector. The cable is made from passive silicon. + ** The cable has the same x size as the sector. + ** Its thickness is given by the global variable gkCableThickness. + ** The cable length is a parameter. + ** The sensor(s) of the sector is/are placed directly in the module; + ** the sector is just auxiliary for the proper placement. + ** + ** Arguments: + ** name volume name + ** sector pointer to sector volume + ** cableLength length of cable + **/ +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength) { + + // --- Check sector volume + if ( ! sector ) Fatal("CreateModule", "Sector volume not found!"); + + // --- Get size of sector + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + + // --- Get size of cable + Double_t cableX = sectorX; + Double_t cableY = cableLength; + Double_t cableZ = gkCableThickness; + + // --- Create module volume + Double_t moduleX = TMath::Max(sectorX, cableX); + Double_t moduleY = sectorY + cableLength; + + Double_t moduleZ = TMath::Max(sectorZ, cableZ); + + TGeoVolume* module = gGeoManager->MakeBox(name, gStsMedium, + moduleX/2., + moduleY/2., + moduleZ/2.); + + // --- Position of sector in module + // --- Sector is centred in x and z and aligned to the bottom + Double_t sectorXpos = 0.; + Double_t sectorYpos = 0.5 * (sectorY - moduleY); + Double_t sectorZpos = 0.; + + + // --- Get sensor(s) from sector + Int_t nSensors = sector->GetNdaughters(); + for (Int_t iSensor = 0; iSensor < nSensors; iSensor++) { + TGeoNode* sensor = sector->GetNode(iSensor); + + // --- Calculate position of sensor in module + const Double_t* xSensTrans = sensor->GetMatrix()->GetTranslation(); + Double_t sensorXpos = sectorXpos + xSensTrans[0]; + Double_t sensorYpos = sectorYpos + xSensTrans[1]; + Double_t sensorZpos = sectorZpos + xSensTrans[2]; + TGeoTranslation* sensTrans = new TGeoTranslation("sensTrans", + sensorXpos, + sensorYpos, + sensorZpos); + + // --- Add sensor volume to module + TGeoVolume* sensVol = sensor->GetVolume(); + module->AddNode(sensor->GetVolume(), iSensor+1, sensTrans); + module->GetShape()->ComputeBBox(); + } + + + // --- Create cable volume, if necessary, and place it in module + // --- Cable is centred in x and z and aligned to the top + if ( gkConstructCables && cableLength > 0.0001 ) { + TString cableName = TString(name) + "_cable"; + TGeoMedium* cableMedium = gGeoMan->GetMedium("STScable"); + if ( ! cableMedium ) Fatal("CreateModule", "Medium STScable not found!"); + TGeoVolume* cable = gGeoManager->MakeBox(cableName.Data(), + cableMedium, + cableX / 2., + cableY / 2., + cableZ / 2.); + // add color to cables + cable->SetLineColor(kOrange); + cable->SetTransparency(60); + Double_t cableXpos = 0.; + Double_t cableYpos = sectorY + 0.5 * cableY - 0.5 * moduleY; + Double_t cableZpos = 0.; + TGeoTranslation* cableTrans = new TGeoTranslation("cableTrans", + cableXpos, + cableYpos, + cableZpos); + module->AddNode(cable, 1, cableTrans); + module->GetShape()->ComputeBBox(); + } + + return module; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a half ladder + ** + ** A half ladder is a virtual volume (TGeoVolumeAssembly) consisting + ** of several modules arranged on top of each other. The modules + ** have a given overlap in y and a displacement in z to allow for the + ** overlap. + ** + ** The typ of sectors / modules to be placed must be specified: + ** 1 = sensor01 + ** 2 = sensor02 + ** 3 = sensor03 + ** 4 = sensor04 + ** 5 = 2 x sensor04 (chained) + ** 6 = 3 x sensor04 (chained) + ** The cable is added automatically from the top of each sensor to + ** the top of the half ladder. + ** The alignment can be left (l) or right (r), which matters in the + ** case of different x sizes of sensors (e.g. SensorType01). + ** + ** Arguments: + ** name volume name + ** nSectors number of sectors + ** sectorTypes array with sector types + ** align horizontal alignment of sectors + * ladderLength full length of the ladder towards FEE + * offsetY gap in the beam-pipe region + **/ +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY, + Int_t start) { + + // --- Create half ladder volume assembly + TGeoVolumeAssembly* halfLadder = new TGeoVolumeAssembly(name); + + // --- Determine size of ladder + Double_t ladderX = 0.; + Double_t ladderY = 0.; + Double_t ladderZ = 0.; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + if ( ! sector ) + Fatal("ConstructHalfLadder", Form("Volume %s not found", sectorName.Data())); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + // --- Ladder x size equals largest sector x size + ladderX = TMath::Max(ladderX, 2. * box->GetDX()); + // --- Ladder y size is sum of sector ysizes + ladderY += 2. * box->GetDY(); + // --- Ladder z size is sum of sector z sizes + ladderZ += 2. * box->GetDZ(); + + cout << "DETT " << ladderX << " ; " << ladderY << " ; " << ladderZ << endl; + } + // --- Subtract overlaps in y + ladderY -= Double_t(nSectors-1) * gkSectorOverlapY; + // --- Add gaps in z direction + ladderZ += Double_t(nSectors-1) * gkSectorGapZ; + + ladderY = TMath::Max(ladderLength - offsetY, ladderY); + + // --- Create and place modules + Double_t yPosSect = -0.5 * ladderY; + Double_t zPosMod = -0.5 * ladderZ; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + yPosSect += 0.5 * sectorY; // Position of sector in ladder + Double_t cableLength = 0.5 * ladderY - yPosSect - 0.5 * sectorY; + TString moduleName = name + "_" + Form("Module%02d", + sectorTypes[iSector]); + TGeoVolume* module = ConstructModule(moduleName.Data(), + sector, cableLength); + + TGeoBBox* shapeMod = (TGeoBBox*) module->GetShape(); + Double_t moduleX = 2. * shapeMod->GetDX(); + Double_t moduleY = 2. * shapeMod->GetDY(); + Double_t moduleZ = 2. * shapeMod->GetDZ(); + Double_t xPosMod = 0.; + if ( align == 'l' ) + xPosMod = 0.5 * (moduleX - ladderX); // left aligned + else if ( align == 'r' ) + xPosMod = 0.5 * (ladderX - moduleX); // right aligned + else + xPosMod = 0.; // centred in x + Double_t yPosMod = 0.5 * (ladderY - moduleY); // top aligned + zPosMod += 0.5 * moduleZ; + +// Int_t angle = 0; // set default rotation angle to 0 +// if (iSector%2 == 1) // set rotation angle for every 2nd sensor +// angle = 180; + + Int_t angle = start * 180; + start = (start + 1) % 2; + + TGeoRotation* rmod = new TGeoRotation(); + rmod->RotateY(angle); + TGeoCombiTrans* cmod = new TGeoCombiTrans (xPosMod, yPosMod, zPosMod, rmod); + halfLadder->AddNode(module, iSector+1, cmod); + +// old style +// TGeoTranslation* trans = new TGeoTranslation("t", xPosMod, yPosMod, zPosMod); +// halfLadder->AddNode(module, iSector+1, trans); + + halfLadder->GetShape()->ComputeBBox(); + yPosSect += 0.5 * sectorY - gkSectorOverlapY; + zPosMod += 0.5 * moduleZ + gkSectorGapZ; + } + + CheckVolume(halfLadder); + cout << endl; + + return halfLadder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Add a carbon support to a ladder + ** + ** Arguments: + ** LadderIndex ladder number + ** ladder pointer to ladder + ** xu size of halfladder + ** ladderY height of ladder along y + ** ladderZ thickness of ladder along z + **/ +void AddCarbonLadder(Int_t LadderIndex, + TGeoVolume* ladder, + Double_t xu, + Double_t ladderY, + Double_t ladderZ) { + + // --- Some variables + TString name = Form("LadderType%04d", LadderIndex); // v19k + Int_t i; + Double_t j; + + Int_t YnumOfFrameBoxes = round(ladderY / gkFrameStep); + + // cout << "DEXZ: lad " << LadderIndex << " inum " << YnumOfFrameBoxes << endl; + + Double_t ladderDZ = (xu/2. + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2)/2.; + cout << "DEFR: frame Z size " << 2 * ladderDZ << " cm" << endl; + + TGeoBBox* fullFrameShp = new TGeoBBox (name+"_CarbonElement_shp", xu/2., gkFrameStep/2., ladderDZ); + TGeoVolume* fullFrameBoxVol = new TGeoVolume(name+"_CarbonElement", fullFrameShp, gStsMedium); + + ConstructFrameElement("CarbonElement", fullFrameBoxVol, xu/2.); + TGeoRotation* fullFrameRot = new TGeoRotation; + fullFrameRot->RotateY(180); + + Int_t inum = YnumOfFrameBoxes; + for (i=1; i<=inum; i++) + { + j=-(inum-1)/2.+(i-1); + // -(10-1)/2. +0 +10-1 -> -4.5 .. +4.5 -> -0.5, +0.5 (= 2) + // -(11-1)/2. +0 +11-1 -> -5.0 .. +5.0 -> -1, 0, 1 (= 3) + // cout << "DE: i " << i << " j " << j << endl; + + if (LadderIndex % 100 <= 3) // central ladders in stations 1 to 3 + { + if ((j>=-1) && (j<=1)) // keep the inner 2 (even) or 3 (odd) elements free for the cone + continue; + } + else if (LadderIndex % 100 <= 8) // central ladders in stations 4 to 8 + { + if ((j>=-2) && (j<=2)) // keep the inner 4 elements free for the cone + continue; + } + + cout << "DELZ: ladderDZ " << ladderDZ << " cm " << -ladderZ/2. - ladderDZ << " cm " << endl; + ladder->AddNode(fullFrameBoxVol, i, new TGeoCombiTrans(name+"_CarbonElement_posrot", 0., j*gkFrameStep, -(ladderZ/2.+ladderDZ), fullFrameRot)); + } + + ladder->GetShape()->ComputeBBox(); + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Construct a ladder out of two half ladders with vertical gap + ** + ** The second half ladder will be rotated by 180 degrees + ** in the x-y plane. The two half ladders will be put on top of each + ** other with a vertical gap. + ** + ** Arguments: + ** name volume name + ** halfLadderU pointer to upper half ladder + ** halfLadderD pointer to lower half ladder + ** gapY vertical gap + ** shiftZ relative displacement along the z axis + **/ + + TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ, + Double_t pitchZ, + Int_t nSectors) { + + // --- Some variables + TGeoBBox* shape = NULL; + + // define additional offset to carbon ladder for half ladders with less than 5 sensors + Double_t offsetZ = (5 - nSectors) * pitchZ; + + // --- Dimensions of half ladders + shape = (TGeoBBox*) halfLadderU->GetShape(); // up + Double_t xu = 2. * shape->GetDX(); + Double_t yu = 2. * shape->GetDY(); + Double_t zu = 2. * shape->GetDZ(); + + shape = (TGeoBBox*) halfLadderD->GetShape(); // down + Double_t xd = 2. * shape->GetDX(); + Double_t yd = 2. * shape->GetDY(); + Double_t zd = 2. * shape->GetDZ(); + + // --- Create ladder volume assembly + TString name = Form("LadderType%04d", LadderIndex); // v19k + TGeoVolumeAssembly* ladder = new TGeoVolumeAssembly(name); + Double_t ladderX = TMath::Max(xu, xd); + Double_t ladderY = yu + yd + gapY; + Double_t ladderZ = TMath::Max(zu, zd + shiftZ + offsetZ); // there are 6 slots - 5 x 1.5 mm + 0.3 mm = 7.8 mm + // Double_t ladderZ = TMath::Max(zu, zd + shiftZ); + + cout << "DERR iladder " << LadderIndex << " nSec " << nSectors + << " zu " << zu << " zd " << zd + << " zd+shi " << zd+shiftZ << " ladderZ " << ladderZ + << " offsetZ " << offsetZ << endl; + + // --- Place half ladders + Double_t xPosU = 0.0; // centred in x + Double_t yPosU = 0.5 * ( ladderY - yu ); // top aligned + Double_t zPosU = 0; + zPosU = 0.5 * ( ladderZ - zu ); // front aligned + if (LadderIndex >= 1000) + zPosU = -0.5 * ( ladderZ - zu ) + offsetZ; // back aligned with possible offset + //zPosU = -zPosU; + + TGeoTranslation* tu = new TGeoTranslation("tu", xPosU, yPosU, zPosU); + ladder->AddNode(halfLadderU, 1, tu); + + Double_t xPosD = 0.0; // centred in x + Double_t yPosD = 0.5 * -( ladderY - yd ); // bottom aligned + Double_t zPosD = 0; + zPosD = 0.5 * -( ladderZ - zd ) + offsetZ; // back aligned with possible offset + if (LadderIndex >= 1000) + zPosD = -0.5 * -( ladderZ - zd ); // front aligned + //zPosD = -zPosD; + + TGeoRotation* rd = new TGeoRotation(); + rd->RotateZ(180.); + TGeoCombiTrans* cd = new TGeoCombiTrans(xPosD, yPosD, zPosD, rd); + ladder->AddNode(halfLadderD, 2, cd); + + ladder->GetShape()->ComputeBBox(); + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD0ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + cout << "DDDD ladder" << LadderIndex << endl; + cout << "DDDD1ladder" << LadderIndex << " ladderX " << ladderX << " ladderY " << ladderY << " ladderZ " << ladderZ << endl; + + // ---------------- Create and place frame boxes ------------------------ + + if (gkConstructFrames) + AddCarbonLadder(LadderIndex, ladder, ladderX, ladderY, ladderZ); + + // -------------------------------------------------------------------------- + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD2ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + return ladder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a unit + ** + ** The unit volume is the minimal box comprising all ladders + ** minus a tube accomodating the beam pipe. + ** + ** The ladders are arranged horizontally from left to right with + ** a given overlap in x. + ** Every second ladder is slightly displaced upstream from the centre + ** z plane and facing downstream, the others are slightly displaced + ** downstream and facing upstream (rotated around the y axis). + ** + ** Arguments: + ** name volume name + ** nLadders number of ladders + ** ladderTypes array of ladder types + **/ + + TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation) { + + Bool_t isFirstPartOfHalfUnit = kFALSE; + + // TString name = Form("Unit%02d", iUnit); // 0,1,2,3,4,5,6,7 - Unit00 missing in output + // TString name = Form("Unit%02d", iUnit+1); // 1,2,3,4,5,6,7,8 + + TGeoVolume* unit = gGeoMan->GetVolume(unitName[iUnit]); + if ( ! unit ) // if it does not yet exist, create a new one + { + unit = new TGeoVolumeAssembly(unitName[iUnit]); + isFirstPartOfHalfUnit = kTRUE; + } + + // --- Some local variables + TGeoBBox* ladderShape = NULL; + TGeoVolume* ladder = NULL; + TString ladderName; + Double_t subtractedVal; + + // --- Determine size of unit from ladders + Double_t statX = 0.; + // Double_t statY = 0.; + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) + { + Int_t ladderType = ladderTypes[iLadder]; // v19k + +// if (iSide == 0) cout << "DWER " << ladderTypes[iLadder] << " " << ladderType << endl; + + if (ladderType > 0) + { + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + if ( ! ladder ) Fatal("ConstructUnit", + Form("Volume %s not found", ladderName.Data())); + ladderShape = (TGeoBBox*) ladder->GetShape(); + statX += 2. * ladderShape->GetDX(); + } + else + statX += gkSensorSizeX; // empty ladder in unit + } + statX -= Double_t(nLadders-1) * gkLadderOverlapX; + +// if (iSide == 0) cout << "DWER -" << endl; + + // --- Place ladders in unit + cout << "xPos0: " << statX << endl; + Double_t xPos = -0.5 * statX; + cout << "xPos1: " << xPos << endl; + Double_t yPos = 0.; + Double_t zPos = 0.; + + Double_t maxdz = 0.; + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) // find maximum dz in this unit + { + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + if (maxdz < ladderShape->GetDZ()) + maxdz = ladderShape->GetDZ(); + } + } + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) + { + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + xPos += ladderShape->GetDX(); + cout << "xPos2: " << xPos << endl; + yPos = 0.; // vertically centred + TGeoRotation* rot = new TGeoRotation(); + + if (gkConstructFrames) + subtractedVal = ladderShape->GetDX() + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2; + else + subtractedVal = 0.; + + zPos = 0.5 * gkLadderGapZ + (2*maxdz-ladderShape->GetDZ()-subtractedVal/2.); // z-aligned ladders + +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " dx: " << ladderShape->GetDX() + << " dy: " << ladderShape->GetDY() + << " dz: " << ladderShape->GetDZ() + << " max dz: " << maxdz << endl; + +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " fra: " << gkFrameThickness/2. + << " sub: " << subtractedVal + << " zpo: " << zPos << endl << endl; + +// v19k + if (ladderTypes[iLadder]/1000 == 1) // flip some of the ladders to reproduce the CAD layout + rot->RotateY(180.); + else + zPos = -zPos; + + if (!isFirstPartOfHalfUnit) + zPos += 10.5; // v19d +// zPos += 10.0; // initial version + + TGeoCombiTrans* trans = new TGeoCombiTrans(xPos, yPos, zPos, rot); +// start +// cout << "DEEE** iLadder " << iLadder << " " << nLadders/2 << " " << nLadders << endl; + + if (iSide == 0) + { + if (iLadder < nLadders/2) // right side - only half unit -x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + else + { + if (iLadder >= nLadders/2) // left side - only half unit +x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + unit->GetShape()->ComputeBBox(); +// stop + xPos += ladderShape->GetDX() - gkLadderOverlapX; + cout << "xPos3: " << xPos << endl; + } + else + xPos += gkSensorSizeX - gkLadderOverlapX; + } + + return unit; + } +/** ======================================================================= **/ + + +/** =========================================================================== + ** Import and add the passive materials to the STS volume + **/ +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile) +{ + TString passiveName = TString("sts_passive_") + geoTag; + TString basePath = gSystem->Getenv("VMCWORKDIR"); + TString relPath = "/geometry/sts/passive/" + passiveName + ".gdml"; + TString passiveFileName = basePath + relPath; + infoFile << std::endl << std::endl; + infoFile << "Importing STS passive materials from GDML file '" << relPath << "'." << std::endl; + + TGDMLParse parser; + TGeoVolume* gdmlVolume = parser.GDMLReadFile(passiveFileName); + PostProcessGdml(gdmlVolume); + gdmlVolume->SetName(passiveName); + + TGeoTranslation* passiveTrans = new TGeoTranslation(0., 0., 4.68 - 2.); + infoFile << "Passive assembly is translated for Z=2.68 cm downstream with respect to parent volume" << std::endl << std::endl; + + gdmlVolume->GetShape()->ComputeBBox(); + CheckVolume(gdmlVolume, infoFile); + + infoFile << std::endl; + for (Int_t iNode = 0; iNode < gdmlVolume->GetNdaughters(); iNode++) { + CheckVolume(gdmlVolume->GetNode(iNode)->GetVolume(), infoFile, kFALSE); + } + + stsVolume->AddNode(gdmlVolume, stsVolume->GetNdaughters(), passiveTrans, ""); +} + +/** =========================================================================== + ** Assign visual properties to the imported gdml volumes + **/ +void PostProcessGdml(TGeoVolume* gdmlVolume) +{ + const UInt_t kPOBColor = kRed-6; + const UInt_t kPOBTransparency = 0;// 5; + + const UInt_t kFEBColor = kOrange-6; + const UInt_t kFEBTransparency = 0;// 5; + + const UInt_t kUnitColor = kCyan-10; + const UInt_t kUnitTransparency = 0;// 5; + + const UInt_t kCfColor = kGray+3; + const UInt_t kCfTransparency = 0;// 10; + + // name <Color, Transparency> + std::map<std::string, std::tuple<UInt_t,UInt_t> > props { + { "passive_POB", std::tuple<UInt_t,UInt_t> {kPOBColor, kPOBTransparency} }, + { "passive_FEB", std::tuple<UInt_t,UInt_t> {kFEBColor, kFEBTransparency} }, + { "passive_unit", std::tuple<UInt_t,UInt_t> {kUnitColor, kUnitTransparency} }, + { "passive_Box_Wall", std::tuple<UInt_t,UInt_t> {kCfColor, kCfTransparency} }, + { "passive_Box_Wall_Front_CF2", std::tuple<UInt_t,UInt_t> {kCfColor-3, kCfTransparency} }, + }; + + // Match volume name and apply visual properties + const TObjArray* volumes = gGeoManager->GetListOfVolumes(); + for (auto& entry : props) { + TIter next(volumes); + TGeoVolume *vol = nullptr; + while ((vol=(TGeoVolume*)next())) { + if (TString(vol->GetName()).Contains(entry.first.c_str())) { + vol->SetLineColor(std::get<0>(entry.second)); + vol->SetTransparency(std::get<1>(entry.second)); + } + } + } +} + +/** =========================================================================== + ** Volume information for debugging + **/ +void CheckVolume(TGeoVolume* volume) { + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + cout << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) cout << ", assembly"; + else { + if ( volume->GetMedium() ) + cout << ", medium " << volume->GetMedium()->GetName(); + else cout << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + cout << endl; + if ( volume->GetNdaughters() ) { + cout << "Daughters: " << endl; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) { + TGeoNode* node = volume->GetNode(iNode); + TGeoBBox* shape = (TGeoBBox*) node->GetVolume()->GetShape(); + cout << setw(15) << node->GetName() << ", size " + << fixed << setprecision(3) + << setw(6) << 2. * shape->GetDX() << " x " + << setw(6) << 2. * shape->GetDY() << " x " + << setw(6) << 2. * shape->GetDZ() << ", position ( "; + TGeoMatrix* matrix = node->GetMatrix(); + const Double_t* pos = matrix->GetTranslation(); + cout << setfill(' '); + cout << fixed << setw(8) << pos[0] << ", " + << setw(8) << pos[1] << ", " + << setw(8) << pos[2] << " )" << endl; + } + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Volume information for output to file + **/ +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren) { + if ( ! file ) return; + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + file << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) file << ", assembly"; + else { + if ( volume->GetMedium() ) + file << ", medium " << volume->GetMedium()->GetName(); + else file << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + file << endl; + if ( volume->GetNdaughters() && listChildren) { + file << "Contains: "; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) + file << volume->GetNode(iNode)->GetVolume()->GetName() << " "; + file << endl; + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Calculate beam pipe outer radius for a given z + **/ +Double_t BeamPipeRadius(Double_t z) { + if ( z < gkPipeZ2 ) return gkPipeR1; + Double_t slope = (gkPipeR3 - gkPipeR2 ) / (gkPipeZ3 - gkPipeZ2); + return gkPipeR2 + slope * (z - gkPipeZ2); +} +/** ======================================================================= **/ + + + +/** ======================================================================= **/ +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + TGeoBBox* frameVertPillarShp; + + Double_t t = gkFrameThickness/2.; + + // --- Main vertical pillars +// TGeoBBox* frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, gkFrameStep/2., t); // square crossection, along y +// TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); +// frameVertPillarVol->SetLineColor(kGreen); +// frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoTranslation(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2.)); +// frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoTranslation(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkCylindricalFrames) + // TGeoBBox* frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", 0, t, gkFrameStep/2.); // circle crossection, along z + frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", gkCylinderDiaInner/2., gkCylinderDiaOuter/2., gkFrameStep/2.); // circle crossection, along z + else + frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, t, gkFrameStep/2.); // square crossection, along z + TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); + frameVertPillarVol->SetLineColor(kGreen); + + TGeoRotation* xRot90 = new TGeoRotation; + xRot90->RotateX(90.); + frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoCombiTrans(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoCombiTrans(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + + // TGeoRotation* vertRot = new TGeoRotation(name + "_vertpillar_rot_1", 90., 45., -90.); + TGeoRotation* vertRot = new TGeoRotation; + vertRot->RotateX(90.); + vertRot->RotateY(45.); + frameBoxVol->AddNode(frameVertPillarVol, 3, new TGeoCombiTrans(name + "_vertpillar_pos_3", 0., 0., (x-sqrt(2.)*t)/2., vertRot)); + + // --- Small horizontal pillar + // TGeoBBox* frameHorPillarShp = new TGeoBBox(name + "_horpillar_shape", x-2.*t, gkThinFrameThickness/2., gkThinFrameThickness/2.); + // TGeoVolume* frameHorPillarVol = new TGeoVolume(name + "_horpillar", frameHorPillarShp, framesMaterial); + // frameHorPillarVol->SetLineColor(kCyan); + // frameBoxVol->AddNode(frameHorPillarVol, 1, new TGeoTranslation(name + "_horpillar_pos_1", 0., -gkFrameStep/2.+gkThinFrameThickness/2., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkConstructSmallFrames) { + + // --- Small sloping pillars + TGeoPara* frameSlopePillarShp = new TGeoPara(name + "_slopepillar_shape", + (x-2.*t)/TMath::Cos(31.4/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., 31.4, 0., 90.); + TGeoVolume* frameSlopePillarVol = new TGeoVolume(name + "_slopepillar", frameSlopePillarShp, framesMaterial); + frameSlopePillarVol->SetLineColor(kCyan); + TGeoRotation* slopeRot = new TGeoRotation(name + "_slopepillar_rot_1", 0., 0., 31.4); + TGeoRotation* slopeRot2 = new TGeoRotation(name + "_slopepillar_rot_2", 0., 0., -31.4); + TGeoCombiTrans* slopeTrRot = new TGeoCombiTrans(name + "_slopepillar_posrot_1", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot); + TGeoCombiTrans* slopeTrRot2 = new TGeoCombiTrans(name + "_slopepillar_posrot_2", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot2); + + frameBoxVol->AddNode(frameSlopePillarVol, 1, slopeTrRot); + frameBoxVol->AddNodeOverlap(frameSlopePillarVol, 2, slopeTrRot2); + + + Double_t angl = 23.; + // --- Small sub pillar + TGeoPara* frameSubPillarShp = new TGeoPara(name + "_subpillar_shape", + (sqrt(2)*(x/2.-t)-t/2.)/TMath::Cos(angl/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., angl, 0., 90.); + TGeoVolume* frameSubPillarVol = new TGeoVolume(name + "_subpillar", frameSubPillarShp, framesMaterial); + frameSubPillarVol->SetLineColor(kMagenta); + + Double_t posZ = t * (1. - 3. / ( 2.*sqrt(2.) )); + + // one side of X direction + TGeoRotation* subRot1 = new TGeoRotation(name + "_subpillar_rot_1", 90., 45., -90.+angl); + TGeoCombiTrans* subTrRot1 = new TGeoCombiTrans(name + "_subpillar_posrot_1", -(-x/2.+t-t/(2.*sqrt(2.))), 1., posZ, subRot1); + + TGeoRotation* subRot2 = new TGeoRotation(name + "_subpillar_rot_2", 90., -90.-45., -90.+angl); + TGeoCombiTrans* subTrRot2 = new TGeoCombiTrans(name + "_subpillar_posrot_2", -(-x/2.+t-t/(2.*sqrt(2.))), -1., posZ, subRot2); + + // other side of X direction + TGeoRotation* subRot3 = new TGeoRotation(name + "_subpillar_rot_3", 90., 90.+45., -90.+angl); + TGeoCombiTrans* subTrRot3 = new TGeoCombiTrans(name + "_subpillar_posrot_3", -x/2.+t-t/(2.*sqrt(2.)), 1., posZ, subRot3); + + TGeoRotation* subRot4 = new TGeoRotation(name + "_subpillar_rot_4", 90., -45., -90.+angl); + TGeoCombiTrans* subTrRot4 = new TGeoCombiTrans(name + "_subpillar_posrot_4", -x/2.+t-t/(2.*sqrt(2.)), -1., posZ, subRot4); + + frameBoxVol->AddNode(frameSubPillarVol, 1, subTrRot1); + frameBoxVol->AddNode(frameSubPillarVol, 2, subTrRot2); + frameBoxVol->AddNode(frameSubPillarVol, 3, subTrRot3); + frameBoxVol->AddNode(frameSubPillarVol, 4, subTrRot4); + // frameBoxVol->GetShape()->ComputeBBox(); + } + + return frameBoxVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructSmallCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 6., 7.6, 6., 6.04, 0., 180.); +// TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + Double_t radius = 3.0; + Double_t thickness = 0.04; // 0.4 mm +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 3., 3.2, 3., 3.2, 0., 180.); + TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, radius, radius+thickness, radius, radius+thickness, 0., 180.); + TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + TGeoCombiTrans* M = new TGeoCombiTrans ("M"); + M->RotateX (45.); + M->SetDy (-5.575); + M->SetDz (6.935); + M->RegisterYourself(); + + TGeoShape* coneShp = new TGeoCompositeShape ("Cone_shp", "A-B:M"); + TGeoVolume* coneVol = new TGeoVolume ("Cone", coneShp, framesMaterial); + coneVol->SetLineColor(kGreen); +// coneVol->RegisterYourself(); + +// // --- Inner cone +// Double_t thickness = 0.02; +// Double_t thickness2 = 0.022; +// // TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); +// TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 3.+thickness, 4.6-thickness2, 2.99+thickness, 3.05-thickness2, 0., 180.); +// +// TGeoCombiTrans* M2 = new TGeoCombiTrans ("M2"); +// M2->RotateX (45.); +// M2->SetDy (-5.575+thickness*sqrt(2.)); +// M2->SetDz (6.935); +// M2->RegisterYourself(); +// +// TGeoShape* coneShp2 = new TGeoCompositeShape ("Cone2_shp", "A2-B:M2"); +// TGeoVolume* coneVol2 = new TGeoVolume ("Cone2", coneShp2, gStsMedium); +// coneVol2->SetLineColor(kGreen); +//// coneVol2->RegisterYourself(); +// +// coneVol->AddNode(coneVol2, 1); + + return coneVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructBigCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone + TGeoConeSeg* bA = new TGeoConeSeg ("bA", coneDz, 6., 7.6, 6., 6.04, 0., 180.); + TGeoBBox* bB = new TGeoBBox ("bB", 8., 6., 10.); + + TGeoCombiTrans* bM = new TGeoCombiTrans ("bM"); + bM->RotateX (45.); + bM->SetDy (-5.575); + bM->SetDz (6.935); + bM->RegisterYourself(); + + TGeoShape* coneBigShp = new TGeoCompositeShape ("ConeBig_shp", "bA-bB:bM"); + TGeoVolume* coneBigVol = new TGeoVolume ("ConeBig", coneBigShp, framesMaterial); + coneBigVol->SetLineColor(kGreen); +// coneBigVol->RegisterYourself(); + + // --- Inner cone + Double_t thickness = 0.02; + Double_t thickness2 = 0.022; + TGeoConeSeg* bA2 = new TGeoConeSeg ("bA2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); + + TGeoCombiTrans* bM2 = new TGeoCombiTrans ("bM2"); + bM2->RotateX (45.); + bM2->SetDy (-5.575+thickness*sqrt(2.)); + bM2->SetDz (6.935); + bM2->RegisterYourself(); + + TGeoShape* coneBigShp2 = new TGeoCompositeShape ("ConeBig2_shp", "bA2-bB:bM2"); + TGeoVolume* coneBigVol2 = new TGeoVolume ("ConeBig2", coneBigShp2, gStsMedium); + coneBigVol2->SetLineColor(kGreen); +// coneBigVol2->RegisterYourself(); + + coneBigVol->AddNode(coneBigVol2, 1); + + return coneBigVol; +} + +/** ======================================================================= **/ diff --git a/macro/sts/geometry/create_stsgeo_v19u.C b/macro/sts/geometry/create_stsgeo_v19u.C new file mode 100644 index 0000000000000000000000000000000000000000..bac9512e1c6c5a3a6bd3ace5f38afc429fc77359 --- /dev/null +++ b/macro/sts/geometry/create_stsgeo_v19u.C @@ -0,0 +1,2404 @@ +/****************************************************************************** + ** Creation of STS geometry in ROOT format (TGeo). + ** + ** @file create_stsgeo_v19u.C + ** @author Volker Friese <v.friese@gsi.de> + ** @since 15 June 2012 + ** @date 09.05.2014 + ** @author Tomas Balog <T.Balog@gsi.de> + ** + ** v19u: rotate the opposite sensors as compared to v19t + ** v19t: application of pp-nn sensor orientation to v19r (as tested in v19s) + ** v19s: introducing pp-nn sensor orientation - only for visualisation using blue and red surfaces + ** v19r: bugfix of v19q - align all halfladders + ** v19q: based on v19l - align ladders to virtual plane in station center, closing the gaps in z + ** v19p: based on v19k - parameters : delta Z prime = 0.70 cm - delta Z pitch = 0.20 cm + ** v19o: based on v19k - parameters : delta Z prime = 0.30 cm - delta Z pitch = 0.20 cm + ** v19n: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.20 cm (bug fix of v19m) + ** v19m: based on v19k - parameters : delta Z prime = 0.55 cm - delta Z pitch = 0.20 cm (bug) + ** v19l: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.15 cm + ** v19k: ladders on upstream side of units get upper half ladders installed first, + ** ladders on downstream side of units get lower half ladders installed first, + ** this saves 1.5 mm space in z per station, 12 mm in total (LadderType went from 3 to 4 digits) + ** parameters : delta Z prime = 1.00 cm - delta Z pitch = 0.15 cm + ** v19j: use overlap and distance parameters from CAD model + ** v19h: put STS stations from v19d at z-positions = 260; 365; 470; 575; 680; 785; 890; 995 mm + ** v19g: place a box with services around v19e + ** v19f: place a box with services around v19d + ** v19e: increase spacing between stations by +10 mm from 100 mm + ** v19d: increase spacing between stations by + 5 mm from 100 mm + ** v19c: drop station 8 and increase spacing between remaining 7 stations from 10 cm to 12 c + ** v19b: introduce FEB orientation in ladder numbering (LadderType went from 2 to 3 digits) + ** v19a: import passive materials from gdml file + ** extend CF ladder structures and cables towards FEE plane + ** change CF ladder frame shape + ** v18d: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu (based on v18b) + ** v18c: fixed cut-out windows in cooling plates, improve the box shape/materials + ** v18b: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu + ** v18a: adds 9 cooling/holding plates and a box around the setup + ** v16g: v16g is the new standard geometry from November 2017 + ** v16g: switch from stations to units - left / right ("Unit01L", "Unit01R") + ** v16f: switch from stations to units + ** - split in upstream / downstream and left / right parts + ** - named Unit0xUR, Unit0xUL, Unit0xDR, Unit0xDL + ** v16e: switch from stations to units - upstream / downstream ("Unit01U", "Unit01D") + ** v16d: skip keeping volumes of sts and stations + ** v16c: like v16b, but senors of ladders beampipe next to beampipe + ** shifted closer to the pipe, like in the CAD model + ** v16b: like v16a, but yellow sensors removed + ** v16a: derived from v15c (no cones), but with sensor types renamed: + ** 2 -> 1, 3 -> 2, 4 -> 3, 5 -> 4, 1 -> 5 + ** + ** v15c: as v15b without cones + ** v15b: introduce modified carbon ladders from v13z + ** v15a: with flipped ladder orientation for stations 0,2,4,6 to match CAD design + ** + ** TODO: + ** + ** DONE: + ** v15b - use carbon macaroni as ladder support + ** v15b - introduce a small gap between lowest sensor and carbon ladder + ** v15b - build small cones for the first 2 stations + ** v15b - within a station the ladders of adjacent units should not touch eachother - set gkLadderGapZ to 10 mm + ** v15b - for all ladders set an even number of ladder elements + ** v15b - z offset of cones to ladders should not be 0.3 by default, but 0.26 + ** v15b - within a station the ladders should be aligned in z, defined either by the unit or the ladder with most sensors + ** v15b - get rid of cone overlap in stations 7 and 8 - done by adapting rHole size + ** + ** The geometry hierarachy is: + ** + ** 1. Sensors (see function CreateSensors) + ** The sensors are the active volumes and the lowest geometry level. + ** They are built as TGeoVolumes, shape box, material silicon. + ** x size is determined by strip pitch 58 mu and 1024 strips + ** plus guard ring of 1.3 mm at each border -> 6.1992 cm. + ** Sensor type 1 is half of that (3.0792 cm). + ** y size is determined by strip length (2.2 / 4.2 / 6.3 cm) plus + ** guard ring of 1.3 mm at top and bottom -> 2.46 / 4.46 / 6.46 cm. + ** z size is a parameter, to be set by gkSensorThickness. + ** + ** 2. Sectors (see function CreateSectors) + ** Sectors consist of several chained sensors. These are arranged + ** vertically on top of each other with a gap to be set by + ** gkChainGapY. Sectors are constructed as TGeoVolumeAssembly. + ** The sectors are auxiliary volumes used for proper placement + ** of the sensor(s) in the module. They do not show up in the + ** final geometry. + ** + ** 3. Modules (see function ConstructModule) + ** A module is a readout unit, consisting of one sensor or + ** a chain of sensors (see sector) and a cable. + ** The cable extends from the top of the sector vertically to the + ** top of the halfladder the module is placed in. The cable and module + ** volume thus depend on the vertical position of the sector in + ** the halfladder. The cables consist of silicon with a thickness to be + ** set by gkCableThickness. + ** Modules are constructed as TGeoVolume, shape box, medium gStsMedium. + ** The module construction can be switched off (gkConstructCables) + ** to reproduce older geometries. + ** + ** 4. Halfladders (see function ConstructHalfLadder) + ** A halfladder is a vertical assembly of several modules. The modules + ** are placed vertically such that their sectors overlap by + ** gkSectorOverlapY. They are displaced in z direction to allow for the + ** overlap in y by gkSectorGapZ. + ** The horizontal placement of modules in the halfladder can be choosen + ** to left aligned or right aligned, which only matters if sensors of + ** different x size are involved. + ** Halfladders are constructed as TGeoVolumeAssembly. + ** + ** 5. Ladders (see function CreateLadders and ConstructLadder) + ** A ladder is a vertical assembly of two halfladders, and is such the + ** vertical building block of a station. The second (bottom) half ladder + ** is rotated upside down. The vertical arrangement is such that the + ** inner sectors of the two halfladders have the overlap gkSectorOverlapY + ** (function CreateLadder) or that there is a vertical gap for the beam + ** hole (function CreateLadderWithGap). + ** Ladders are constructed as TGeoVolumeAssembly. + ** + ** 6. Stations (see function ConstructStation) + ** A station represents one layer of the STS geometry: one measurement + ** at (approximately) a given z position. It consist of several ladders + ** arranged horizontally to cover the acceptance. + ** The ladders are arranged such that there is a horizontal overlap + ** between neighbouring ladders (gkLadderOverLapX) and a vertical gap + ** to allow for this overlap (gkLadderGapZ). Each second ladder is + ** rotated around its y axis to face away from or into the beam. + ** Stations are constructed as TGeoVolumes, shape box minus tube (for + ** the beam hole), material gStsMedium. + ** + ** 7. STS + ** The STS is a volume hosting the entire detectors system. It consists + ** of several stations located at different z positions. + ** The STS is constructed as TGeoVolume, shape box minus cone (for the + ** beam pipe), material gStsMedium. The size of the box is computed to + ** enclose all stations. + *****************************************************************************/ + + +// Remark: With the proper steering variables, this should exactly reproduce +// the geometry version v11b of A. Kotynia's described in the ASCII format. +// The only exception is a minimal difference in the z position of the +// sectors/sensors. This is because of ladder types 2 and 4 containing the half +// sensors around the beam hole (stations 1,2 and 3). In v11b, the two ladders +// covering the beam hole cannot be transformed into each other by rotations, +// but only by a reflection. This means they are constructionally different. +// To avoid introducing another two ladder types, the difference in z position +// was accepted. + + +// Differences to v12: +// gkChainGap reduced from 1 mm to 0 +// gkCableThickness increased from 100 mum to 200 mum (2 cables per module) +// gkSectorOverlapY reduced from 3 mm to 2.4 mm +// New sensor types 05 and 06 +// New sector types 07 and 08 +// Re-definiton of ladders (17 types instead of 8) +// Re-definiton of station from new ladders + + +#include <iomanip> +#include <iostream> +#include "TGeoManager.h" + +#include "TGeoTube.h" +#include "TGeoPara.h" +#include "TGeoCone.h" +#include "TGeoTrd2.h" +#include "TGeoCompositeShape.h" +#include "TGeoXtru.h" +#include "TGeoPhysicalNode.h" + +// forward declarations +Int_t CreateSensors(); +Int_t CreateSectors(); +Int_t CreateLadders(); +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength); +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY, + Int_t start); +TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ, + Double_t pitchZ, + Int_t nSectors); +TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation); +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile); +void PostProcessGdml(TGeoVolume* gdmlTop); +void CheckVolume(TGeoVolume* volume); +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren = kTRUE); +Double_t BeamPipeRadius(Double_t z); +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x); +TGeoVolume* ConstructSmallCone(Double_t coneDz); +TGeoVolume* ConstructBigCone(Double_t coneDz); + +// ------------- Version highlight ----------------------------------- + +const std::string gVersionHighlight = R"( +Summary: + This version adds passive materials imported from GDML model to the STS geometry: + * Taken from and largely correspond to mechanical CAD drawings of the detector + * Thermal insulation box: + - made out of carbon sandwitch panel (2mm carbon fiber sheet + layer of carbon foam + 2mm carbon fiber sheet) + - front window of complex shape with interface to MVD / target chamber + - back window with large aperture (2000 x 1200 mm) square cut into carbon foam + * Structural units: + - made of 2 complex shape aluminum C-Frames, 15mm thick + - placed at 25, 35, ... ,105 cm absolute Z + - contain front-end and power distribution boxes with equivalent X_0 values + + Scripted geometry tweaks: + * Ladders and cables are extended towards the read-out planes having same lengths in respective rows + * Adjusted form and shape of carbon ladder structures from L-type to X-type + * Reduced verbosity of this file + + Sensor arrangement is the same as in version v16g + + !! Important for this version is the discrepancy from the mechanical CAD w.r.t. front wall. + The square window was replaced by a round one to avoid overlaps with present beam pipe designs, e.g. pipe_v16b_1e +)"; + +// ------------- Steering variables ----------------------------------- + +// ---> Horizontal width of sensors [cm] +const Double_t gkSensorSizeX = 6.2; // was 6.2092; // 6.2 - Oleg CAD 15/05/2020 + +// ---> Thickness of sensors [cm] +const Double_t gkSensorThickness = 0.03; + +// ---> Vertical gap between chained sensors [cm] +const Double_t gkChainGapY = 0.00; + +// ---> Thickness of cables [cm] +const Double_t gkCableThickness = 0.02; + +// ---> Horizontal overlap of neighbouring ladders [cm] +const Double_t gkLadderOverlapX = 0.25; // delta X - Oleg CAD 14/05/2020 + +// ---> Vertical overlap of neighbouring sectors in a ladder [cm] +const Double_t gkSectorOverlapY = 0.46; // delta Y - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring sectors in a ladder [cm] +const Double_t gkSectorGapZ = 0.12; // gap + thickness = pitch // delta Z pitch = 0.15 - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring ladders [cm] +const Double_t gkLadderGapZ = 0.50 - 0.15; // for asym // 0.5 for sym // delta Z prime + +// ---> Gap in z between lowest sector to carbon support structure [cm] +const Double_t gkSectorGapZFrame = 0.280 - 0.025; // Oleg CAD 05/05/2020 // there is a 2.8 mm gap between the bottom side of the sensor and the top ledge of the carbon ladder + +// ---> Switch to construct / not to construct readout cables +const Bool_t gkConstructCables = kTRUE; + +// ---> Switch to construct / not to construct frames +const Bool_t gkConstructCones = kFALSE; // kTRUE; // switch this false by default for v15c and v16x +const Bool_t gkConstructFrames = kTRUE; // kFALSE; // switch this true by default for v15c and v16x +const Bool_t gkConstructSmallFrames = kTRUE; // kFALSE; +const Bool_t gkCylindricalFrames = kTRUE; // kFALSE; + +// ---> Size of the frame +const Double_t gkFrameThickness = 0.2; +const Double_t gkThinFrameThickness = 0.05; +const Double_t gkFrameStep = 4.0; // size of frame cell along y direction + +const Double_t gkCylinderDiaInner = 0.07; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) +const Double_t gkCylinderDiaOuter = 0.15; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) + +// ---> Switch to import / not to import the Passive materials from GDML file +//const Bool_t gkImportPassive = kTRUE; +const Bool_t gkImportPassive = kFALSE; + +// ---------------------------------------------------------------------------- + + +// -------------- Parameters of beam pipe in the STS region -------------- +// ---> Needed to compute stations and STS such as to avoid overlaps +const Double_t gkPipeZ1 = 22.0; +const Double_t gkPipeR1 = 1.8; +const Double_t gkPipeZ2 = 50.0; +const Double_t gkPipeR2 = 1.8; +const Double_t gkPipeZ3 = 125.0; +const Double_t gkPipeR3 = 5.5; + +//DE const Double_t gkPipeZ1 = 27.0; +//DE const Double_t gkPipeR1 = 1.05; +//DE const Double_t gkPipeZ2 = 160.0; +//DE const Double_t gkPipeR2 = 3.25; +// ---------------------------------------------------------------------------- + +//TString unitName[16] = // names of units for v16e +// { "Unit00D", +// "Unit01U", "Unit01D", +// "Unit02U", "Unit02D", +// "Unit03U", "Unit03D", +// "Unit04U", "Unit04D", +// "Unit05U", "Unit05D", +// "Unit06U", "Unit06D", +// "Unit07U", "Unit07D", +// "Unit08U" }; + +//TString unitName[32] = // names of units for v16f +// { "Unit00DR", "Unit00DL", +// "Unit01UR", "Unit01UL", "Unit01DR", "Unit01DL", +// "Unit02UR", "Unit02UL", "Unit02DR", "Unit02DL", +// "Unit03UR", "Unit03UL", "Unit03DR", "Unit03DL", +// "Unit04UR", "Unit04UL", "Unit04DR", "Unit04DL", +// "Unit05UR", "Unit05UL", "Unit05DR", "Unit05DL", +// "Unit06UR", "Unit06UL", "Unit06DR", "Unit06DL", +// "Unit07UR", "Unit07UL", "Unit07DR", "Unit07DL", +// "Unit08UR", "Unit08UL" }; + +TString unitName[32] = // names of units for v16g - while merging D and U parts + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", "Unit01R", "Unit01L", + "Unit02R", "Unit02L", "Unit02R", "Unit02L", + "Unit03R", "Unit03L", "Unit03R", "Unit03L", + "Unit04R", "Unit04L", "Unit04R", "Unit04L", + "Unit05R", "Unit05L", "Unit05R", "Unit05L", + "Unit06R", "Unit06L", "Unit06R", "Unit06L", + "Unit07R", "Unit07L", "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +TString unitName18[18] = // names of units for v16g + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", + "Unit02R", "Unit02L", + "Unit03R", "Unit03L", + "Unit04R", "Unit04L", + "Unit05R", "Unit05L", + "Unit06R", "Unit06L", + "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +// ------------- Other global variables ----------------------------------- +// ---> STS medium (for every volume except silicon) +TGeoMedium* gStsMedium = NULL; // will be set later +// ---> TGeoManager (too lazy to write out 'Manager' all the time +TGeoManager* gGeoMan = NULL; // will be set later +// ---------------------------------------------------------------------------- + + + + +// ============================================================================ +// ====== Main function ===== +// ============================================================================ + +void create_stsgeo_v19u(const char* geoTag="v19u") +{ + + // ------- Geometry file name (output) ---------------------------------- + TString geoFileName = "sts_"; + geoFileName = geoFileName + geoTag + ".geo.root"; + // -------------------------------------------------------------------------- + + + // ------- Open info file ----------------------------------------------- + TString infoFileName = geoFileName; + infoFileName.ReplaceAll("root", "info"); + fstream infoFile; + infoFile.open(infoFileName.Data(), fstream::out); + infoFile << "STS geometry created with create_stsgeo_v19u.C" << endl; + infoFile << gVersionHighlight << endl; + infoFile << "Global variables: " << endl; + infoFile << "Sensor thickness = " << gkSensorThickness << " cm" << endl; + infoFile << "Vertical gap in sensor chain = " + << gkChainGapY << " cm" << endl; + infoFile << "Vertical overlap of sensors = " + << gkSectorOverlapY << " cm" << endl; + infoFile << "Gap in z between neighbour sensors = " + << gkSectorGapZ << " cm" << endl; + infoFile << "Horizontal overlap of sensors = " + << gkLadderOverlapX << " cm" << endl; + infoFile << "Gap in z between neighbour ladders = " + << gkLadderGapZ << " cm" << endl; + if ( gkConstructCables ) + infoFile << "Cable thickness = " << gkCableThickness << " cm" << endl; + else + infoFile << "No cables" << endl; + infoFile << endl; + infoFile << "Beam pipe: R1 = " << gkPipeR1 << " cm at z = " + << gkPipeZ1 << " cm" << endl; + infoFile << "Beam pipe: R2 = " << gkPipeR2 << " cm at z = " + << gkPipeZ2 << " cm" << endl; + infoFile << "Beam pipe: R3 = " << gkPipeR3 << " cm at z = " + << gkPipeZ3 << " cm" << endl; + // -------------------------------------------------------------------------- + + + // ------- Load media from media file ----------------------------------- + FairGeoLoader* geoLoad = new FairGeoLoader("TGeo","FairGeoLoader"); + FairGeoInterface* geoFace = geoLoad->getGeoInterface(); + TString geoPath = gSystem->Getenv("VMCWORKDIR"); + TString medFile = geoPath + "/geometry/media.geo"; + geoFace->setMediaFile(medFile); + geoFace->readMedia(); + gGeoMan = gGeoManager; + // -------------------------------------------------------------------------- + + + // ----------------- Get and create the required media ----------------- + FairGeoMedia* geoMedia = geoFace->getMedia(); + FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder(); + + // ---> air + FairGeoMedium* mAir = geoMedia->getMedium("air"); + if ( ! mAir ) Fatal("Main", "FairMedium air not found"); + geoBuild->createMedium(mAir); + TGeoMedium* air = gGeoMan->GetMedium("air"); + if ( ! air ) Fatal("Main", "Medium air not found"); + + // ---> silicon + FairGeoMedium* mSilicon = geoMedia->getMedium("silicon"); + if ( ! mSilicon ) Fatal("Main", "FairMedium silicon not found"); + geoBuild->createMedium(mSilicon); + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + if ( ! silicon ) Fatal("Main", "Medium silicon not found"); + + // ---> carbon + FairGeoMedium* mCarbon = geoMedia->getMedium("carbon"); + if ( ! mCarbon ) Fatal("Main", "FairMedium carbon not found"); + geoBuild->createMedium(mCarbon); + TGeoMedium* carbon = gGeoMan->GetMedium("carbon"); + if ( ! carbon ) Fatal("Main", "Medium carbon not found"); + + // ---> STSBoxCarbonFoam + FairGeoMedium* mSTSBoxCarbonFoam = geoMedia->getMedium("STSBoxCarbonFoam"); + if ( ! mSTSBoxCarbonFoam ) Fatal("Main", "FairMedium STSBoxCarbonFoam not found"); + geoBuild->createMedium(mSTSBoxCarbonFoam); + TGeoMedium* STSBoxCarbonFoam = gGeoMan->GetMedium("STSBoxCarbonFoam"); + if ( ! STSBoxCarbonFoam ) Fatal("Main", "Medium STSBoxCarbonFoam not found"); + + // ---> STSBoxCarbonFibre + FairGeoMedium* mSTSBoxCarbonFibre = geoMedia->getMedium("STSBoxCarbonFibre"); + if ( ! mSTSBoxCarbonFibre ) Fatal("Main", "FairMedium STSBoxCarbonFibre not found"); + geoBuild->createMedium(mSTSBoxCarbonFibre); + TGeoMedium* STSBoxCarbonFibre = gGeoMan->GetMedium("STSBoxCarbonFibre"); + if ( ! STSBoxCarbonFibre ) Fatal("Main", "Medium STSBoxCarbonFibre not found"); + + // ---> STScable + FairGeoMedium* mSTScable = geoMedia->getMedium("STScable"); + if ( ! mSTScable ) Fatal("Main", "FairMedium STScable not found"); + geoBuild->createMedium(mSTScable); + TGeoMedium* STScable = gGeoMan->GetMedium("STScable"); + if ( ! STScable ) Fatal("Main", "Medium STScable not found"); + + // ---> Aluminium + FairGeoMedium* mAluminium = geoMedia->getMedium("aluminium"); + if ( ! mAluminium ) Fatal("Main", "FairMedium aluminium not found"); + geoBuild->createMedium(mAluminium); + TGeoMedium* aluminium = gGeoMan->GetMedium("aluminium"); + if ( ! aluminium ) Fatal("Main", "Medium aluminium not found"); + + // --- + gStsMedium = air; + // -------------------------------------------------------------------------- + + + // -------------- Create geometry and top volume ------------------------- + gGeoMan = (TGeoManager*)gROOT->FindObject("FAIRGeom"); +// gGeoMan->SetName("STSgeom"); + TGeoVolume* top = new TGeoVolumeAssembly("top"); +// TGeoBBox* topbox= new TGeoBBox("", 120., 120., 120.); +// TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air")); + gGeoMan->SetTopVolume(top); + // -------------------------------------------------------------------------- + + + // -------------- Create media ------------------------------------------ + /* + cout << endl; + cout << "===> Creating media...."; + cout << CreateMedia(); + cout << " media created" << endl; + TList* media = gGeoMan->GetListOfMedia(); + for (Int_t iMedium = 0; iMedium < media->GetSize(); iMedium++ ) { + cout << "Medium " << iMedium << ": " + << ((TGeoMedium*) media->At(iMedium))->GetName() << endl; + } + gStsMedium = gGeoMan->GetMedium("air"); + if ( ! gStsMedium ) Fatal("Main", "medium sts_air not found"); + */ + // -------------------------------------------------------------------------- + + + // --------------- Create sensors --------------------------------------- + cout << endl << endl; + cout << "===> Creating sensors...." << endl << endl; + infoFile << endl << "Sensors: " << endl; + Int_t nSensors = CreateSensors(); + for (Int_t iSensor = 1; iSensor <= nSensors; iSensor++) { + TString name = Form("Sensor%02d",iSensor); + TGeoVolume* sensor = gGeoMan->GetVolume(name); + + // add color to sensors + if (iSensor == 1) + sensor->SetLineColor(kRed); + if (iSensor == 2) + sensor->SetLineColor(kGreen); + if (iSensor == 3) + sensor->SetLineColor(kBlue); + if (iSensor == 4) + sensor->SetLineColor(kAzure); + if (iSensor == 5) + sensor->SetLineColor(kYellow); + if (iSensor == 6) + sensor->SetLineColor(kYellow); + if (iSensor == 7) + sensor->SetLineColor(kYellow); + + CheckVolume(sensor); + CheckVolume(sensor, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create sectors -------------------------------------- + cout << endl << endl; + cout << "===> Creating sectors...." << endl; + // infoFile << endl << "Sectors: " << endl; + Int_t nSectors = CreateSectors(); + for (Int_t iSector = 1; iSector <= nSectors; iSector++) { + // cout << endl; + TString name = Form("Sector%02d", iSector); + TGeoVolume* sector = gGeoMan->GetVolume(name); + CheckVolume(sector); + // CheckVolume(sector, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create ladders -------------------------------------- + cout << endl << endl; + cout << "===> Creating ladders...." << endl; + infoFile << endl << "Ladders:" << endl; + + TString name = ""; + TGeoVolume* ladder; + + + Int_t nLadders = CreateLadders(); + + for (Int_t iLadder = 1; iLadder <= nLadders; iLadder++) { + cout << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType0%02d", iLadder); // v19b + name = Form("LadderType00%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF1: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType1%02d", iLadder); // v19b + name = Form("LadderType01%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF2: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType10%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF3: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType11%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF4: ladder name: " << name << endl << endl; + } + // -------------------------------------------------------------------------- + + + // ---------------- Create cones ---------------------------------------- + Double_t coneDz = 1.64; + TGeoVolume* coneSmallVolum = ConstructSmallCone(coneDz); + if (!coneSmallVolum) Fatal("ConstructSmallCone", "Volume Cone not found"); + TGeoVolume* coneBigVolum = ConstructBigCone(coneDz); + if (!coneBigVolum) Fatal("ConstructBigCone", "Volume Cone not found"); + // -------------------------------------------------------------------------- + + + // ---------------- Create stations ------------------------------------- + cout << endl << endl; + cout << "===> Creating stations...." << endl; + infoFile << endl << "Stations: " << endl; + Int_t angle = 0; + nLadders = 0; + Int_t ladderTypes[16]; // there are max 16 ladders in one layer + TGeoTranslation* statTrans = NULL; + + TGeoVolume *myunit[32]; // units + +// Int_t statPos[8] = { 30, 40, 50, 60, 70, 80, 90, 100 }; // z positions of stations +// Int_t statPos[16] = { 28, 32, 38, 42, 48, 52, 58, 62, +// 68, 72, 78, 82, 88, 92, 98,102 }; // z positions of units +// Int_t statPos[16] = { 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units +// Int_t statPos18[18] = { 30, 30, // expanded for placement of Unit00 +// 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units + // v19h + Double_t statPos[16] = { 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of units + Double_t statPos18[18] = { 26.0, 26.0, // expanded for placement of Unit00 + 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of unit + +// // v19d +// Double_t statPos[16] = { 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units +// Double_t statPos18[18] = { 30.0, 30.0, // expanded for placement of Unit00 +// 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units + +////Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.9 , 3.7 , 3.7 , 4.2 , 4.2 }; // size of cutouts in stations +// Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.43, 3.04, 3.35, 3.96, 4.2 }; // size of cutouts in stations, derived from gapXYZ[x][1]/2 + + Int_t cone_size[8] = { 0, 0, 0, 1, 1, 1, 1, 1 }; // size of cones: 0 = small, 1 = large + + Double_t cone_offset[2] = { 0.305, 0.285 }; + +// Int_t allLadderTypes[8][16]= +// { { -1, -1, -1, -1, 10, 109, 9, 101, 1, 109, 9, 110, -1, -1, -1, -1 }, // station 1 +// { -1, -1, 111, 10, 110, 9, 109, 2, 102, 9, 109, 10, 110, 11, -1, -1 }, // station 2 +// { -1, -1, 14, 113, 12, 112, 12, 103, 3, 112, 12, 112, 13, 114, -1, -1 }, // station 3 +// { -1, 15, 114, 13, 112, 12, 112, 4, 104, 12, 112, 12, 113, 14, 115, -1 }, // station 4 +// { -1, 119, 18, 117, 17, 116, 16, 105, 5, 116, 16, 117, 17, 118, 19, -1 }, // station 5 +// { -1, 19, 118, 17, 117, 16, 116, 6, 106, 16, 116, 17, 117, 18, 119, -1 }, // station 6 +// { 21, 119, 18, 120, 20, 120, 20, 107, 7, 120, 20, 120, 20, 118, 19, 121 }, // station 7 +// { 119, 17, 123, 22, 122, 22, 122, 8, 108, 22, 122, 22, 122, 23, 117, 19 } }; // station 8 + +//============================================================================================== + +// explanation: type xyzz +// where x = carbon ladder orientation +// where y = FEB box orientation +// where zz = sensor arrangement on ladder +// with FEB orientation - v19b + Int_t allUnitTypes[16][16]= + { { -1, -1, -1, -1, 10, 0, 9, 0, 101, 0, 109, 0, -1, -1, -1, -1 }, // unit00D Station01 00 + { -1, -1, -1, -1, 0, 1109, 0, 1101, 0, 1009, 0, 1010, -1, -1, -1, -1 }, // unit01U Station01 01 + + { -1, -1, 0, 10, 0, 9, 0, 2, 0, 109, 0, 110, 0, 111, -1, -1 }, // unit01D Station02 02 + { -1, -1, 1111, 0, 1110, 0, 1109, 0, 1002, 0, 1009, 0, 1010, 0, -1, -1 }, // unit02U Station02 03 + + { -1, -1, 14, 0, 12, 0, 12, 0, 103, 0, 112, 0, 113, 0, -1, -1 }, // unit02D Station03 04 + { -1, -1, 0, 1113, 0, 1112, 0, 1103, 0, 1012, 0, 1012, 0, 1014, -1, -1 }, // unit03U Station03 05 + + { -1, 15, 0, 13, 0, 12, 0, 4, 0, 112, 0, 112, 0, 114, 0, -1 }, // unit03D Station04 06 + { -1, 0, 1114, 0, 1112, 0, 1112, 0, 1004, 0, 1012, 0, 1013, 0, 1015, -1 }, // unit04U Station04 07 + + { -1, 0, 18, 0, 17, 0, 16, 0, 105, 0, 116, 0, 117, 0, 119, -1 }, // unit04D Station05 08 + { -1, 1119, 0, 1117, 0, 1116, 0, 1105, 0, 1016, 0, 1017, 0, 1018, 0, -1 }, // unit05U Station05 09 + + { -1, 19, 0, 17, 0, 16, 0, 6, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05D Station06 10 + { -1, 0, 1118, 0, 1117, 0, 1116, 0, 1006, 0, 1016, 0, 1017, 0, 1019, -1 }, // unit06U Station06 11 + + { 21, 0, 25, 0, 20, 0, 20, 0, 107, 0, 120, 0, 120, 0, 127, 0 }, // unit06D Station07 12 + { 0, 1127, 0, 1120, 0, 1120, 0, 1107, 0, 1020, 0, 1020, 0, 1025, 0, 1021 }, // unit07U Station07 13 + + { 0, 24, 0, 22, 0, 22, 0, 8, 0, 122, 0, 122, 0, 123, 0, 126 }, // unit07D Station08 14 + { 1126, 0, 1123, 0, 1122, 0, 1122, 0, 1008, 0, 1022, 0, 1022, 0, 1024, 0 } }; // unit08U Station08 15 + +//============================================================================================== + +// without FEB orientation - v19a +// v19a Int_t allUnitTypes[16][16]= +// v19a { { -1, -1, -1, -1, 10, 0, 9, 0, 1, 0, 9, 0, -1, -1, -1, -1 }, // unit00D Station01 00 +// v19a { -1, -1, -1, -1, 0, 109, 0, 101, 0, 109, 0, 110, -1, -1, -1, -1 }, // unit01U Station01 01 +// v19a { -1, -1, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, -1, -1 }, // unit01D Station02 02 +// v19a { -1, -1, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, -1, -1 }, // unit02U Station02 03 +// v19a { -1, -1, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, -1, -1 }, // unit02D Station03 04 +// v19a { -1, -1, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, -1, -1 }, // unit03U Station03 05 +// v19a { -1, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, -1 }, // unit03D Station04 06 +// v19a { -1, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, -1 }, // unit04U Station04 07 +// v19a { -1, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, -1 }, // unit04D Station05 08 +// v19a { -1, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05U Station05 09 +// v19a { -1, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, -1 }, // unit05D Station06 10 +// v19a { -1, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, -1 }, // unit06U Station06 11 +// v19a { 21, 0, 25, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 27, 0 }, // unit06D Station07 12 +// v19a { 0, 127, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 125, 0, 121 }, // unit07U Station07 13 +// v19a { 0, 24, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 26 }, // unit07D Station08 14 +// v19a { 126, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 124, 0 } }; // unit08U Station08 15 + + +// unitTypes[0] = { 0, 0, 0, 0, 10, 0, 9, 0, 1, 0, 9, 0, 0, 0, 0, 0 }; // unit 0D +// unitTypes[1] = { 0, 0, 0, 0, 0, 109, 0, 101, 0, 109, 0, 110, 0, 0, 0, 0 }; // unit 1U +// unitTypes[2] = { 0, 0, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, 0, 0 }; // unit 1D +// unitTypes[3] = { 0, 0, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, 0, 0 }; // unit 2U +// unitTypes[4] = { 0, 0, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, 0, 0 }; // unit 2D +// unitTypes[5] = { 0, 0, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, 0, 0 }; // unit 3U +// unitTypes[6] = { 0, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, 0 }; // unit 3D +// unitTypes[7] = { 0, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, 0 }; // unit 4U +// unitTypes[8] = { 0, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, 0 }; // unit 4D +// unitTypes[9] = { 0, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, 0 }; // unit 5U +// unitTypes[10] = { 0, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, 0 }; // unit 5D +// unitTypes[11] = { 0, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, 0 }; // unit 6U +// unitTypes[12] = { 21, 0, 18, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 19, 0 }; // unit 6D +// unitTypes[13] = { 0, 119, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 118, 0, 121 }; // unit 7U +// unitTypes[14] = { 0, 17, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 19 }; // unit 7D +// unitTypes[15] = { 119, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 117, 0 }; // unit 8U + + +// // generate unit +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) +// for (Int_t iLadder = 0; iLadder < 16; iLadder++) +// { +// allUnitTypes[iUnit][iLadder] = 0; +// if ((iUnit % 2 == 0) && (allLadderTypes[iUnit/2][iLadder] < 100)) // if carbon structure is oriented upstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// if ((iUnit % 2 == 1) && (allLadderTypes[iUnit/2][iLadder] >= 100)) // if carbon structure is oriented downstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// } + + + // dump unit + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << "DE unitTypes[" << iUnit << "] = { "; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + { + cout << allUnitTypes[iUnit][iLadder]; + if (iLadder < 15) + cout << ", "; + else + cout << " };"; + } + cout << endl; + } + + + // --- Units 01 - 16 + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << endl; + + nLadders = 0; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + if (allUnitTypes[iUnit][iLadder] >= 0) + { + ladderTypes[nLadders] = allUnitTypes[iUnit][iLadder]; + cout << "DE ladderTypes[" << nLadders << "] = " << allUnitTypes[iUnit][iLadder] << ";" << endl; + nLadders++; + } + myunit[iUnit*2+0] = ConstructUnit(0, iUnit*2+0, nLadders, ladderTypes, iUnit/2+1); + myunit[iUnit*2+1] = ConstructUnit(1, iUnit*2+1, nLadders, ladderTypes, iUnit/2+1); + +// if (gkConstructCones) { +// if (iUnit%2 == 0) +// angle = 90; +// else +// angle = -90; +// +// // upstream +// TGeoRotation* coneRot11 = new TGeoRotation; +// coneRot11->RotateZ(angle); +// coneRot11->RotateY(180); +// TGeoCombiTrans* conePosRot11 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-cone_offset[cone_size[iUnit]]-gkLadderGapZ/2., coneRot11); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 1, conePosRot11); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 1, conePosRot11); +// +// // downstream +// TGeoRotation* coneRot12 = new TGeoRotation; +// coneRot12->RotateZ(angle); +// TGeoCombiTrans* conePosRot12 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+cone_offset[cone_size[iUnit]]+gkLadderGapZ/2., coneRot12); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 2, conePosRot12); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 2, conePosRot12); +// +// myunit[iUnit]->GetShape()->ComputeBBox(); +// } + +// CheckVolume(myunit[iUnit]); +// CheckVolume(myunit[iUnit], infoFile); + if ((iUnit%2 == 0)||(iUnit == 15)) + { + CheckVolume(myunit[iUnit*2+0]); + CheckVolume(myunit[iUnit*2+0], infoFile); + CheckVolume(myunit[iUnit*2+1]); + CheckVolume(myunit[iUnit*2+1], infoFile); + } + infoFile << "Position z = " << statPos[iUnit] << endl; + } + // -------------------------------------------------------------------------- + + + // --------------- Create STS volume ------------------------------------ + cout << endl << endl; + cout << "===> Creating STS...." << endl; + +// // --- Determine size of STS box +// Double_t stsX = 0.; +// Double_t stsY = 0.; +// Double_t stsZ = 0.; +// Double_t stsBorder = 2*5.; // 5 cm space for carbon ladders on each side +// for (Int_t iStation = 1; iStation<=8; iStation++) { +// TString statName = Form("Station%02d", iStation); +// TGeoVolume* station = gGeoMan->GetVolume(statName); +// TGeoBBox* shape = (TGeoBBox*) station->GetShape(); +// stsX = TMath::Max(stsX, 2.* shape->GetDX() ); +// stsY = TMath::Max(stsY, 2.* shape->GetDY() ); +// cout << "Station " << iStation << ": Y " << stsY << endl; +// } +// // --- Some border around the stations +// stsX += stsBorder; +// stsY += stsBorder; +// stsZ = ( statPos[7] - statPos[0] ) + stsBorder; +// +// // --- Create box around the stations +// new TGeoBBox("stsBox", stsX/2., stsY/2., stsZ/2.); +// cout << "size of STS box: x " << stsX << " - y " << stsY << " - z " << stsZ << endl; +// +// // --- Create cone hosting the beam pipe +// // --- One straight section with constant radius followed by a cone +// Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +// Double_t z2 = gkPipeZ2; +// Double_t z3 = statPos[7] + 0.5 * stsBorder; // end of STS box +// Double_t r1 = BeamPipeRadius(z1); +// Double_t r2 = BeamPipeRadius(z2); +// Double_t r3 = BeamPipeRadius(z3); +// r1 += 0.01; // safety margin +// r2 += 0.01; // safety margin +// r3 += 0.01; // safety margin +// +// cout << endl; +// cout << z1 << " " << r1 << endl; +// cout << z2 << " " << r2 << endl; +// cout << z3 << " " << r3 << endl; +// +// cout << endl; +// cout << "station1 : " << BeamPipeRadius(statPos[0]) << endl; +// cout << "station2 : " << BeamPipeRadius(statPos[1]) << endl; +// cout << "station3 : " << BeamPipeRadius(statPos[2]) << endl; +// cout << "station4 : " << BeamPipeRadius(statPos[3]) << endl; +// cout << "station5 : " << BeamPipeRadius(statPos[4]) << endl; +// cout << "station6 : " << BeamPipeRadius(statPos[5]) << endl; +// cout << "station7 : " << BeamPipeRadius(statPos[6]) << endl; +// cout << "station8 : " << BeamPipeRadius(statPos[7]) << endl; +// +// // TGeoPcon* cutout = new TGeoPcon("stsCone", 0., 360., 3); // 2.*TMath::Pi(), 3); +// // cutout->DefineSection(0, z1, 0., r1); +// // cutout->DefineSection(1, z2, 0., r2); +// // cutout->DefineSection(2, z3, 0., r3); +// new TGeoTrd2("stsCone1", r1, r2, r1, r2, (z2-z1)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans1 = new TGeoTranslation("trans1", 0., 0., -(z3-z1)/2.+(z2-z1)/2.); +// trans1->RegisterYourself(); +// new TGeoTrd2("stsCone2", r2, r3, r2, r3, (z3-z2)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans2 = new TGeoTranslation("trans2", 0., 0., +(z3-z1)/2.-(z3-z2)/2.); +// trans2->RegisterYourself(); +// +////DE Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +////DE Double_t z2 = statPos[7] + 0.5 * stsBorder; // end of STS box +////DE Double_t slope = (gkPipeR2 - gkPipeR1) / (gkPipeZ2 - gkPipeZ1); +////DE Double_t r1 = gkPipeR1 + slope * (z1 - gkPipeZ1); // at start of STS +////DE Double_t r2 = gkPipeR1 + slope * (z2 - gkPipeZ1); // at end of STS +////DE r1 += 0.1; // safety margin +////DE r2 += 0.1; // safety margin +////DE // new TGeoCone("stsCone", stsZ/2., 0., r1, 0., r2); +////DE new TGeoTrd2("stsCone", r1, r2, r1, r2, stsZ/2.); + + + // // Create holding/cooling plates + // static std::vector< std::vector<Double_t> > plateSizes = { + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // }; + + // // 8-vertex cut-outs { minWidth, maxWidth, minHeight, maxHeight } + // static std::vector< std::vector<Double_t> > plateCutOuts = { + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 17.6, 47.6 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 49.0, 79.0 }, + // { 85.5,115.5, 51.5, 82.8 }, + // { 85.5,115.5, 59.0, 91.4 }, + // { 85.5,115.5, 68.0, 99.0 }, + // }; + + // for (Int_t iPlate = 0; iPlate < 9; iPlate++) { + // Int_t iUnit = iPlate * 2; + // TGeoBBox* outerPlate = new TGeoBBox(Form("outerPlate%02d",iPlate), + // plateSizes[iPlate][0], plateSizes[iPlate][1], plateSizes[iPlate][2]); + + // TGeoBBox* unitShapeR = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+0])->GetShape(); + // TGeoBBox* unitShapeL = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+1])->GetShape(); + + // Double_t maxDx = (unitShapeR->GetDX() + unitShapeL->GetDX()) / 2.; + // Double_t maxDy = TMath::Max(unitShapeR->GetDY(), unitShapeL->GetDY()); + // cout << maxDy << endl; + + // Double_t* cutOutX = new Double_t[8]; + // Double_t* cutOutY = new Double_t[8]; + + // cutOutX[0] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[0] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[1] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[1] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[2] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[2] = 1/2. * plateCutOuts[iPlate][2]; + // cutOutX[3] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[3] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[4] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[4] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[5] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[5] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[6] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[6] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[7] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[7] = 1/2. * plateCutOuts[iPlate][2]; + + // TGeoXtru* cutOutShape = new TGeoXtru(2); + // cutOutShape->SetName(Form("innerPlate%02d", iPlate)); + // cutOutShape->DefinePolygon(8, cutOutX, cutOutY); + // cutOutShape->DefineSection(0, -1*plateSizes[iPlate][2]-1e-7); + // cutOutShape->DefineSection(1, +1*plateSizes[iPlate][2]+1e-7); + + // TGeoShape* plateShape = new TGeoCompositeShape(Form("PlateShape%02d",iPlate), Form("outerPlate%02d-innerPlate%02d",iPlate,iPlate)); + // TGeoVolume* plate = new TGeoVolume(Form("Plate%02d", iPlate), plateShape, gGeoManager->GetMedium("aluminium")); + // plate->SetLineColor(kRed); + // plate->SetTransparency(65); + // plate->GetShape()->ComputeBBox(); + // } + + // --- Create STS volume + TString stsName = "sts_"; + stsName += geoTag; + +// TGeoShape* stsShape = new TGeoCompositeShape("stsShape", +// "stsBox-stsCone1:trans1-stsCone2:trans2"); +// TGeoVolume* sts = new TGeoVolume(stsName.Data(), stsShape, gStsMedium); + + Double_t stsBorder = 2 * 5.; + + TGeoVolume* sts = new TGeoVolumeAssembly(stsName.Data()); + + // --- Place stations in the STS + Double_t stsPosZ = 0.5 * ( statPos[15] + statPos[0] ); // todo units: update statPos[7] + // cout << "stsPosZ " << stsPosZ << " " << statPos[15] << " " << statPos[0] << "*****" << endl; + +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) { + for (Int_t iUnit = 0; iUnit < 18; iUnit++) { +// for (Int_t iUnit = 0; iUnit < 32; iUnit++) { + TGeoVolume* station = gGeoMan->GetVolume(unitName18[iUnit]); +// Double_t posZ = statPos[iUnit] - stsPosZ; + Double_t posZ = statPos18[iUnit] - stsPosZ; +// Double_t posZ = statPos[iUnit/2] - stsPosZ; + TGeoTranslation* trans = new TGeoTranslation(0., 0., posZ); + sts->AddNode(station, iUnit+1, trans); + sts->GetShape()->ComputeBBox(); + } + + // --- Import passive elements from GDML file + if (gkImportPassive) { + ImportPassive(sts, geoTag, infoFile); + } + + cout << endl; + CheckVolume(sts); + // -------------------------------------------------------------------------- + + + // --------------- Finish ----------------------------------------------- + TGeoTranslation* stsTrans = new TGeoTranslation(0., 0., stsPosZ); + top->AddNode(sts, 1, stsTrans); + top->GetShape()->ComputeBBox(); + cout << endl << endl; + + CheckVolume(top); + cout << endl << endl; + gGeoMan->CloseGeometry(); + gGeoMan->CheckOverlaps(0.0001); + gGeoMan->PrintOverlaps(); + gGeoMan->CheckOverlaps(0.0001, "s"); + gGeoMan->PrintOverlaps(); + gGeoMan->Test(); + + TFile* geoFile = new TFile(geoFileName, "RECREATE"); + top->Write(); + cout << endl; + cout << "Geometry " << top->GetName() << " written to " + << geoFileName << endl; + geoFile->Close(); + + TString geoFileName_ = "sts_"; + geoFileName_ = geoFileName_ + geoTag + "_geo.root"; + + geoFile = new TFile(geoFileName_, "RECREATE"); + gGeoMan->Write(); // use this is you want GeoManager format in the output + geoFile->Close(); + + TString geoFileName__ = "sts_"; + geoFileName_ = geoFileName__ + geoTag + "-geo.root"; + sts->Export(geoFileName_); + + geoFile = new TFile(geoFileName_, "UPDATE"); + stsTrans->Write(); + geoFile->Close(); + + // gGeoManager->FindVolumeFast("LadderType10_CarbonElement")->Draw("ogl"); + top->Draw("ogl"); + gGeoManager->SetVisLevel(8); + + infoFile.close(); + +} +// ============================================================================ +// ====== End of main function ===== +// ============================================================================ + + + + + +// **************************************************************************** +// ***** Definition of media, sensors, sectors and ladders ***** +// ***** ***** +// ***** Decoupled from main function for better readability ***** +// **************************************************************************** + + +/** =========================================================================== + ** Create media + ** + ** Currently created: air, active silicon, passive silion + ** + ** Not used for the time being + **/ +Int_t CreateMedia() { + + Int_t nMedia = 0; + Double_t density = 0.; + + // --- Material air + density = 1.205e-3; // [g/cm^3] + TGeoMixture* matAir = new TGeoMixture("sts_air", 3, density); + matAir->AddElement(14.0067, 7, 0.755); // Nitrogen + matAir->AddElement(15.999, 8, 0.231); // Oxygen + matAir->AddElement(39.948, 18, 0.014); // Argon + + // --- Material silicon + density = 2.33; // [g/cm^3] + TGeoElement* elSi = gGeoMan->GetElementTable()->GetElement(14); + TGeoMaterial* matSi = new TGeoMaterial("matSi", elSi, density); + + + // --- Air (passive) + TGeoMedium* medAir = new TGeoMedium("air", nMedia++, matAir); + medAir->SetParam(0, 0.); // is passive + medAir->SetParam(1, 1.); // is in magnetic field + medAir->SetParam(2, 20.); // max. field [kG] + medAir->SetParam(6, 0.001); // boundary crossing precision [cm] + + + // --- Active silicon for sensors + TGeoMedium* medSiAct = new TGeoMedium("silicon", + nMedia++, matSi); + medSiAct->SetParam(0, 1.); // is active + medSiAct->SetParam(1, 1.); // is in magnetic field + medSiAct->SetParam(2, 20.); // max. field [kG] + medSiAct->SetParam(6, 0.001); // boundary crossing precisison [cm] + + // --- Passive silicon for cables + TGeoMedium* medSiPas = new TGeoMedium("carbon", + nMedia++, matSi); + medSiPas->SetParam(0, 0.); // is passive + medSiPas->SetParam(1, 1.); // is in magnetic field + medSiPas->SetParam(2, 20.); // max. field [kG] + medSiPas->SetParam(6, 0.001); // boundary crossing precisison [cm] + + return nMedia; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sensors + ** + ** Sensors are created as volumes with box shape and active silicon as medium. + ** Four kinds of sensors: 3.2x2.2, 6.2x2.2, 6.2x4.2, 6.2x6.2 + **/ +Int_t CreateSensors() { + + Int_t nSensors = 0; + + Double_t xSize = 0.; + Double_t ySize = 0.; + Double_t zSize = gkSensorThickness; + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + + + // --- Sensor type 01: Small sensor (6.2 cm x 2.2 cm) + xSize = gkSensorSizeX; + ySize = 2.2; + TGeoBBox* shape_sensor01 = new TGeoBBox("sensor01", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor01", shape_sensor01, silicon); + nSensors++; + + + // --- Sensor type 02: Medium sensor (6.2 cm x 4.2 cm) + xSize = gkSensorSizeX; + ySize = 4.2; + TGeoBBox* shape_sensor02 = new TGeoBBox("sensor02", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor02", shape_sensor02, silicon); + nSensors++; + + + // --- Sensor type 03: Big sensor (6.2 cm x 6.2 cm) + xSize = gkSensorSizeX; + ySize = 6.2; + TGeoBBox* shape_sensor03 = new TGeoBBox("sensor03", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor03", shape_sensor03, silicon); + nSensors++; + + + // --- Sensor type 04: Big sensor (6.2 cm x 12.4 cm) + xSize = gkSensorSizeX; + ySize = 12.4; + TGeoBBox* shape_sensor04 = new TGeoBBox("sensor04", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor04", shape_sensor04, silicon); + nSensors++; + + + // below are extra small sensors, those are not available in the CAD model + + // --- Sensor Type 05: Half small sensor (4 cm x 2.5 cm) + xSize = 4.0; + ySize = 2.5; + TGeoBBox* shape_sensor05 = new TGeoBBox("sensor05", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor05", shape_sensor05, silicon); + nSensors++; + + + // --- Sensor type 06: Additional "in hole" sensor (3.1 cm x 4.2 cm) + xSize = 3.1; + ySize = 4.2; + TGeoBBox* shape_sensor06 = new TGeoBBox("sensor06", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor06", shape_sensor06, silicon); + nSensors++; + + + // --- Sensor type 07: Mini Medium sensor (1.5 cm x 4.2 cm) + xSize = 1.5; + ySize = 4.2; + TGeoBBox* shape_sensor07 = new TGeoBBox("sensor07", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor07", shape_sensor07, silicon); + nSensors++; + + + return nSensors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sectors + ** + ** A sector is either a single sensor or several chained sensors. + ** It is implemented as TGeoVolumeAssembly. + ** Currently available: + ** - single sensors of type 1 - 4 + ** - two chained sensors of type 4 + ** - three chained sensors of type 4 + **/ +Int_t CreateSectors() { + + Int_t nSectors = 0; + + TGeoVolume* sensor01 = gGeoMan->GetVolume("Sensor01"); + TGeoVolume* sensor02 = gGeoMan->GetVolume("Sensor02"); + TGeoVolume* sensor03 = gGeoMan->GetVolume("Sensor03"); + TGeoVolume* sensor04 = gGeoMan->GetVolume("Sensor04"); + TGeoVolume* sensor05 = gGeoMan->GetVolume("Sensor05"); + TGeoVolume* sensor06 = gGeoMan->GetVolume("Sensor06"); + TGeoVolume* sensor07 = gGeoMan->GetVolume("Sensor07"); + // TGeoBBox* box4 = (TGeoBBox*) sensor04->GetShape(); + + // --- Sector type 1: single sensor of type 1 + TGeoVolumeAssembly* sector01 = new TGeoVolumeAssembly("Sector01"); + sector01->AddNode(sensor01, 1); + sector01->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 2: single sensor of type 2 + TGeoVolumeAssembly* sector02 = new TGeoVolumeAssembly("Sector02"); + sector02->AddNode(sensor02, 1); + sector02->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 3: single sensor of type 3 + TGeoVolumeAssembly* sector03 = new TGeoVolumeAssembly("Sector03"); + sector03->AddNode(sensor03, 1); + sector03->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 4: single sensor of type 4 + TGeoVolumeAssembly* sector04 = new TGeoVolumeAssembly("Sector04"); + sector04->AddNode(sensor04, 1); + sector04->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 5: single sensor of type 5 + TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); + sector05->AddNode(sensor05, 1); + sector05->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 6: single sensor of type 6 + TGeoVolumeAssembly* sector06 = new TGeoVolumeAssembly("Sector06"); + sector06->AddNode(sensor06, 1); + sector06->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 7: single sensor of type 7 + TGeoVolumeAssembly* sector07 = new TGeoVolumeAssembly("Sector07"); + sector07->AddNode(sensor07, 1); + sector07->GetShape()->ComputeBBox(); + nSectors++; + +// // --- Sector type 5: two sensors of type 4 +// TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); +// Double_t shift5 = 0.5 * gkChainGapY + box4->GetDY(); +// TGeoTranslation* transD5 = +// new TGeoTranslation("td", 0., -1. * shift5, 0.); +// TGeoTranslation* transU5 = +// new TGeoTranslation("tu", 0., shift5, 0.); +// sector05->AddNode(sensor04, 1, transD5); +// sector05->AddNode(sensor04, 2, transU5); +// sector05->GetShape()->ComputeBBox(); +// nSectors++; + + return nSectors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create ladders + ** + ** Ladders are the building blocks of the stations. They contain + ** several modules placed one after the other along the z axis + ** such that the sectors are arranged vertically (with overlap). + ** + ** A ladder is constructed out of two half ladders, the second of which + ** is rotated in the x-y plane by 180 degrees and displaced + ** in z direction. + **/ +Int_t CreateLadders() { + + Int_t nLadders = 0; + + // --- Some variables + Int_t nSectors = 0; + Int_t sectorTypes[10]; + TGeoBBox* shape = NULL; + TString s0name; + TString hlname; + char align; + TGeoVolume* s0vol = NULL; + TGeoVolume* halfLadderU = NULL; + TGeoVolume* halfLadderD = NULL; + + // --- Ladders 01-23 + Int_t allSectorTypes[27][6] = { { 1, 2, 3, 3, 0, -1 }, // ladder 01 - 5 - last column defines alignment of small sensors + { 1, 2, 3, 3, 0, 0 }, // ladder 02 - 5 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, -1 }, // ladder 03 - 6 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 04 - 6 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, -1 }, // ladder 05 - 7 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 06 - 7 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 07 - last column defines alignment of small sensors + { 3, 4, 4, 4, 0, 0 }, // ladder 08 - last column defines alignment of small sensors + + { 1, 1, 2, 3, 3, 0 }, // ladder 09 - last column defines alignment of small sensors + { 1, 1, 2, 2, 3, 0 }, // ladder 10 - last column defines alignment of small sensors + { 2, 2, 0, 0, 0, 0 }, // ladder 11 - last column defines alignment of small sensors + { 2, 2, 2, 3, 4, 0 }, // ladder 12 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 13 - last column defines alignment of small sensors + + { 2, 3, 4, 0, 0, 0 }, // ladder 14 - last column defines alignment of small sensors + { 3, 3, 0, 0, 0, 0 }, // ladder 15 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 16 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 17 - last column defines alignment of small sensors + { 3, 4, 4, 0, 0, 0 }, // ladder 18 - last column defines alignment of small sensors + + { 4, 4, 0, 0, 0, 0 }, // ladder 19 - last column defines alignment of small sensors + { 1, 2, 4, 4, 4, 0 }, // ladder 20 - last column defines alignment of small sensors + { 4, 0, 0, 0, 0, 0 }, // ladder 21 - last column defines alignment of small sensors + { 2, 3, 4, 4, 4, 0 }, // ladder 22 - last column defines alignment of small sensors + { 2, 3, 3, 4, 4, 0 }, // ladder 23 - last column defines alignment of small sensors + + { 2, 3, 4, 4, 0, 0 }, // ladder 24 - copy of 17 with different total length + { 3, 4, 4, 0, 0, 0 }, // ladder 25 - copy of 18 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 26 - copy of 19 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 27 - copy of 19 with different total length + }; // 8 full - 19 partial ladders + +// Issue #405 +// Counting from the most upstream ladder, the gaps between sensors are as follows: +// 01 (most upstream): 41.3mm +// 02: 41.3mm +// 03: 42.0mm +// 04: 48.6mm +// 05: 60.8mm +// 06: 67.0mm +// 07: 79.2mm +// 08 (most downstream): 88.0mm + + Double_t pitchZ = 0; + Double_t gapXYZ[27][3] = { + { 0., 4.13, 0. }, // ladder 01 + { 0., 4.13, 0. }, // ladder 02 + { 0., 4.20, 0. }, // ladder 03 + { 0., 4.86, 0. }, // ladder 04 + { 0., 6.08, 0. }, // ladder 05 + { 0., 6.70, 0. }, // ladder 06 + { 0., 7.92, 0. }, // ladder 07 + { 0., 8.80, 0. }, // ladder 08 + { 0., -gkSectorOverlapY, 0. }, // ladder 09 + { 0., -gkSectorOverlapY, 0. }, // ladder 10 + { 0., -gkSectorOverlapY, 0. }, // ladder 11 + { 0., -gkSectorOverlapY, 0. }, // ladder 12 + { 0., -gkSectorOverlapY, 0. }, // ladder 13 + { 0., -gkSectorOverlapY, 0. }, // ladder 14 + { 0., -gkSectorOverlapY, 0. }, // ladder 15 + { 0., -gkSectorOverlapY, 0. }, // ladder 16 + { 0., -gkSectorOverlapY, 0. }, // ladder 17 + { 0., -gkSectorOverlapY, 0. }, // ladder 18 + { 0., -gkSectorOverlapY, 0. }, // ladder 19 + { 0., -gkSectorOverlapY, 0. }, // ladder 20 + { 0., -gkSectorOverlapY, 0. }, // ladder 21 + { 0., -gkSectorOverlapY, 0. }, // ladder 22 + { 0., -gkSectorOverlapY, 0. }, // ladder 23 + + { 0., -gkSectorOverlapY, 0. }, // ladder 24 - copy of 17 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 25 - copy of 18 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 26 - copy of 19 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 27 - copy of 19 with different total length + }; + + Double_t ladderLength[27] = { + 48.0, // ladder 01 + 48.0, // ladder 02 + 64.0, // ladder 03 + 64.0, // ladder 04 + 80.0, // ladder 05 + 80.0, // ladder 06 + 92.0, // ladder 07 + 96.0, // ladder 08 + 48.0, // ladder 09 + 48.0, // ladder 10 + 48.0, // ladder 11 + 64.0, // ladder 12 + 64.0, // ladder 13 + 64.0, // ladder 14 + 64.0, // ladder 15 + 80.0, // ladder 16 + 80.0, // ladder 17 + 80.0, // ladder 18 + 80.0, // ladder 19 + 92.0, // ladder 20 + 92.0, // ladder 21 + 96.0, // ladder 22 + 96.0, // ladder 23 + + 96.0, // ladder 24 - copy of 17 with different total length + 92.0, // ladder 25 - copy of 18 with different total length + 96.0, // ladder 26 - copy of 19 with different total length + 92.0, // ladder 27 - copy of 19 with different total length + }; +// ======================================================================== + + // calculate Z shift for ladders with and without gaps in the center + s0name = Form("Sector%02d", allSectorTypes[0][0]); + s0vol = gGeoMan->GetVolume(s0name); + shape = (TGeoBBox*) s0vol->GetShape(); + +// ======================================================================== + + for (Int_t iLadder = 0; iLadder < 27; iLadder++) + { + cout << endl; + nSectors = 0; + for (Int_t i=0; i < 5; i++) + if (allSectorTypes[iLadder][i] != 0) + { + sectorTypes[nSectors] = allSectorTypes[iLadder][i]; // copy sectors for this ladder + cout << "DE iLadder " << iLadder+1 << " sectorTypes[" << nSectors << "] = " << allSectorTypes[iLadder][i] << ";" << endl; + nSectors++; // count how many sectors are in this ladder + } + + // always set displacement in z between upper and lower half ladder + gapXYZ[iLadder][2] = 2. * shape->GetDZ() + gkSectorGapZ; + + // define additional offset to carbon ladder for half ladders with less than 5 sensors + pitchZ = 2. * shape->GetDZ() + gkSectorGapZ; + + if (allSectorTypes[iLadder][5] == 0) + align = 'l'; + else + align = 'r'; + hlname = Form("HalfLadder%02du", iLadder+1); + // build upper half ladder + Int_t Ustart = 0; // 1; + if (iLadder < 8) + Ustart = 1; // 0; + halfLadderU = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2., Ustart); // mirrored + + if (allSectorTypes[iLadder][5] == 0) + align = 'r'; + else + align = 'l'; + hlname = Form("HalfLadder%02dd", iLadder+1); + // build lower half ladder + Int_t Dstart = 1; // 0; + if (iLadder < 8) + Dstart = 0; // 1; + halfLadderD = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2., Dstart); // mirrored + + // at this point half ladders are constructed + + // build all 4 possible ladders types for this sensor arrangement + ConstructLadder( iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19a + ConstructLadder( 100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19b + + ConstructLadder(1000+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19k + ConstructLadder(1100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19k + + nLadders++; + } + + return nLadders; +} +/** ======================================================================= **/ + + + +// **************************************************************************** +// ***** ***** +// ***** Generic functions for the construction of STS elements ***** +// ***** ***** +// ***** module: volume (made of a sector and a cable) ***** +// ***** haf ladder: assembly (made of modules) ***** +// ***** ladder: assembly (made of two half ladders) ***** +// ***** station: volume (made of ladders) ***** +// ***** ***** +// **************************************************************************** + + + +/** =========================================================================== + ** Construct a module + ** + ** A module is a sector plus the readout cable extending from the + ** top of the sector. The cable is made from passive silicon. + ** The cable has the same x size as the sector. + ** Its thickness is given by the global variable gkCableThickness. + ** The cable length is a parameter. + ** The sensor(s) of the sector is/are placed directly in the module; + ** the sector is just auxiliary for the proper placement. + ** + ** Arguments: + ** name volume name + ** sector pointer to sector volume + ** cableLength length of cable + **/ +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength) { + + // --- Check sector volume + if ( ! sector ) Fatal("CreateModule", "Sector volume not found!"); + + // --- Get size of sector + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + + // --- Get size of cable + Double_t cableX = sectorX; + Double_t cableY = cableLength; + Double_t cableZ = gkCableThickness; + + // --- Create module volume + Double_t moduleX = TMath::Max(sectorX, cableX); + Double_t moduleY = sectorY + cableLength; + + Double_t moduleZ = TMath::Max(sectorZ, cableZ); + + TGeoVolume* module = gGeoManager->MakeBox(name, gStsMedium, + moduleX/2., + moduleY/2., + moduleZ/2.); + + // --- Position of sector in module + // --- Sector is centred in x and z and aligned to the bottom + Double_t sectorXpos = 0.; + Double_t sectorYpos = 0.5 * (sectorY - moduleY); + Double_t sectorZpos = 0.; + + + // --- Get sensor(s) from sector + Int_t nSensors = sector->GetNdaughters(); + for (Int_t iSensor = 0; iSensor < nSensors; iSensor++) { + TGeoNode* sensor = sector->GetNode(iSensor); + + // --- Calculate position of sensor in module + const Double_t* xSensTrans = sensor->GetMatrix()->GetTranslation(); + Double_t sensorXpos = sectorXpos + xSensTrans[0]; + Double_t sensorYpos = sectorYpos + xSensTrans[1]; + Double_t sensorZpos = sectorZpos + xSensTrans[2]; + TGeoTranslation* sensTrans = new TGeoTranslation("sensTrans", + sensorXpos, + sensorYpos, + sensorZpos); + + // --- Add sensor volume to module + TGeoVolume* sensVol = sensor->GetVolume(); + module->AddNode(sensor->GetVolume(), iSensor+1, sensTrans); + module->GetShape()->ComputeBBox(); + } + + + // --- Create cable volume, if necessary, and place it in module + // --- Cable is centred in x and z and aligned to the top + if ( gkConstructCables && cableLength > 0.0001 ) { + TString cableName = TString(name) + "_cable"; + TGeoMedium* cableMedium = gGeoMan->GetMedium("STScable"); + if ( ! cableMedium ) Fatal("CreateModule", "Medium STScable not found!"); + TGeoVolume* cable = gGeoManager->MakeBox(cableName.Data(), + cableMedium, + cableX / 2., + cableY / 2., + cableZ / 2.); + // add color to cables + cable->SetLineColor(kOrange); + cable->SetTransparency(60); + Double_t cableXpos = 0.; + Double_t cableYpos = sectorY + 0.5 * cableY - 0.5 * moduleY; + Double_t cableZpos = 0.; + TGeoTranslation* cableTrans = new TGeoTranslation("cableTrans", + cableXpos, + cableYpos, + cableZpos); + module->AddNode(cable, 1, cableTrans); + module->GetShape()->ComputeBBox(); + } + + return module; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a half ladder + ** + ** A half ladder is a virtual volume (TGeoVolumeAssembly) consisting + ** of several modules arranged on top of each other. The modules + ** have a given overlap in y and a displacement in z to allow for the + ** overlap. + ** + ** The typ of sectors / modules to be placed must be specified: + ** 1 = sensor01 + ** 2 = sensor02 + ** 3 = sensor03 + ** 4 = sensor04 + ** 5 = 2 x sensor04 (chained) + ** 6 = 3 x sensor04 (chained) + ** The cable is added automatically from the top of each sensor to + ** the top of the half ladder. + ** The alignment can be left (l) or right (r), which matters in the + ** case of different x sizes of sensors (e.g. SensorType01). + ** + ** Arguments: + ** name volume name + ** nSectors number of sectors + ** sectorTypes array with sector types + ** align horizontal alignment of sectors + * ladderLength full length of the ladder towards FEE + * offsetY gap in the beam-pipe region + **/ +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY, + Int_t start) { + + // --- Create half ladder volume assembly + TGeoVolumeAssembly* halfLadder = new TGeoVolumeAssembly(name); + + // --- Determine size of ladder + Double_t ladderX = 0.; + Double_t ladderY = 0.; + Double_t ladderZ = 0.; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + if ( ! sector ) + Fatal("ConstructHalfLadder", Form("Volume %s not found", sectorName.Data())); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + // --- Ladder x size equals largest sector x size + ladderX = TMath::Max(ladderX, 2. * box->GetDX()); + // --- Ladder y size is sum of sector ysizes + ladderY += 2. * box->GetDY(); + // --- Ladder z size is sum of sector z sizes + ladderZ += 2. * box->GetDZ(); + + cout << "DETT " << ladderX << " ; " << ladderY << " ; " << ladderZ << endl; + } + // --- Subtract overlaps in y + ladderY -= Double_t(nSectors-1) * gkSectorOverlapY; + // --- Add gaps in z direction + ladderZ += Double_t(nSectors-1) * gkSectorGapZ; + + ladderY = TMath::Max(ladderLength - offsetY, ladderY); + + // --- Create and place modules + Double_t yPosSect = -0.5 * ladderY; + Double_t zPosMod = -0.5 * ladderZ; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + yPosSect += 0.5 * sectorY; // Position of sector in ladder + Double_t cableLength = 0.5 * ladderY - yPosSect - 0.5 * sectorY; + TString moduleName = name + "_" + Form("Module%02d", + sectorTypes[iSector]); + TGeoVolume* module = ConstructModule(moduleName.Data(), + sector, cableLength); + + TGeoBBox* shapeMod = (TGeoBBox*) module->GetShape(); + Double_t moduleX = 2. * shapeMod->GetDX(); + Double_t moduleY = 2. * shapeMod->GetDY(); + Double_t moduleZ = 2. * shapeMod->GetDZ(); + Double_t xPosMod = 0.; + if ( align == 'l' ) + xPosMod = 0.5 * (moduleX - ladderX); // left aligned + else if ( align == 'r' ) + xPosMod = 0.5 * (ladderX - moduleX); // right aligned + else + xPosMod = 0.; // centred in x + Double_t yPosMod = 0.5 * (ladderY - moduleY); // top aligned + zPosMod += 0.5 * moduleZ; + +// Int_t angle = 0; // set default rotation angle to 0 +// if (iSector%2 == 1) // set rotation angle for every 2nd sensor +// angle = 180; + + Int_t angle = start * 180; + start = (start + 1) % 2; + + TGeoRotation* rmod = new TGeoRotation(); + rmod->RotateY(angle); + TGeoCombiTrans* cmod = new TGeoCombiTrans (xPosMod, yPosMod, zPosMod, rmod); + halfLadder->AddNode(module, iSector+1, cmod); + +// old style +// TGeoTranslation* trans = new TGeoTranslation("t", xPosMod, yPosMod, zPosMod); +// halfLadder->AddNode(module, iSector+1, trans); + + halfLadder->GetShape()->ComputeBBox(); + yPosSect += 0.5 * sectorY - gkSectorOverlapY; + zPosMod += 0.5 * moduleZ + gkSectorGapZ; + } + + CheckVolume(halfLadder); + cout << endl; + + return halfLadder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Add a carbon support to a ladder + ** + ** Arguments: + ** LadderIndex ladder number + ** ladder pointer to ladder + ** xu size of halfladder + ** ladderY height of ladder along y + ** ladderZ thickness of ladder along z + **/ +void AddCarbonLadder(Int_t LadderIndex, + TGeoVolume* ladder, + Double_t xu, + Double_t ladderY, + Double_t ladderZ) { + + // --- Some variables + TString name = Form("LadderType%04d", LadderIndex); // v19k + Int_t i; + Double_t j; + + Int_t YnumOfFrameBoxes = round(ladderY / gkFrameStep); + + // cout << "DEXZ: lad " << LadderIndex << " inum " << YnumOfFrameBoxes << endl; + + Double_t ladderDZ = (xu/2. + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2)/2.; + cout << "DEFR: frame Z size " << 2 * ladderDZ << " cm" << endl; + + TGeoBBox* fullFrameShp = new TGeoBBox (name+"_CarbonElement_shp", xu/2., gkFrameStep/2., ladderDZ); + TGeoVolume* fullFrameBoxVol = new TGeoVolume(name+"_CarbonElement", fullFrameShp, gStsMedium); + + ConstructFrameElement("CarbonElement", fullFrameBoxVol, xu/2.); + TGeoRotation* fullFrameRot = new TGeoRotation; + fullFrameRot->RotateY(180); + + Int_t inum = YnumOfFrameBoxes; + for (i=1; i<=inum; i++) + { + j=-(inum-1)/2.+(i-1); + // -(10-1)/2. +0 +10-1 -> -4.5 .. +4.5 -> -0.5, +0.5 (= 2) + // -(11-1)/2. +0 +11-1 -> -5.0 .. +5.0 -> -1, 0, 1 (= 3) + // cout << "DE: i " << i << " j " << j << endl; + + if (LadderIndex % 100 <= 3) // central ladders in stations 1 to 3 + { + if ((j>=-1) && (j<=1)) // keep the inner 2 (even) or 3 (odd) elements free for the cone + continue; + } + else if (LadderIndex % 100 <= 8) // central ladders in stations 4 to 8 + { + if ((j>=-2) && (j<=2)) // keep the inner 4 elements free for the cone + continue; + } + + cout << "DELZ: ladderDZ " << ladderDZ << " cm " << -ladderZ/2. - ladderDZ << " cm " << endl; + ladder->AddNode(fullFrameBoxVol, i, new TGeoCombiTrans(name+"_CarbonElement_posrot", 0., j*gkFrameStep, -(ladderZ/2.+ladderDZ), fullFrameRot)); + } + + ladder->GetShape()->ComputeBBox(); + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Construct a ladder out of two half ladders with vertical gap + ** + ** The second half ladder will be rotated by 180 degrees + ** in the x-y plane. The two half ladders will be put on top of each + ** other with a vertical gap. + ** + ** Arguments: + ** name volume name + ** halfLadderU pointer to upper half ladder + ** halfLadderD pointer to lower half ladder + ** gapY vertical gap + ** shiftZ relative displacement along the z axis + **/ + + TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ, + Double_t pitchZ, + Int_t nSectors) { + + // --- Some variables + TGeoBBox* shape = NULL; + + // define additional offset to carbon ladder for half ladders with less than 5 sensors + Double_t offsetZ = (5 - nSectors) * pitchZ; + + // --- Dimensions of half ladders + shape = (TGeoBBox*) halfLadderU->GetShape(); // up + Double_t xu = 2. * shape->GetDX(); + Double_t yu = 2. * shape->GetDY(); + Double_t zu = 2. * shape->GetDZ(); + + shape = (TGeoBBox*) halfLadderD->GetShape(); // down + Double_t xd = 2. * shape->GetDX(); + Double_t yd = 2. * shape->GetDY(); + Double_t zd = 2. * shape->GetDZ(); + + // --- Create ladder volume assembly + TString name = Form("LadderType%04d", LadderIndex); // v19k + TGeoVolumeAssembly* ladder = new TGeoVolumeAssembly(name); + Double_t ladderX = TMath::Max(xu, xd); + Double_t ladderY = yu + yd + gapY; + Double_t ladderZ = TMath::Max(zu, zd + shiftZ + offsetZ); // there are 6 slots - 5 x 1.5 mm + 0.3 mm = 7.8 mm + // Double_t ladderZ = TMath::Max(zu, zd + shiftZ); + + cout << "DERR iladder " << LadderIndex << " nSec " << nSectors + << " zu " << zu << " zd " << zd + << " zd+shi " << zd+shiftZ << " ladderZ " << ladderZ + << " offsetZ " << offsetZ << endl; + + // --- Place half ladders + Double_t xPosU = 0.0; // centred in x + Double_t yPosU = 0.5 * ( ladderY - yu ); // top aligned + Double_t zPosU = 0; + zPosU = 0.5 * ( ladderZ - zu ); // front aligned + if (LadderIndex >= 1000) + zPosU = -0.5 * ( ladderZ - zu ) + offsetZ; // back aligned with possible offset + //zPosU = -zPosU; + + TGeoTranslation* tu = new TGeoTranslation("tu", xPosU, yPosU, zPosU); + ladder->AddNode(halfLadderU, 1, tu); + + Double_t xPosD = 0.0; // centred in x + Double_t yPosD = 0.5 * -( ladderY - yd ); // bottom aligned + Double_t zPosD = 0; + zPosD = 0.5 * -( ladderZ - zd ) + offsetZ; // back aligned with possible offset + if (LadderIndex >= 1000) + zPosD = -0.5 * -( ladderZ - zd ); // front aligned + //zPosD = -zPosD; + + TGeoRotation* rd = new TGeoRotation(); + rd->RotateZ(180.); + TGeoCombiTrans* cd = new TGeoCombiTrans(xPosD, yPosD, zPosD, rd); + ladder->AddNode(halfLadderD, 2, cd); + + ladder->GetShape()->ComputeBBox(); + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD0ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + cout << "DDDD ladder" << LadderIndex << endl; + cout << "DDDD1ladder" << LadderIndex << " ladderX " << ladderX << " ladderY " << ladderY << " ladderZ " << ladderZ << endl; + + // ---------------- Create and place frame boxes ------------------------ + + if (gkConstructFrames) + AddCarbonLadder(LadderIndex, ladder, ladderX, ladderY, ladderZ); + + // -------------------------------------------------------------------------- + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD2ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + return ladder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a unit + ** + ** The unit volume is the minimal box comprising all ladders + ** minus a tube accomodating the beam pipe. + ** + ** The ladders are arranged horizontally from left to right with + ** a given overlap in x. + ** Every second ladder is slightly displaced upstream from the centre + ** z plane and facing downstream, the others are slightly displaced + ** downstream and facing upstream (rotated around the y axis). + ** + ** Arguments: + ** name volume name + ** nLadders number of ladders + ** ladderTypes array of ladder types + **/ + + TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation) { + + Bool_t isFirstPartOfHalfUnit = kFALSE; + + // TString name = Form("Unit%02d", iUnit); // 0,1,2,3,4,5,6,7 - Unit00 missing in output + // TString name = Form("Unit%02d", iUnit+1); // 1,2,3,4,5,6,7,8 + + TGeoVolume* unit = gGeoMan->GetVolume(unitName[iUnit]); + if ( ! unit ) // if it does not yet exist, create a new one + { + unit = new TGeoVolumeAssembly(unitName[iUnit]); + isFirstPartOfHalfUnit = kTRUE; + } + + // --- Some local variables + TGeoBBox* ladderShape = NULL; + TGeoVolume* ladder = NULL; + TString ladderName; + Double_t subtractedVal; + + // --- Determine size of unit from ladders + Double_t statX = 0.; + // Double_t statY = 0.; + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) + { + Int_t ladderType = ladderTypes[iLadder]; // v19k + +// if (iSide == 0) cout << "DWER " << ladderTypes[iLadder] << " " << ladderType << endl; + + if (ladderType > 0) + { + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + if ( ! ladder ) Fatal("ConstructUnit", + Form("Volume %s not found", ladderName.Data())); + ladderShape = (TGeoBBox*) ladder->GetShape(); + statX += 2. * ladderShape->GetDX(); + } + else + statX += gkSensorSizeX; // empty ladder in unit + } + statX -= Double_t(nLadders-1) * gkLadderOverlapX; + +// if (iSide == 0) cout << "DWER -" << endl; + + // --- Place ladders in unit + cout << "xPos0: " << statX << endl; + Double_t xPos = -0.5 * statX; + cout << "xPos1: " << xPos << endl; + Double_t yPos = 0.; + Double_t zPos = 0.; + + Double_t maxdz = 0.; + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) // find maximum dz in this unit + { + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + if (maxdz < ladderShape->GetDZ()) + maxdz = ladderShape->GetDZ(); + } + } + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) + { + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + xPos += ladderShape->GetDX(); + cout << "xPos2: " << xPos << endl; + yPos = 0.; // vertically centred + TGeoRotation* rot = new TGeoRotation(); + + if (gkConstructFrames) + subtractedVal = ladderShape->GetDX() + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2; + else + subtractedVal = 0.; + + zPos = 0.5 * gkLadderGapZ + (2*maxdz-ladderShape->GetDZ()-subtractedVal/2.); // z-aligned ladders + +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " dx: " << ladderShape->GetDX() + << " dy: " << ladderShape->GetDY() + << " dz: " << ladderShape->GetDZ() + << " max dz: " << maxdz << endl; + +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " fra: " << gkFrameThickness/2. + << " sub: " << subtractedVal + << " zpo: " << zPos << endl << endl; + +// v19k + if (ladderTypes[iLadder]/1000 == 1) // flip some of the ladders to reproduce the CAD layout + rot->RotateY(180.); + else + zPos = -zPos; + + if (!isFirstPartOfHalfUnit) + zPos += 10.5; // v19d +// zPos += 10.0; // initial version + + TGeoCombiTrans* trans = new TGeoCombiTrans(xPos, yPos, zPos, rot); +// start +// cout << "DEEE** iLadder " << iLadder << " " << nLadders/2 << " " << nLadders << endl; + + if (iSide == 0) + { + if (iLadder < nLadders/2) // right side - only half unit -x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + else + { + if (iLadder >= nLadders/2) // left side - only half unit +x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + unit->GetShape()->ComputeBBox(); +// stop + xPos += ladderShape->GetDX() - gkLadderOverlapX; + cout << "xPos3: " << xPos << endl; + } + else + xPos += gkSensorSizeX - gkLadderOverlapX; + } + + return unit; + } +/** ======================================================================= **/ + + +/** =========================================================================== + ** Import and add the passive materials to the STS volume + **/ +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile) +{ + TString passiveName = TString("sts_passive_") + geoTag; + TString basePath = gSystem->Getenv("VMCWORKDIR"); + TString relPath = "/geometry/sts/passive/" + passiveName + ".gdml"; + TString passiveFileName = basePath + relPath; + infoFile << std::endl << std::endl; + infoFile << "Importing STS passive materials from GDML file '" << relPath << "'." << std::endl; + + TGDMLParse parser; + TGeoVolume* gdmlVolume = parser.GDMLReadFile(passiveFileName); + PostProcessGdml(gdmlVolume); + gdmlVolume->SetName(passiveName); + + TGeoTranslation* passiveTrans = new TGeoTranslation(0., 0., 4.68 - 2.); + infoFile << "Passive assembly is translated for Z=2.68 cm downstream with respect to parent volume" << std::endl << std::endl; + + gdmlVolume->GetShape()->ComputeBBox(); + CheckVolume(gdmlVolume, infoFile); + + infoFile << std::endl; + for (Int_t iNode = 0; iNode < gdmlVolume->GetNdaughters(); iNode++) { + CheckVolume(gdmlVolume->GetNode(iNode)->GetVolume(), infoFile, kFALSE); + } + + stsVolume->AddNode(gdmlVolume, stsVolume->GetNdaughters(), passiveTrans, ""); +} + +/** =========================================================================== + ** Assign visual properties to the imported gdml volumes + **/ +void PostProcessGdml(TGeoVolume* gdmlVolume) +{ + const UInt_t kPOBColor = kRed-6; + const UInt_t kPOBTransparency = 0;// 5; + + const UInt_t kFEBColor = kOrange-6; + const UInt_t kFEBTransparency = 0;// 5; + + const UInt_t kUnitColor = kCyan-10; + const UInt_t kUnitTransparency = 0;// 5; + + const UInt_t kCfColor = kGray+3; + const UInt_t kCfTransparency = 0;// 10; + + // name <Color, Transparency> + std::map<std::string, std::tuple<UInt_t,UInt_t> > props { + { "passive_POB", std::tuple<UInt_t,UInt_t> {kPOBColor, kPOBTransparency} }, + { "passive_FEB", std::tuple<UInt_t,UInt_t> {kFEBColor, kFEBTransparency} }, + { "passive_unit", std::tuple<UInt_t,UInt_t> {kUnitColor, kUnitTransparency} }, + { "passive_Box_Wall", std::tuple<UInt_t,UInt_t> {kCfColor, kCfTransparency} }, + { "passive_Box_Wall_Front_CF2", std::tuple<UInt_t,UInt_t> {kCfColor-3, kCfTransparency} }, + }; + + // Match volume name and apply visual properties + const TObjArray* volumes = gGeoManager->GetListOfVolumes(); + for (auto& entry : props) { + TIter next(volumes); + TGeoVolume *vol = nullptr; + while ((vol=(TGeoVolume*)next())) { + if (TString(vol->GetName()).Contains(entry.first.c_str())) { + vol->SetLineColor(std::get<0>(entry.second)); + vol->SetTransparency(std::get<1>(entry.second)); + } + } + } +} + +/** =========================================================================== + ** Volume information for debugging + **/ +void CheckVolume(TGeoVolume* volume) { + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + cout << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) cout << ", assembly"; + else { + if ( volume->GetMedium() ) + cout << ", medium " << volume->GetMedium()->GetName(); + else cout << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + cout << endl; + if ( volume->GetNdaughters() ) { + cout << "Daughters: " << endl; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) { + TGeoNode* node = volume->GetNode(iNode); + TGeoBBox* shape = (TGeoBBox*) node->GetVolume()->GetShape(); + cout << setw(15) << node->GetName() << ", size " + << fixed << setprecision(3) + << setw(6) << 2. * shape->GetDX() << " x " + << setw(6) << 2. * shape->GetDY() << " x " + << setw(6) << 2. * shape->GetDZ() << ", position ( "; + TGeoMatrix* matrix = node->GetMatrix(); + const Double_t* pos = matrix->GetTranslation(); + cout << setfill(' '); + cout << fixed << setw(8) << pos[0] << ", " + << setw(8) << pos[1] << ", " + << setw(8) << pos[2] << " )" << endl; + } + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Volume information for output to file + **/ +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren) { + if ( ! file ) return; + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + file << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) file << ", assembly"; + else { + if ( volume->GetMedium() ) + file << ", medium " << volume->GetMedium()->GetName(); + else file << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + file << endl; + if ( volume->GetNdaughters() && listChildren) { + file << "Contains: "; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) + file << volume->GetNode(iNode)->GetVolume()->GetName() << " "; + file << endl; + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Calculate beam pipe outer radius for a given z + **/ +Double_t BeamPipeRadius(Double_t z) { + if ( z < gkPipeZ2 ) return gkPipeR1; + Double_t slope = (gkPipeR3 - gkPipeR2 ) / (gkPipeZ3 - gkPipeZ2); + return gkPipeR2 + slope * (z - gkPipeZ2); +} +/** ======================================================================= **/ + + + +/** ======================================================================= **/ +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + TGeoBBox* frameVertPillarShp; + + Double_t t = gkFrameThickness/2.; + + // --- Main vertical pillars +// TGeoBBox* frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, gkFrameStep/2., t); // square crossection, along y +// TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); +// frameVertPillarVol->SetLineColor(kGreen); +// frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoTranslation(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2.)); +// frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoTranslation(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkCylindricalFrames) + // TGeoBBox* frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", 0, t, gkFrameStep/2.); // circle crossection, along z + frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", gkCylinderDiaInner/2., gkCylinderDiaOuter/2., gkFrameStep/2.); // circle crossection, along z + else + frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, t, gkFrameStep/2.); // square crossection, along z + TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); + frameVertPillarVol->SetLineColor(kGreen); + + TGeoRotation* xRot90 = new TGeoRotation; + xRot90->RotateX(90.); + frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoCombiTrans(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoCombiTrans(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + + // TGeoRotation* vertRot = new TGeoRotation(name + "_vertpillar_rot_1", 90., 45., -90.); + TGeoRotation* vertRot = new TGeoRotation; + vertRot->RotateX(90.); + vertRot->RotateY(45.); + frameBoxVol->AddNode(frameVertPillarVol, 3, new TGeoCombiTrans(name + "_vertpillar_pos_3", 0., 0., (x-sqrt(2.)*t)/2., vertRot)); + + // --- Small horizontal pillar + // TGeoBBox* frameHorPillarShp = new TGeoBBox(name + "_horpillar_shape", x-2.*t, gkThinFrameThickness/2., gkThinFrameThickness/2.); + // TGeoVolume* frameHorPillarVol = new TGeoVolume(name + "_horpillar", frameHorPillarShp, framesMaterial); + // frameHorPillarVol->SetLineColor(kCyan); + // frameBoxVol->AddNode(frameHorPillarVol, 1, new TGeoTranslation(name + "_horpillar_pos_1", 0., -gkFrameStep/2.+gkThinFrameThickness/2., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkConstructSmallFrames) { + + // --- Small sloping pillars + TGeoPara* frameSlopePillarShp = new TGeoPara(name + "_slopepillar_shape", + (x-2.*t)/TMath::Cos(31.4/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., 31.4, 0., 90.); + TGeoVolume* frameSlopePillarVol = new TGeoVolume(name + "_slopepillar", frameSlopePillarShp, framesMaterial); + frameSlopePillarVol->SetLineColor(kCyan); + TGeoRotation* slopeRot = new TGeoRotation(name + "_slopepillar_rot_1", 0., 0., 31.4); + TGeoRotation* slopeRot2 = new TGeoRotation(name + "_slopepillar_rot_2", 0., 0., -31.4); + TGeoCombiTrans* slopeTrRot = new TGeoCombiTrans(name + "_slopepillar_posrot_1", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot); + TGeoCombiTrans* slopeTrRot2 = new TGeoCombiTrans(name + "_slopepillar_posrot_2", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot2); + + frameBoxVol->AddNode(frameSlopePillarVol, 1, slopeTrRot); + frameBoxVol->AddNodeOverlap(frameSlopePillarVol, 2, slopeTrRot2); + + + Double_t angl = 23.; + // --- Small sub pillar + TGeoPara* frameSubPillarShp = new TGeoPara(name + "_subpillar_shape", + (sqrt(2)*(x/2.-t)-t/2.)/TMath::Cos(angl/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., angl, 0., 90.); + TGeoVolume* frameSubPillarVol = new TGeoVolume(name + "_subpillar", frameSubPillarShp, framesMaterial); + frameSubPillarVol->SetLineColor(kMagenta); + + Double_t posZ = t * (1. - 3. / ( 2.*sqrt(2.) )); + + // one side of X direction + TGeoRotation* subRot1 = new TGeoRotation(name + "_subpillar_rot_1", 90., 45., -90.+angl); + TGeoCombiTrans* subTrRot1 = new TGeoCombiTrans(name + "_subpillar_posrot_1", -(-x/2.+t-t/(2.*sqrt(2.))), 1., posZ, subRot1); + + TGeoRotation* subRot2 = new TGeoRotation(name + "_subpillar_rot_2", 90., -90.-45., -90.+angl); + TGeoCombiTrans* subTrRot2 = new TGeoCombiTrans(name + "_subpillar_posrot_2", -(-x/2.+t-t/(2.*sqrt(2.))), -1., posZ, subRot2); + + // other side of X direction + TGeoRotation* subRot3 = new TGeoRotation(name + "_subpillar_rot_3", 90., 90.+45., -90.+angl); + TGeoCombiTrans* subTrRot3 = new TGeoCombiTrans(name + "_subpillar_posrot_3", -x/2.+t-t/(2.*sqrt(2.)), 1., posZ, subRot3); + + TGeoRotation* subRot4 = new TGeoRotation(name + "_subpillar_rot_4", 90., -45., -90.+angl); + TGeoCombiTrans* subTrRot4 = new TGeoCombiTrans(name + "_subpillar_posrot_4", -x/2.+t-t/(2.*sqrt(2.)), -1., posZ, subRot4); + + frameBoxVol->AddNode(frameSubPillarVol, 1, subTrRot1); + frameBoxVol->AddNode(frameSubPillarVol, 2, subTrRot2); + frameBoxVol->AddNode(frameSubPillarVol, 3, subTrRot3); + frameBoxVol->AddNode(frameSubPillarVol, 4, subTrRot4); + // frameBoxVol->GetShape()->ComputeBBox(); + } + + return frameBoxVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructSmallCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 6., 7.6, 6., 6.04, 0., 180.); +// TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + Double_t radius = 3.0; + Double_t thickness = 0.04; // 0.4 mm +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 3., 3.2, 3., 3.2, 0., 180.); + TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, radius, radius+thickness, radius, radius+thickness, 0., 180.); + TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + TGeoCombiTrans* M = new TGeoCombiTrans ("M"); + M->RotateX (45.); + M->SetDy (-5.575); + M->SetDz (6.935); + M->RegisterYourself(); + + TGeoShape* coneShp = new TGeoCompositeShape ("Cone_shp", "A-B:M"); + TGeoVolume* coneVol = new TGeoVolume ("Cone", coneShp, framesMaterial); + coneVol->SetLineColor(kGreen); +// coneVol->RegisterYourself(); + +// // --- Inner cone +// Double_t thickness = 0.02; +// Double_t thickness2 = 0.022; +// // TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); +// TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 3.+thickness, 4.6-thickness2, 2.99+thickness, 3.05-thickness2, 0., 180.); +// +// TGeoCombiTrans* M2 = new TGeoCombiTrans ("M2"); +// M2->RotateX (45.); +// M2->SetDy (-5.575+thickness*sqrt(2.)); +// M2->SetDz (6.935); +// M2->RegisterYourself(); +// +// TGeoShape* coneShp2 = new TGeoCompositeShape ("Cone2_shp", "A2-B:M2"); +// TGeoVolume* coneVol2 = new TGeoVolume ("Cone2", coneShp2, gStsMedium); +// coneVol2->SetLineColor(kGreen); +//// coneVol2->RegisterYourself(); +// +// coneVol->AddNode(coneVol2, 1); + + return coneVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructBigCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone + TGeoConeSeg* bA = new TGeoConeSeg ("bA", coneDz, 6., 7.6, 6., 6.04, 0., 180.); + TGeoBBox* bB = new TGeoBBox ("bB", 8., 6., 10.); + + TGeoCombiTrans* bM = new TGeoCombiTrans ("bM"); + bM->RotateX (45.); + bM->SetDy (-5.575); + bM->SetDz (6.935); + bM->RegisterYourself(); + + TGeoShape* coneBigShp = new TGeoCompositeShape ("ConeBig_shp", "bA-bB:bM"); + TGeoVolume* coneBigVol = new TGeoVolume ("ConeBig", coneBigShp, framesMaterial); + coneBigVol->SetLineColor(kGreen); +// coneBigVol->RegisterYourself(); + + // --- Inner cone + Double_t thickness = 0.02; + Double_t thickness2 = 0.022; + TGeoConeSeg* bA2 = new TGeoConeSeg ("bA2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); + + TGeoCombiTrans* bM2 = new TGeoCombiTrans ("bM2"); + bM2->RotateX (45.); + bM2->SetDy (-5.575+thickness*sqrt(2.)); + bM2->SetDz (6.935); + bM2->RegisterYourself(); + + TGeoShape* coneBigShp2 = new TGeoCompositeShape ("ConeBig2_shp", "bA2-bB:bM2"); + TGeoVolume* coneBigVol2 = new TGeoVolume ("ConeBig2", coneBigShp2, gStsMedium); + coneBigVol2->SetLineColor(kGreen); +// coneBigVol2->RegisterYourself(); + + coneBigVol->AddNode(coneBigVol2, 1); + + return coneBigVol; +} + +/** ======================================================================= **/ diff --git a/macro/sts/geometry/create_stsgeo_v19v.C b/macro/sts/geometry/create_stsgeo_v19v.C new file mode 100644 index 0000000000000000000000000000000000000000..f150d71b708442dc74afbb4a9da0d7cb542ddefb --- /dev/null +++ b/macro/sts/geometry/create_stsgeo_v19v.C @@ -0,0 +1,2407 @@ +/****************************************************************************** + ** Creation of STS geometry in ROOT format (TGeo). + ** + ** @file create_stsgeo_v19v.C + ** @author Volker Friese <v.friese@gsi.de> + ** @since 15 June 2012 + ** @date 09.05.2014 + ** @author Tomas Balog <T.Balog@gsi.de> + ** + ** v19v: based on v19t: rotate all sensors by 180 degrees around y + ** v19u: rotate the opposite sensors as compared to v19t + ** v19t: application of pp-nn sensor orientation to v19r (as tested in v19s) + ** v19s: introducing pp-nn sensor orientation - only for visualisation using blue and red surfaces + ** v19r: bugfix of v19q - align all halfladders + ** v19q: based on v19l - align ladders to virtual plane in station center, closing the gaps in z + ** v19p: based on v19k - parameters : delta Z prime = 0.70 cm - delta Z pitch = 0.20 cm + ** v19o: based on v19k - parameters : delta Z prime = 0.30 cm - delta Z pitch = 0.20 cm + ** v19n: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.20 cm (bug fix of v19m) + ** v19m: based on v19k - parameters : delta Z prime = 0.55 cm - delta Z pitch = 0.20 cm (bug) + ** v19l: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.15 cm + ** v19k: ladders on upstream side of units get upper half ladders installed first, + ** ladders on downstream side of units get lower half ladders installed first, + ** this saves 1.5 mm space in z per station, 12 mm in total (LadderType went from 3 to 4 digits) + ** parameters : delta Z prime = 1.00 cm - delta Z pitch = 0.15 cm + ** v19j: use overlap and distance parameters from CAD model + ** v19h: put STS stations from v19d at z-positions = 260; 365; 470; 575; 680; 785; 890; 995 mm + ** v19g: place a box with services around v19e + ** v19f: place a box with services around v19d + ** v19e: increase spacing between stations by +10 mm from 100 mm + ** v19d: increase spacing between stations by + 5 mm from 100 mm + ** v19c: drop station 8 and increase spacing between remaining 7 stations from 10 cm to 12 c + ** v19b: introduce FEB orientation in ladder numbering (LadderType went from 2 to 3 digits) + ** v19a: import passive materials from gdml file + ** extend CF ladder structures and cables towards FEE plane + ** change CF ladder frame shape + ** v18d: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu (based on v18b) + ** v18c: fixed cut-out windows in cooling plates, improve the box shape/materials + ** v18b: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu + ** v18a: adds 9 cooling/holding plates and a box around the setup + ** v16g: v16g is the new standard geometry from November 2017 + ** v16g: switch from stations to units - left / right ("Unit01L", "Unit01R") + ** v16f: switch from stations to units + ** - split in upstream / downstream and left / right parts + ** - named Unit0xUR, Unit0xUL, Unit0xDR, Unit0xDL + ** v16e: switch from stations to units - upstream / downstream ("Unit01U", "Unit01D") + ** v16d: skip keeping volumes of sts and stations + ** v16c: like v16b, but senors of ladders beampipe next to beampipe + ** shifted closer to the pipe, like in the CAD model + ** v16b: like v16a, but yellow sensors removed + ** v16a: derived from v15c (no cones), but with sensor types renamed: + ** 2 -> 1, 3 -> 2, 4 -> 3, 5 -> 4, 1 -> 5 + ** + ** v15c: as v15b without cones + ** v15b: introduce modified carbon ladders from v13z + ** v15a: with flipped ladder orientation for stations 0,2,4,6 to match CAD design + ** + ** TODO: + ** + ** DONE: + ** v15b - use carbon macaroni as ladder support + ** v15b - introduce a small gap between lowest sensor and carbon ladder + ** v15b - build small cones for the first 2 stations + ** v15b - within a station the ladders of adjacent units should not touch eachother - set gkLadderGapZ to 10 mm + ** v15b - for all ladders set an even number of ladder elements + ** v15b - z offset of cones to ladders should not be 0.3 by default, but 0.26 + ** v15b - within a station the ladders should be aligned in z, defined either by the unit or the ladder with most sensors + ** v15b - get rid of cone overlap in stations 7 and 8 - done by adapting rHole size + ** + ** The geometry hierarachy is: + ** + ** 1. Sensors (see function CreateSensors) + ** The sensors are the active volumes and the lowest geometry level. + ** They are built as TGeoVolumes, shape box, material silicon. + ** x size is determined by strip pitch 58 mu and 1024 strips + ** plus guard ring of 1.3 mm at each border -> 6.1992 cm. + ** Sensor type 1 is half of that (3.0792 cm). + ** y size is determined by strip length (2.2 / 4.2 / 6.3 cm) plus + ** guard ring of 1.3 mm at top and bottom -> 2.46 / 4.46 / 6.46 cm. + ** z size is a parameter, to be set by gkSensorThickness. + ** + ** 2. Sectors (see function CreateSectors) + ** Sectors consist of several chained sensors. These are arranged + ** vertically on top of each other with a gap to be set by + ** gkChainGapY. Sectors are constructed as TGeoVolumeAssembly. + ** The sectors are auxiliary volumes used for proper placement + ** of the sensor(s) in the module. They do not show up in the + ** final geometry. + ** + ** 3. Modules (see function ConstructModule) + ** A module is a readout unit, consisting of one sensor or + ** a chain of sensors (see sector) and a cable. + ** The cable extends from the top of the sector vertically to the + ** top of the halfladder the module is placed in. The cable and module + ** volume thus depend on the vertical position of the sector in + ** the halfladder. The cables consist of silicon with a thickness to be + ** set by gkCableThickness. + ** Modules are constructed as TGeoVolume, shape box, medium gStsMedium. + ** The module construction can be switched off (gkConstructCables) + ** to reproduce older geometries. + ** + ** 4. Halfladders (see function ConstructHalfLadder) + ** A halfladder is a vertical assembly of several modules. The modules + ** are placed vertically such that their sectors overlap by + ** gkSectorOverlapY. They are displaced in z direction to allow for the + ** overlap in y by gkSectorGapZ. + ** The horizontal placement of modules in the halfladder can be choosen + ** to left aligned or right aligned, which only matters if sensors of + ** different x size are involved. + ** Halfladders are constructed as TGeoVolumeAssembly. + ** + ** 5. Ladders (see function CreateLadders and ConstructLadder) + ** A ladder is a vertical assembly of two halfladders, and is such the + ** vertical building block of a station. The second (bottom) half ladder + ** is rotated upside down. The vertical arrangement is such that the + ** inner sectors of the two halfladders have the overlap gkSectorOverlapY + ** (function CreateLadder) or that there is a vertical gap for the beam + ** hole (function CreateLadderWithGap). + ** Ladders are constructed as TGeoVolumeAssembly. + ** + ** 6. Stations (see function ConstructStation) + ** A station represents one layer of the STS geometry: one measurement + ** at (approximately) a given z position. It consist of several ladders + ** arranged horizontally to cover the acceptance. + ** The ladders are arranged such that there is a horizontal overlap + ** between neighbouring ladders (gkLadderOverLapX) and a vertical gap + ** to allow for this overlap (gkLadderGapZ). Each second ladder is + ** rotated around its y axis to face away from or into the beam. + ** Stations are constructed as TGeoVolumes, shape box minus tube (for + ** the beam hole), material gStsMedium. + ** + ** 7. STS + ** The STS is a volume hosting the entire detectors system. It consists + ** of several stations located at different z positions. + ** The STS is constructed as TGeoVolume, shape box minus cone (for the + ** beam pipe), material gStsMedium. The size of the box is computed to + ** enclose all stations. + *****************************************************************************/ + + +// Remark: With the proper steering variables, this should exactly reproduce +// the geometry version v11b of A. Kotynia's described in the ASCII format. +// The only exception is a minimal difference in the z position of the +// sectors/sensors. This is because of ladder types 2 and 4 containing the half +// sensors around the beam hole (stations 1,2 and 3). In v11b, the two ladders +// covering the beam hole cannot be transformed into each other by rotations, +// but only by a reflection. This means they are constructionally different. +// To avoid introducing another two ladder types, the difference in z position +// was accepted. + + +// Differences to v12: +// gkChainGap reduced from 1 mm to 0 +// gkCableThickness increased from 100 mum to 200 mum (2 cables per module) +// gkSectorOverlapY reduced from 3 mm to 2.4 mm +// New sensor types 05 and 06 +// New sector types 07 and 08 +// Re-definiton of ladders (17 types instead of 8) +// Re-definiton of station from new ladders + + +#include <iomanip> +#include <iostream> +#include "TGeoManager.h" + +#include "TGeoTube.h" +#include "TGeoPara.h" +#include "TGeoCone.h" +#include "TGeoTrd2.h" +#include "TGeoCompositeShape.h" +#include "TGeoXtru.h" +#include "TGeoPhysicalNode.h" + +// forward declarations +Int_t CreateSensors(); +Int_t CreateSectors(); +Int_t CreateLadders(); +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength); +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY, + Int_t start); +TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ, + Double_t pitchZ, + Int_t nSectors); +TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation); +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile); +void PostProcessGdml(TGeoVolume* gdmlTop); +void CheckVolume(TGeoVolume* volume); +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren = kTRUE); +Double_t BeamPipeRadius(Double_t z); +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x); +TGeoVolume* ConstructSmallCone(Double_t coneDz); +TGeoVolume* ConstructBigCone(Double_t coneDz); + +// ------------- Version highlight ----------------------------------- + +const std::string gVersionHighlight = R"( +Summary: + This version adds passive materials imported from GDML model to the STS geometry: + * Taken from and largely correspond to mechanical CAD drawings of the detector + * Thermal insulation box: + - made out of carbon sandwitch panel (2mm carbon fiber sheet + layer of carbon foam + 2mm carbon fiber sheet) + - front window of complex shape with interface to MVD / target chamber + - back window with large aperture (2000 x 1200 mm) square cut into carbon foam + * Structural units: + - made of 2 complex shape aluminum C-Frames, 15mm thick + - placed at 25, 35, ... ,105 cm absolute Z + - contain front-end and power distribution boxes with equivalent X_0 values + + Scripted geometry tweaks: + * Ladders and cables are extended towards the read-out planes having same lengths in respective rows + * Adjusted form and shape of carbon ladder structures from L-type to X-type + * Reduced verbosity of this file + + Sensor arrangement is the same as in version v16g + + !! Important for this version is the discrepancy from the mechanical CAD w.r.t. front wall. + The square window was replaced by a round one to avoid overlaps with present beam pipe designs, e.g. pipe_v16b_1e +)"; + +// ------------- Steering variables ----------------------------------- + +// ---> Horizontal width of sensors [cm] +const Double_t gkSensorSizeX = 6.2; // was 6.2092; // 6.2 - Oleg CAD 15/05/2020 + +// ---> Thickness of sensors [cm] +const Double_t gkSensorThickness = 0.03; + +// ---> Vertical gap between chained sensors [cm] +const Double_t gkChainGapY = 0.00; + +// ---> Thickness of cables [cm] +const Double_t gkCableThickness = 0.02; + +// ---> Horizontal overlap of neighbouring ladders [cm] +const Double_t gkLadderOverlapX = 0.25; // delta X - Oleg CAD 14/05/2020 + +// ---> Vertical overlap of neighbouring sectors in a ladder [cm] +const Double_t gkSectorOverlapY = 0.46; // delta Y - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring sectors in a ladder [cm] +const Double_t gkSectorGapZ = 0.12; // gap + thickness = pitch // delta Z pitch = 0.15 - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring ladders [cm] +const Double_t gkLadderGapZ = 0.50 - 0.15; // for asym // 0.5 for sym // delta Z prime + +// ---> Gap in z between lowest sector to carbon support structure [cm] +const Double_t gkSectorGapZFrame = 0.280 - 0.025; // Oleg CAD 05/05/2020 // there is a 2.8 mm gap between the bottom side of the sensor and the top ledge of the carbon ladder + +// ---> Switch to construct / not to construct readout cables +const Bool_t gkConstructCables = kTRUE; + +// ---> Switch to construct / not to construct frames +const Bool_t gkConstructCones = kFALSE; // kTRUE; // switch this false by default for v15c and v16x +const Bool_t gkConstructFrames = kTRUE; // kFALSE; // switch this true by default for v15c and v16x +const Bool_t gkConstructSmallFrames = kTRUE; // kFALSE; +const Bool_t gkCylindricalFrames = kTRUE; // kFALSE; + +// ---> Size of the frame +const Double_t gkFrameThickness = 0.2; +const Double_t gkThinFrameThickness = 0.05; +const Double_t gkFrameStep = 4.0; // size of frame cell along y direction + +const Double_t gkCylinderDiaInner = 0.07; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) +const Double_t gkCylinderDiaOuter = 0.15; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) + +// ---> Switch to import / not to import the Passive materials from GDML file +//const Bool_t gkImportPassive = kTRUE; +const Bool_t gkImportPassive = kFALSE; + +// ---------------------------------------------------------------------------- + + +// -------------- Parameters of beam pipe in the STS region -------------- +// ---> Needed to compute stations and STS such as to avoid overlaps +const Double_t gkPipeZ1 = 22.0; +const Double_t gkPipeR1 = 1.8; +const Double_t gkPipeZ2 = 50.0; +const Double_t gkPipeR2 = 1.8; +const Double_t gkPipeZ3 = 125.0; +const Double_t gkPipeR3 = 5.5; + +//DE const Double_t gkPipeZ1 = 27.0; +//DE const Double_t gkPipeR1 = 1.05; +//DE const Double_t gkPipeZ2 = 160.0; +//DE const Double_t gkPipeR2 = 3.25; +// ---------------------------------------------------------------------------- + +//TString unitName[16] = // names of units for v16e +// { "Unit00D", +// "Unit01U", "Unit01D", +// "Unit02U", "Unit02D", +// "Unit03U", "Unit03D", +// "Unit04U", "Unit04D", +// "Unit05U", "Unit05D", +// "Unit06U", "Unit06D", +// "Unit07U", "Unit07D", +// "Unit08U" }; + +//TString unitName[32] = // names of units for v16f +// { "Unit00DR", "Unit00DL", +// "Unit01UR", "Unit01UL", "Unit01DR", "Unit01DL", +// "Unit02UR", "Unit02UL", "Unit02DR", "Unit02DL", +// "Unit03UR", "Unit03UL", "Unit03DR", "Unit03DL", +// "Unit04UR", "Unit04UL", "Unit04DR", "Unit04DL", +// "Unit05UR", "Unit05UL", "Unit05DR", "Unit05DL", +// "Unit06UR", "Unit06UL", "Unit06DR", "Unit06DL", +// "Unit07UR", "Unit07UL", "Unit07DR", "Unit07DL", +// "Unit08UR", "Unit08UL" }; + +TString unitName[32] = // names of units for v16g - while merging D and U parts + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", "Unit01R", "Unit01L", + "Unit02R", "Unit02L", "Unit02R", "Unit02L", + "Unit03R", "Unit03L", "Unit03R", "Unit03L", + "Unit04R", "Unit04L", "Unit04R", "Unit04L", + "Unit05R", "Unit05L", "Unit05R", "Unit05L", + "Unit06R", "Unit06L", "Unit06R", "Unit06L", + "Unit07R", "Unit07L", "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +TString unitName18[18] = // names of units for v16g + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", + "Unit02R", "Unit02L", + "Unit03R", "Unit03L", + "Unit04R", "Unit04L", + "Unit05R", "Unit05L", + "Unit06R", "Unit06L", + "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +// ------------- Other global variables ----------------------------------- +// ---> STS medium (for every volume except silicon) +TGeoMedium* gStsMedium = NULL; // will be set later +// ---> TGeoManager (too lazy to write out 'Manager' all the time +TGeoManager* gGeoMan = NULL; // will be set later +// ---------------------------------------------------------------------------- + + + + +// ============================================================================ +// ====== Main function ===== +// ============================================================================ + +void create_stsgeo_v19v(const char* geoTag="v19v") +{ + + // ------- Geometry file name (output) ---------------------------------- + TString geoFileName = "sts_"; + geoFileName = geoFileName + geoTag + ".geo.root"; + // -------------------------------------------------------------------------- + + + // ------- Open info file ----------------------------------------------- + TString infoFileName = geoFileName; + infoFileName.ReplaceAll("root", "info"); + fstream infoFile; + infoFile.open(infoFileName.Data(), fstream::out); + infoFile << "STS geometry created with create_stsgeo_v19v.C" << endl; + infoFile << gVersionHighlight << endl; + infoFile << "Global variables: " << endl; + infoFile << "Sensor thickness = " << gkSensorThickness << " cm" << endl; + infoFile << "Vertical gap in sensor chain = " + << gkChainGapY << " cm" << endl; + infoFile << "Vertical overlap of sensors = " + << gkSectorOverlapY << " cm" << endl; + infoFile << "Gap in z between neighbour sensors = " + << gkSectorGapZ << " cm" << endl; + infoFile << "Horizontal overlap of sensors = " + << gkLadderOverlapX << " cm" << endl; + infoFile << "Gap in z between neighbour ladders = " + << gkLadderGapZ << " cm" << endl; + if ( gkConstructCables ) + infoFile << "Cable thickness = " << gkCableThickness << " cm" << endl; + else + infoFile << "No cables" << endl; + infoFile << endl; + infoFile << "Beam pipe: R1 = " << gkPipeR1 << " cm at z = " + << gkPipeZ1 << " cm" << endl; + infoFile << "Beam pipe: R2 = " << gkPipeR2 << " cm at z = " + << gkPipeZ2 << " cm" << endl; + infoFile << "Beam pipe: R3 = " << gkPipeR3 << " cm at z = " + << gkPipeZ3 << " cm" << endl; + // -------------------------------------------------------------------------- + + + // ------- Load media from media file ----------------------------------- + FairGeoLoader* geoLoad = new FairGeoLoader("TGeo","FairGeoLoader"); + FairGeoInterface* geoFace = geoLoad->getGeoInterface(); + TString geoPath = gSystem->Getenv("VMCWORKDIR"); + TString medFile = geoPath + "/geometry/media.geo"; + geoFace->setMediaFile(medFile); + geoFace->readMedia(); + gGeoMan = gGeoManager; + // -------------------------------------------------------------------------- + + + // ----------------- Get and create the required media ----------------- + FairGeoMedia* geoMedia = geoFace->getMedia(); + FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder(); + + // ---> air + FairGeoMedium* mAir = geoMedia->getMedium("air"); + if ( ! mAir ) Fatal("Main", "FairMedium air not found"); + geoBuild->createMedium(mAir); + TGeoMedium* air = gGeoMan->GetMedium("air"); + if ( ! air ) Fatal("Main", "Medium air not found"); + + // ---> silicon + FairGeoMedium* mSilicon = geoMedia->getMedium("silicon"); + if ( ! mSilicon ) Fatal("Main", "FairMedium silicon not found"); + geoBuild->createMedium(mSilicon); + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + if ( ! silicon ) Fatal("Main", "Medium silicon not found"); + + // ---> carbon + FairGeoMedium* mCarbon = geoMedia->getMedium("carbon"); + if ( ! mCarbon ) Fatal("Main", "FairMedium carbon not found"); + geoBuild->createMedium(mCarbon); + TGeoMedium* carbon = gGeoMan->GetMedium("carbon"); + if ( ! carbon ) Fatal("Main", "Medium carbon not found"); + + // ---> STSBoxCarbonFoam + FairGeoMedium* mSTSBoxCarbonFoam = geoMedia->getMedium("STSBoxCarbonFoam"); + if ( ! mSTSBoxCarbonFoam ) Fatal("Main", "FairMedium STSBoxCarbonFoam not found"); + geoBuild->createMedium(mSTSBoxCarbonFoam); + TGeoMedium* STSBoxCarbonFoam = gGeoMan->GetMedium("STSBoxCarbonFoam"); + if ( ! STSBoxCarbonFoam ) Fatal("Main", "Medium STSBoxCarbonFoam not found"); + + // ---> STSBoxCarbonFibre + FairGeoMedium* mSTSBoxCarbonFibre = geoMedia->getMedium("STSBoxCarbonFibre"); + if ( ! mSTSBoxCarbonFibre ) Fatal("Main", "FairMedium STSBoxCarbonFibre not found"); + geoBuild->createMedium(mSTSBoxCarbonFibre); + TGeoMedium* STSBoxCarbonFibre = gGeoMan->GetMedium("STSBoxCarbonFibre"); + if ( ! STSBoxCarbonFibre ) Fatal("Main", "Medium STSBoxCarbonFibre not found"); + + // ---> STScable + FairGeoMedium* mSTScable = geoMedia->getMedium("STScable"); + if ( ! mSTScable ) Fatal("Main", "FairMedium STScable not found"); + geoBuild->createMedium(mSTScable); + TGeoMedium* STScable = gGeoMan->GetMedium("STScable"); + if ( ! STScable ) Fatal("Main", "Medium STScable not found"); + + // ---> Aluminium + FairGeoMedium* mAluminium = geoMedia->getMedium("aluminium"); + if ( ! mAluminium ) Fatal("Main", "FairMedium aluminium not found"); + geoBuild->createMedium(mAluminium); + TGeoMedium* aluminium = gGeoMan->GetMedium("aluminium"); + if ( ! aluminium ) Fatal("Main", "Medium aluminium not found"); + + // --- + gStsMedium = air; + // -------------------------------------------------------------------------- + + + // -------------- Create geometry and top volume ------------------------- + gGeoMan = (TGeoManager*)gROOT->FindObject("FAIRGeom"); +// gGeoMan->SetName("STSgeom"); + TGeoVolume* top = new TGeoVolumeAssembly("top"); +// TGeoBBox* topbox= new TGeoBBox("", 120., 120., 120.); +// TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air")); + gGeoMan->SetTopVolume(top); + // -------------------------------------------------------------------------- + + + // -------------- Create media ------------------------------------------ + /* + cout << endl; + cout << "===> Creating media...."; + cout << CreateMedia(); + cout << " media created" << endl; + TList* media = gGeoMan->GetListOfMedia(); + for (Int_t iMedium = 0; iMedium < media->GetSize(); iMedium++ ) { + cout << "Medium " << iMedium << ": " + << ((TGeoMedium*) media->At(iMedium))->GetName() << endl; + } + gStsMedium = gGeoMan->GetMedium("air"); + if ( ! gStsMedium ) Fatal("Main", "medium sts_air not found"); + */ + // -------------------------------------------------------------------------- + + + // --------------- Create sensors --------------------------------------- + cout << endl << endl; + cout << "===> Creating sensors...." << endl << endl; + infoFile << endl << "Sensors: " << endl; + Int_t nSensors = CreateSensors(); + for (Int_t iSensor = 1; iSensor <= nSensors; iSensor++) { + TString name = Form("Sensor%02d",iSensor); + TGeoVolume* sensor = gGeoMan->GetVolume(name); + + // add color to sensors + if (iSensor == 1) + sensor->SetLineColor(kRed); + if (iSensor == 2) + sensor->SetLineColor(kGreen); + if (iSensor == 3) + sensor->SetLineColor(kBlue); + if (iSensor == 4) + sensor->SetLineColor(kAzure); + if (iSensor == 5) + sensor->SetLineColor(kYellow); + if (iSensor == 6) + sensor->SetLineColor(kYellow); + if (iSensor == 7) + sensor->SetLineColor(kYellow); + + CheckVolume(sensor); + CheckVolume(sensor, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create sectors -------------------------------------- + cout << endl << endl; + cout << "===> Creating sectors...." << endl; + // infoFile << endl << "Sectors: " << endl; + Int_t nSectors = CreateSectors(); + for (Int_t iSector = 1; iSector <= nSectors; iSector++) { + // cout << endl; + TString name = Form("Sector%02d", iSector); + TGeoVolume* sector = gGeoMan->GetVolume(name); + CheckVolume(sector); + // CheckVolume(sector, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create ladders -------------------------------------- + cout << endl << endl; + cout << "===> Creating ladders...." << endl; + infoFile << endl << "Ladders:" << endl; + + TString name = ""; + TGeoVolume* ladder; + + + Int_t nLadders = CreateLadders(); + + for (Int_t iLadder = 1; iLadder <= nLadders; iLadder++) { + cout << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType0%02d", iLadder); // v19b + name = Form("LadderType00%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF1: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType1%02d", iLadder); // v19b + name = Form("LadderType01%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF2: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType10%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF3: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType11%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF4: ladder name: " << name << endl << endl; + } + // -------------------------------------------------------------------------- + + + // ---------------- Create cones ---------------------------------------- + Double_t coneDz = 1.64; + TGeoVolume* coneSmallVolum = ConstructSmallCone(coneDz); + if (!coneSmallVolum) Fatal("ConstructSmallCone", "Volume Cone not found"); + TGeoVolume* coneBigVolum = ConstructBigCone(coneDz); + if (!coneBigVolum) Fatal("ConstructBigCone", "Volume Cone not found"); + // -------------------------------------------------------------------------- + + + // ---------------- Create stations ------------------------------------- + cout << endl << endl; + cout << "===> Creating stations...." << endl; + infoFile << endl << "Stations: " << endl; + Int_t angle = 0; + nLadders = 0; + Int_t ladderTypes[16]; // there are max 16 ladders in one layer + TGeoTranslation* statTrans = NULL; + + TGeoVolume *myunit[32]; // units + +// Int_t statPos[8] = { 30, 40, 50, 60, 70, 80, 90, 100 }; // z positions of stations +// Int_t statPos[16] = { 28, 32, 38, 42, 48, 52, 58, 62, +// 68, 72, 78, 82, 88, 92, 98,102 }; // z positions of units +// Int_t statPos[16] = { 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units +// Int_t statPos18[18] = { 30, 30, // expanded for placement of Unit00 +// 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units + // v19h + Double_t statPos[16] = { 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of units + Double_t statPos18[18] = { 26.0, 26.0, // expanded for placement of Unit00 + 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of unit + +// // v19d +// Double_t statPos[16] = { 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units +// Double_t statPos18[18] = { 30.0, 30.0, // expanded for placement of Unit00 +// 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units + +////Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.9 , 3.7 , 3.7 , 4.2 , 4.2 }; // size of cutouts in stations +// Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.43, 3.04, 3.35, 3.96, 4.2 }; // size of cutouts in stations, derived from gapXYZ[x][1]/2 + + Int_t cone_size[8] = { 0, 0, 0, 1, 1, 1, 1, 1 }; // size of cones: 0 = small, 1 = large + + Double_t cone_offset[2] = { 0.305, 0.285 }; + +// Int_t allLadderTypes[8][16]= +// { { -1, -1, -1, -1, 10, 109, 9, 101, 1, 109, 9, 110, -1, -1, -1, -1 }, // station 1 +// { -1, -1, 111, 10, 110, 9, 109, 2, 102, 9, 109, 10, 110, 11, -1, -1 }, // station 2 +// { -1, -1, 14, 113, 12, 112, 12, 103, 3, 112, 12, 112, 13, 114, -1, -1 }, // station 3 +// { -1, 15, 114, 13, 112, 12, 112, 4, 104, 12, 112, 12, 113, 14, 115, -1 }, // station 4 +// { -1, 119, 18, 117, 17, 116, 16, 105, 5, 116, 16, 117, 17, 118, 19, -1 }, // station 5 +// { -1, 19, 118, 17, 117, 16, 116, 6, 106, 16, 116, 17, 117, 18, 119, -1 }, // station 6 +// { 21, 119, 18, 120, 20, 120, 20, 107, 7, 120, 20, 120, 20, 118, 19, 121 }, // station 7 +// { 119, 17, 123, 22, 122, 22, 122, 8, 108, 22, 122, 22, 122, 23, 117, 19 } }; // station 8 + +//============================================================================================== + +// explanation: type xyzz +// where x = carbon ladder orientation +// where y = FEB box orientation +// where zz = sensor arrangement on ladder +// with FEB orientation - v19b + Int_t allUnitTypes[16][16]= + { { -1, -1, -1, -1, 10, 0, 9, 0, 101, 0, 109, 0, -1, -1, -1, -1 }, // unit00D Station01 00 + { -1, -1, -1, -1, 0, 1109, 0, 1101, 0, 1009, 0, 1010, -1, -1, -1, -1 }, // unit01U Station01 01 + + { -1, -1, 0, 10, 0, 9, 0, 2, 0, 109, 0, 110, 0, 111, -1, -1 }, // unit01D Station02 02 + { -1, -1, 1111, 0, 1110, 0, 1109, 0, 1002, 0, 1009, 0, 1010, 0, -1, -1 }, // unit02U Station02 03 + + { -1, -1, 14, 0, 12, 0, 12, 0, 103, 0, 112, 0, 113, 0, -1, -1 }, // unit02D Station03 04 + { -1, -1, 0, 1113, 0, 1112, 0, 1103, 0, 1012, 0, 1012, 0, 1014, -1, -1 }, // unit03U Station03 05 + + { -1, 15, 0, 13, 0, 12, 0, 4, 0, 112, 0, 112, 0, 114, 0, -1 }, // unit03D Station04 06 + { -1, 0, 1114, 0, 1112, 0, 1112, 0, 1004, 0, 1012, 0, 1013, 0, 1015, -1 }, // unit04U Station04 07 + + { -1, 0, 18, 0, 17, 0, 16, 0, 105, 0, 116, 0, 117, 0, 119, -1 }, // unit04D Station05 08 + { -1, 1119, 0, 1117, 0, 1116, 0, 1105, 0, 1016, 0, 1017, 0, 1018, 0, -1 }, // unit05U Station05 09 + + { -1, 19, 0, 17, 0, 16, 0, 6, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05D Station06 10 + { -1, 0, 1118, 0, 1117, 0, 1116, 0, 1006, 0, 1016, 0, 1017, 0, 1019, -1 }, // unit06U Station06 11 + + { 21, 0, 25, 0, 20, 0, 20, 0, 107, 0, 120, 0, 120, 0, 127, 0 }, // unit06D Station07 12 + { 0, 1127, 0, 1120, 0, 1120, 0, 1107, 0, 1020, 0, 1020, 0, 1025, 0, 1021 }, // unit07U Station07 13 + + { 0, 24, 0, 22, 0, 22, 0, 8, 0, 122, 0, 122, 0, 123, 0, 126 }, // unit07D Station08 14 + { 1126, 0, 1123, 0, 1122, 0, 1122, 0, 1008, 0, 1022, 0, 1022, 0, 1024, 0 } }; // unit08U Station08 15 + +//============================================================================================== + +// without FEB orientation - v19a +// v19a Int_t allUnitTypes[16][16]= +// v19a { { -1, -1, -1, -1, 10, 0, 9, 0, 1, 0, 9, 0, -1, -1, -1, -1 }, // unit00D Station01 00 +// v19a { -1, -1, -1, -1, 0, 109, 0, 101, 0, 109, 0, 110, -1, -1, -1, -1 }, // unit01U Station01 01 +// v19a { -1, -1, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, -1, -1 }, // unit01D Station02 02 +// v19a { -1, -1, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, -1, -1 }, // unit02U Station02 03 +// v19a { -1, -1, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, -1, -1 }, // unit02D Station03 04 +// v19a { -1, -1, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, -1, -1 }, // unit03U Station03 05 +// v19a { -1, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, -1 }, // unit03D Station04 06 +// v19a { -1, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, -1 }, // unit04U Station04 07 +// v19a { -1, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, -1 }, // unit04D Station05 08 +// v19a { -1, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05U Station05 09 +// v19a { -1, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, -1 }, // unit05D Station06 10 +// v19a { -1, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, -1 }, // unit06U Station06 11 +// v19a { 21, 0, 25, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 27, 0 }, // unit06D Station07 12 +// v19a { 0, 127, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 125, 0, 121 }, // unit07U Station07 13 +// v19a { 0, 24, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 26 }, // unit07D Station08 14 +// v19a { 126, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 124, 0 } }; // unit08U Station08 15 + + +// unitTypes[0] = { 0, 0, 0, 0, 10, 0, 9, 0, 1, 0, 9, 0, 0, 0, 0, 0 }; // unit 0D +// unitTypes[1] = { 0, 0, 0, 0, 0, 109, 0, 101, 0, 109, 0, 110, 0, 0, 0, 0 }; // unit 1U +// unitTypes[2] = { 0, 0, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, 0, 0 }; // unit 1D +// unitTypes[3] = { 0, 0, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, 0, 0 }; // unit 2U +// unitTypes[4] = { 0, 0, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, 0, 0 }; // unit 2D +// unitTypes[5] = { 0, 0, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, 0, 0 }; // unit 3U +// unitTypes[6] = { 0, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, 0 }; // unit 3D +// unitTypes[7] = { 0, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, 0 }; // unit 4U +// unitTypes[8] = { 0, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, 0 }; // unit 4D +// unitTypes[9] = { 0, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, 0 }; // unit 5U +// unitTypes[10] = { 0, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, 0 }; // unit 5D +// unitTypes[11] = { 0, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, 0 }; // unit 6U +// unitTypes[12] = { 21, 0, 18, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 19, 0 }; // unit 6D +// unitTypes[13] = { 0, 119, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 118, 0, 121 }; // unit 7U +// unitTypes[14] = { 0, 17, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 19 }; // unit 7D +// unitTypes[15] = { 119, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 117, 0 }; // unit 8U + + +// // generate unit +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) +// for (Int_t iLadder = 0; iLadder < 16; iLadder++) +// { +// allUnitTypes[iUnit][iLadder] = 0; +// if ((iUnit % 2 == 0) && (allLadderTypes[iUnit/2][iLadder] < 100)) // if carbon structure is oriented upstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// if ((iUnit % 2 == 1) && (allLadderTypes[iUnit/2][iLadder] >= 100)) // if carbon structure is oriented downstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// } + + + // dump unit + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << "DE unitTypes[" << iUnit << "] = { "; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + { + cout << allUnitTypes[iUnit][iLadder]; + if (iLadder < 15) + cout << ", "; + else + cout << " };"; + } + cout << endl; + } + + + // --- Units 01 - 16 + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << endl; + + nLadders = 0; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + if (allUnitTypes[iUnit][iLadder] >= 0) + { + ladderTypes[nLadders] = allUnitTypes[iUnit][iLadder]; + cout << "DE ladderTypes[" << nLadders << "] = " << allUnitTypes[iUnit][iLadder] << ";" << endl; + nLadders++; + } + myunit[iUnit*2+0] = ConstructUnit(0, iUnit*2+0, nLadders, ladderTypes, iUnit/2+1); + myunit[iUnit*2+1] = ConstructUnit(1, iUnit*2+1, nLadders, ladderTypes, iUnit/2+1); + +// if (gkConstructCones) { +// if (iUnit%2 == 0) +// angle = 90; +// else +// angle = -90; +// +// // upstream +// TGeoRotation* coneRot11 = new TGeoRotation; +// coneRot11->RotateZ(angle); +// coneRot11->RotateY(180); +// TGeoCombiTrans* conePosRot11 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-cone_offset[cone_size[iUnit]]-gkLadderGapZ/2., coneRot11); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 1, conePosRot11); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 1, conePosRot11); +// +// // downstream +// TGeoRotation* coneRot12 = new TGeoRotation; +// coneRot12->RotateZ(angle); +// TGeoCombiTrans* conePosRot12 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+cone_offset[cone_size[iUnit]]+gkLadderGapZ/2., coneRot12); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 2, conePosRot12); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 2, conePosRot12); +// +// myunit[iUnit]->GetShape()->ComputeBBox(); +// } + +// CheckVolume(myunit[iUnit]); +// CheckVolume(myunit[iUnit], infoFile); + if ((iUnit%2 == 0)||(iUnit == 15)) + { + CheckVolume(myunit[iUnit*2+0]); + CheckVolume(myunit[iUnit*2+0], infoFile); + CheckVolume(myunit[iUnit*2+1]); + CheckVolume(myunit[iUnit*2+1], infoFile); + } + infoFile << "Position z = " << statPos[iUnit] << endl; + } + // -------------------------------------------------------------------------- + + + // --------------- Create STS volume ------------------------------------ + cout << endl << endl; + cout << "===> Creating STS...." << endl; + +// // --- Determine size of STS box +// Double_t stsX = 0.; +// Double_t stsY = 0.; +// Double_t stsZ = 0.; +// Double_t stsBorder = 2*5.; // 5 cm space for carbon ladders on each side +// for (Int_t iStation = 1; iStation<=8; iStation++) { +// TString statName = Form("Station%02d", iStation); +// TGeoVolume* station = gGeoMan->GetVolume(statName); +// TGeoBBox* shape = (TGeoBBox*) station->GetShape(); +// stsX = TMath::Max(stsX, 2.* shape->GetDX() ); +// stsY = TMath::Max(stsY, 2.* shape->GetDY() ); +// cout << "Station " << iStation << ": Y " << stsY << endl; +// } +// // --- Some border around the stations +// stsX += stsBorder; +// stsY += stsBorder; +// stsZ = ( statPos[7] - statPos[0] ) + stsBorder; +// +// // --- Create box around the stations +// new TGeoBBox("stsBox", stsX/2., stsY/2., stsZ/2.); +// cout << "size of STS box: x " << stsX << " - y " << stsY << " - z " << stsZ << endl; +// +// // --- Create cone hosting the beam pipe +// // --- One straight section with constant radius followed by a cone +// Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +// Double_t z2 = gkPipeZ2; +// Double_t z3 = statPos[7] + 0.5 * stsBorder; // end of STS box +// Double_t r1 = BeamPipeRadius(z1); +// Double_t r2 = BeamPipeRadius(z2); +// Double_t r3 = BeamPipeRadius(z3); +// r1 += 0.01; // safety margin +// r2 += 0.01; // safety margin +// r3 += 0.01; // safety margin +// +// cout << endl; +// cout << z1 << " " << r1 << endl; +// cout << z2 << " " << r2 << endl; +// cout << z3 << " " << r3 << endl; +// +// cout << endl; +// cout << "station1 : " << BeamPipeRadius(statPos[0]) << endl; +// cout << "station2 : " << BeamPipeRadius(statPos[1]) << endl; +// cout << "station3 : " << BeamPipeRadius(statPos[2]) << endl; +// cout << "station4 : " << BeamPipeRadius(statPos[3]) << endl; +// cout << "station5 : " << BeamPipeRadius(statPos[4]) << endl; +// cout << "station6 : " << BeamPipeRadius(statPos[5]) << endl; +// cout << "station7 : " << BeamPipeRadius(statPos[6]) << endl; +// cout << "station8 : " << BeamPipeRadius(statPos[7]) << endl; +// +// // TGeoPcon* cutout = new TGeoPcon("stsCone", 0., 360., 3); // 2.*TMath::Pi(), 3); +// // cutout->DefineSection(0, z1, 0., r1); +// // cutout->DefineSection(1, z2, 0., r2); +// // cutout->DefineSection(2, z3, 0., r3); +// new TGeoTrd2("stsCone1", r1, r2, r1, r2, (z2-z1)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans1 = new TGeoTranslation("trans1", 0., 0., -(z3-z1)/2.+(z2-z1)/2.); +// trans1->RegisterYourself(); +// new TGeoTrd2("stsCone2", r2, r3, r2, r3, (z3-z2)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans2 = new TGeoTranslation("trans2", 0., 0., +(z3-z1)/2.-(z3-z2)/2.); +// trans2->RegisterYourself(); +// +////DE Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +////DE Double_t z2 = statPos[7] + 0.5 * stsBorder; // end of STS box +////DE Double_t slope = (gkPipeR2 - gkPipeR1) / (gkPipeZ2 - gkPipeZ1); +////DE Double_t r1 = gkPipeR1 + slope * (z1 - gkPipeZ1); // at start of STS +////DE Double_t r2 = gkPipeR1 + slope * (z2 - gkPipeZ1); // at end of STS +////DE r1 += 0.1; // safety margin +////DE r2 += 0.1; // safety margin +////DE // new TGeoCone("stsCone", stsZ/2., 0., r1, 0., r2); +////DE new TGeoTrd2("stsCone", r1, r2, r1, r2, stsZ/2.); + + + // // Create holding/cooling plates + // static std::vector< std::vector<Double_t> > plateSizes = { + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // }; + + // // 8-vertex cut-outs { minWidth, maxWidth, minHeight, maxHeight } + // static std::vector< std::vector<Double_t> > plateCutOuts = { + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 17.6, 47.6 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 49.0, 79.0 }, + // { 85.5,115.5, 51.5, 82.8 }, + // { 85.5,115.5, 59.0, 91.4 }, + // { 85.5,115.5, 68.0, 99.0 }, + // }; + + // for (Int_t iPlate = 0; iPlate < 9; iPlate++) { + // Int_t iUnit = iPlate * 2; + // TGeoBBox* outerPlate = new TGeoBBox(Form("outerPlate%02d",iPlate), + // plateSizes[iPlate][0], plateSizes[iPlate][1], plateSizes[iPlate][2]); + + // TGeoBBox* unitShapeR = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+0])->GetShape(); + // TGeoBBox* unitShapeL = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+1])->GetShape(); + + // Double_t maxDx = (unitShapeR->GetDX() + unitShapeL->GetDX()) / 2.; + // Double_t maxDy = TMath::Max(unitShapeR->GetDY(), unitShapeL->GetDY()); + // cout << maxDy << endl; + + // Double_t* cutOutX = new Double_t[8]; + // Double_t* cutOutY = new Double_t[8]; + + // cutOutX[0] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[0] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[1] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[1] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[2] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[2] = 1/2. * plateCutOuts[iPlate][2]; + // cutOutX[3] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[3] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[4] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[4] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[5] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[5] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[6] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[6] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[7] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[7] = 1/2. * plateCutOuts[iPlate][2]; + + // TGeoXtru* cutOutShape = new TGeoXtru(2); + // cutOutShape->SetName(Form("innerPlate%02d", iPlate)); + // cutOutShape->DefinePolygon(8, cutOutX, cutOutY); + // cutOutShape->DefineSection(0, -1*plateSizes[iPlate][2]-1e-7); + // cutOutShape->DefineSection(1, +1*plateSizes[iPlate][2]+1e-7); + + // TGeoShape* plateShape = new TGeoCompositeShape(Form("PlateShape%02d",iPlate), Form("outerPlate%02d-innerPlate%02d",iPlate,iPlate)); + // TGeoVolume* plate = new TGeoVolume(Form("Plate%02d", iPlate), plateShape, gGeoManager->GetMedium("aluminium")); + // plate->SetLineColor(kRed); + // plate->SetTransparency(65); + // plate->GetShape()->ComputeBBox(); + // } + + // --- Create STS volume + TString stsName = "sts_"; + stsName += geoTag; + +// TGeoShape* stsShape = new TGeoCompositeShape("stsShape", +// "stsBox-stsCone1:trans1-stsCone2:trans2"); +// TGeoVolume* sts = new TGeoVolume(stsName.Data(), stsShape, gStsMedium); + + Double_t stsBorder = 2 * 5.; + + TGeoVolume* sts = new TGeoVolumeAssembly(stsName.Data()); + + // --- Place stations in the STS + Double_t stsPosZ = 0.5 * ( statPos[15] + statPos[0] ); // todo units: update statPos[7] + // cout << "stsPosZ " << stsPosZ << " " << statPos[15] << " " << statPos[0] << "*****" << endl; + +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) { + for (Int_t iUnit = 0; iUnit < 18; iUnit++) { +// for (Int_t iUnit = 0; iUnit < 32; iUnit++) { + TGeoVolume* station = gGeoMan->GetVolume(unitName18[iUnit]); +// Double_t posZ = statPos[iUnit] - stsPosZ; + Double_t posZ = statPos18[iUnit] - stsPosZ; +// Double_t posZ = statPos[iUnit/2] - stsPosZ; + TGeoTranslation* trans = new TGeoTranslation(0., 0., posZ); + sts->AddNode(station, iUnit+1, trans); + sts->GetShape()->ComputeBBox(); + } + + // --- Import passive elements from GDML file + if (gkImportPassive) { + ImportPassive(sts, geoTag, infoFile); + } + + cout << endl; + CheckVolume(sts); + // -------------------------------------------------------------------------- + + + // --------------- Finish ----------------------------------------------- + TGeoTranslation* stsTrans = new TGeoTranslation(0., 0., stsPosZ); + top->AddNode(sts, 1, stsTrans); + top->GetShape()->ComputeBBox(); + cout << endl << endl; + + CheckVolume(top); + cout << endl << endl; + gGeoMan->CloseGeometry(); + gGeoMan->CheckOverlaps(0.0001); + gGeoMan->PrintOverlaps(); + gGeoMan->CheckOverlaps(0.0001, "s"); + gGeoMan->PrintOverlaps(); + gGeoMan->Test(); + + TFile* geoFile = new TFile(geoFileName, "RECREATE"); + top->Write(); + cout << endl; + cout << "Geometry " << top->GetName() << " written to " + << geoFileName << endl; + geoFile->Close(); + + TString geoFileName_ = "sts_"; + geoFileName_ = geoFileName_ + geoTag + "_geo.root"; + + geoFile = new TFile(geoFileName_, "RECREATE"); + gGeoMan->Write(); // use this is you want GeoManager format in the output + geoFile->Close(); + + TString geoFileName__ = "sts_"; + geoFileName_ = geoFileName__ + geoTag + "-geo.root"; + sts->Export(geoFileName_); + + geoFile = new TFile(geoFileName_, "UPDATE"); + stsTrans->Write(); + geoFile->Close(); + + // gGeoManager->FindVolumeFast("LadderType10_CarbonElement")->Draw("ogl"); + top->Draw("ogl"); + gGeoManager->SetVisLevel(8); + + infoFile.close(); + +} +// ============================================================================ +// ====== End of main function ===== +// ============================================================================ + + + + + +// **************************************************************************** +// ***** Definition of media, sensors, sectors and ladders ***** +// ***** ***** +// ***** Decoupled from main function for better readability ***** +// **************************************************************************** + + +/** =========================================================================== + ** Create media + ** + ** Currently created: air, active silicon, passive silion + ** + ** Not used for the time being + **/ +Int_t CreateMedia() { + + Int_t nMedia = 0; + Double_t density = 0.; + + // --- Material air + density = 1.205e-3; // [g/cm^3] + TGeoMixture* matAir = new TGeoMixture("sts_air", 3, density); + matAir->AddElement(14.0067, 7, 0.755); // Nitrogen + matAir->AddElement(15.999, 8, 0.231); // Oxygen + matAir->AddElement(39.948, 18, 0.014); // Argon + + // --- Material silicon + density = 2.33; // [g/cm^3] + TGeoElement* elSi = gGeoMan->GetElementTable()->GetElement(14); + TGeoMaterial* matSi = new TGeoMaterial("matSi", elSi, density); + + + // --- Air (passive) + TGeoMedium* medAir = new TGeoMedium("air", nMedia++, matAir); + medAir->SetParam(0, 0.); // is passive + medAir->SetParam(1, 1.); // is in magnetic field + medAir->SetParam(2, 20.); // max. field [kG] + medAir->SetParam(6, 0.001); // boundary crossing precision [cm] + + + // --- Active silicon for sensors + TGeoMedium* medSiAct = new TGeoMedium("silicon", + nMedia++, matSi); + medSiAct->SetParam(0, 1.); // is active + medSiAct->SetParam(1, 1.); // is in magnetic field + medSiAct->SetParam(2, 20.); // max. field [kG] + medSiAct->SetParam(6, 0.001); // boundary crossing precisison [cm] + + // --- Passive silicon for cables + TGeoMedium* medSiPas = new TGeoMedium("carbon", + nMedia++, matSi); + medSiPas->SetParam(0, 0.); // is passive + medSiPas->SetParam(1, 1.); // is in magnetic field + medSiPas->SetParam(2, 20.); // max. field [kG] + medSiPas->SetParam(6, 0.001); // boundary crossing precisison [cm] + + return nMedia; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sensors + ** + ** Sensors are created as volumes with box shape and active silicon as medium. + ** Four kinds of sensors: 3.2x2.2, 6.2x2.2, 6.2x4.2, 6.2x6.2 + **/ +Int_t CreateSensors() { + + Int_t nSensors = 0; + + Double_t xSize = 0.; + Double_t ySize = 0.; + Double_t zSize = gkSensorThickness; + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + + + // --- Sensor type 01: Small sensor (6.2 cm x 2.2 cm) + xSize = gkSensorSizeX; + ySize = 2.2; + TGeoBBox* shape_sensor01 = new TGeoBBox("sensor01", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor01", shape_sensor01, silicon); + nSensors++; + + + // --- Sensor type 02: Medium sensor (6.2 cm x 4.2 cm) + xSize = gkSensorSizeX; + ySize = 4.2; + TGeoBBox* shape_sensor02 = new TGeoBBox("sensor02", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor02", shape_sensor02, silicon); + nSensors++; + + + // --- Sensor type 03: Big sensor (6.2 cm x 6.2 cm) + xSize = gkSensorSizeX; + ySize = 6.2; + TGeoBBox* shape_sensor03 = new TGeoBBox("sensor03", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor03", shape_sensor03, silicon); + nSensors++; + + + // --- Sensor type 04: Big sensor (6.2 cm x 12.4 cm) + xSize = gkSensorSizeX; + ySize = 12.4; + TGeoBBox* shape_sensor04 = new TGeoBBox("sensor04", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor04", shape_sensor04, silicon); + nSensors++; + + + // below are extra small sensors, those are not available in the CAD model + + // --- Sensor Type 05: Half small sensor (4 cm x 2.5 cm) + xSize = 4.0; + ySize = 2.5; + TGeoBBox* shape_sensor05 = new TGeoBBox("sensor05", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor05", shape_sensor05, silicon); + nSensors++; + + + // --- Sensor type 06: Additional "in hole" sensor (3.1 cm x 4.2 cm) + xSize = 3.1; + ySize = 4.2; + TGeoBBox* shape_sensor06 = new TGeoBBox("sensor06", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor06", shape_sensor06, silicon); + nSensors++; + + + // --- Sensor type 07: Mini Medium sensor (1.5 cm x 4.2 cm) + xSize = 1.5; + ySize = 4.2; + TGeoBBox* shape_sensor07 = new TGeoBBox("sensor07", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor07", shape_sensor07, silicon); + nSensors++; + + + return nSensors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sectors + ** + ** A sector is either a single sensor or several chained sensors. + ** It is implemented as TGeoVolumeAssembly. + ** Currently available: + ** - single sensors of type 1 - 4 + ** - two chained sensors of type 4 + ** - three chained sensors of type 4 + **/ +Int_t CreateSectors() { + + Int_t nSectors = 0; + + TGeoVolume* sensor01 = gGeoMan->GetVolume("Sensor01"); + TGeoVolume* sensor02 = gGeoMan->GetVolume("Sensor02"); + TGeoVolume* sensor03 = gGeoMan->GetVolume("Sensor03"); + TGeoVolume* sensor04 = gGeoMan->GetVolume("Sensor04"); + TGeoVolume* sensor05 = gGeoMan->GetVolume("Sensor05"); + TGeoVolume* sensor06 = gGeoMan->GetVolume("Sensor06"); + TGeoVolume* sensor07 = gGeoMan->GetVolume("Sensor07"); + // TGeoBBox* box4 = (TGeoBBox*) sensor04->GetShape(); + + // --- Sector type 1: single sensor of type 1 + TGeoVolumeAssembly* sector01 = new TGeoVolumeAssembly("Sector01"); + sector01->AddNode(sensor01, 1); + sector01->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 2: single sensor of type 2 + TGeoVolumeAssembly* sector02 = new TGeoVolumeAssembly("Sector02"); + sector02->AddNode(sensor02, 1); + sector02->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 3: single sensor of type 3 + TGeoVolumeAssembly* sector03 = new TGeoVolumeAssembly("Sector03"); + sector03->AddNode(sensor03, 1); + sector03->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 4: single sensor of type 4 + TGeoVolumeAssembly* sector04 = new TGeoVolumeAssembly("Sector04"); + sector04->AddNode(sensor04, 1); + sector04->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 5: single sensor of type 5 + TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); + sector05->AddNode(sensor05, 1); + sector05->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 6: single sensor of type 6 + TGeoVolumeAssembly* sector06 = new TGeoVolumeAssembly("Sector06"); + sector06->AddNode(sensor06, 1); + sector06->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 7: single sensor of type 7 + TGeoVolumeAssembly* sector07 = new TGeoVolumeAssembly("Sector07"); + sector07->AddNode(sensor07, 1); + sector07->GetShape()->ComputeBBox(); + nSectors++; + +// // --- Sector type 5: two sensors of type 4 +// TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); +// Double_t shift5 = 0.5 * gkChainGapY + box4->GetDY(); +// TGeoTranslation* transD5 = +// new TGeoTranslation("td", 0., -1. * shift5, 0.); +// TGeoTranslation* transU5 = +// new TGeoTranslation("tu", 0., shift5, 0.); +// sector05->AddNode(sensor04, 1, transD5); +// sector05->AddNode(sensor04, 2, transU5); +// sector05->GetShape()->ComputeBBox(); +// nSectors++; + + return nSectors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create ladders + ** + ** Ladders are the building blocks of the stations. They contain + ** several modules placed one after the other along the z axis + ** such that the sectors are arranged vertically (with overlap). + ** + ** A ladder is constructed out of two half ladders, the second of which + ** is rotated in the x-y plane by 180 degrees and displaced + ** in z direction. + **/ +Int_t CreateLadders() { + + Int_t nLadders = 0; + + // --- Some variables + Int_t nSectors = 0; + Int_t sectorTypes[10]; + TGeoBBox* shape = NULL; + TString s0name; + TString hlname; + char align; + TGeoVolume* s0vol = NULL; + TGeoVolume* halfLadderU = NULL; + TGeoVolume* halfLadderD = NULL; + + // --- Ladders 01-23 + Int_t allSectorTypes[27][6] = { { 1, 2, 3, 3, 0, -1 }, // ladder 01 - 5 - last column defines alignment of small sensors + { 1, 2, 3, 3, 0, 0 }, // ladder 02 - 5 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, -1 }, // ladder 03 - 6 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 04 - 6 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, -1 }, // ladder 05 - 7 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 06 - 7 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 07 - last column defines alignment of small sensors + { 3, 4, 4, 4, 0, 0 }, // ladder 08 - last column defines alignment of small sensors + + { 1, 1, 2, 3, 3, 0 }, // ladder 09 - last column defines alignment of small sensors + { 1, 1, 2, 2, 3, 0 }, // ladder 10 - last column defines alignment of small sensors + { 2, 2, 0, 0, 0, 0 }, // ladder 11 - last column defines alignment of small sensors + { 2, 2, 2, 3, 4, 0 }, // ladder 12 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 13 - last column defines alignment of small sensors + + { 2, 3, 4, 0, 0, 0 }, // ladder 14 - last column defines alignment of small sensors + { 3, 3, 0, 0, 0, 0 }, // ladder 15 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 16 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 17 - last column defines alignment of small sensors + { 3, 4, 4, 0, 0, 0 }, // ladder 18 - last column defines alignment of small sensors + + { 4, 4, 0, 0, 0, 0 }, // ladder 19 - last column defines alignment of small sensors + { 1, 2, 4, 4, 4, 0 }, // ladder 20 - last column defines alignment of small sensors + { 4, 0, 0, 0, 0, 0 }, // ladder 21 - last column defines alignment of small sensors + { 2, 3, 4, 4, 4, 0 }, // ladder 22 - last column defines alignment of small sensors + { 2, 3, 3, 4, 4, 0 }, // ladder 23 - last column defines alignment of small sensors + + { 2, 3, 4, 4, 0, 0 }, // ladder 24 - copy of 17 with different total length + { 3, 4, 4, 0, 0, 0 }, // ladder 25 - copy of 18 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 26 - copy of 19 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 27 - copy of 19 with different total length + }; // 8 full - 19 partial ladders + +// Issue #405 +// Counting from the most upstream ladder, the gaps between sensors are as follows: +// 01 (most upstream): 41.3mm +// 02: 41.3mm +// 03: 42.0mm +// 04: 48.6mm +// 05: 60.8mm +// 06: 67.0mm +// 07: 79.2mm +// 08 (most downstream): 88.0mm + + Double_t pitchZ = 0; + Double_t gapXYZ[27][3] = { + { 0., 4.13, 0. }, // ladder 01 + { 0., 4.13, 0. }, // ladder 02 + { 0., 4.20, 0. }, // ladder 03 + { 0., 4.86, 0. }, // ladder 04 + { 0., 6.08, 0. }, // ladder 05 + { 0., 6.70, 0. }, // ladder 06 + { 0., 7.92, 0. }, // ladder 07 + { 0., 8.80, 0. }, // ladder 08 + { 0., -gkSectorOverlapY, 0. }, // ladder 09 + { 0., -gkSectorOverlapY, 0. }, // ladder 10 + { 0., -gkSectorOverlapY, 0. }, // ladder 11 + { 0., -gkSectorOverlapY, 0. }, // ladder 12 + { 0., -gkSectorOverlapY, 0. }, // ladder 13 + { 0., -gkSectorOverlapY, 0. }, // ladder 14 + { 0., -gkSectorOverlapY, 0. }, // ladder 15 + { 0., -gkSectorOverlapY, 0. }, // ladder 16 + { 0., -gkSectorOverlapY, 0. }, // ladder 17 + { 0., -gkSectorOverlapY, 0. }, // ladder 18 + { 0., -gkSectorOverlapY, 0. }, // ladder 19 + { 0., -gkSectorOverlapY, 0. }, // ladder 20 + { 0., -gkSectorOverlapY, 0. }, // ladder 21 + { 0., -gkSectorOverlapY, 0. }, // ladder 22 + { 0., -gkSectorOverlapY, 0. }, // ladder 23 + + { 0., -gkSectorOverlapY, 0. }, // ladder 24 - copy of 17 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 25 - copy of 18 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 26 - copy of 19 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 27 - copy of 19 with different total length + }; + + Double_t ladderLength[27] = { + 48.0, // ladder 01 + 48.0, // ladder 02 + 64.0, // ladder 03 + 64.0, // ladder 04 + 80.0, // ladder 05 + 80.0, // ladder 06 + 92.0, // ladder 07 + 96.0, // ladder 08 + 48.0, // ladder 09 + 48.0, // ladder 10 + 48.0, // ladder 11 + 64.0, // ladder 12 + 64.0, // ladder 13 + 64.0, // ladder 14 + 64.0, // ladder 15 + 80.0, // ladder 16 + 80.0, // ladder 17 + 80.0, // ladder 18 + 80.0, // ladder 19 + 92.0, // ladder 20 + 92.0, // ladder 21 + 96.0, // ladder 22 + 96.0, // ladder 23 + + 96.0, // ladder 24 - copy of 17 with different total length + 92.0, // ladder 25 - copy of 18 with different total length + 96.0, // ladder 26 - copy of 19 with different total length + 92.0, // ladder 27 - copy of 19 with different total length + }; +// ======================================================================== + + // calculate Z shift for ladders with and without gaps in the center + s0name = Form("Sector%02d", allSectorTypes[0][0]); + s0vol = gGeoMan->GetVolume(s0name); + shape = (TGeoBBox*) s0vol->GetShape(); + +// ======================================================================== + + for (Int_t iLadder = 0; iLadder < 27; iLadder++) + { + cout << endl; + nSectors = 0; + for (Int_t i=0; i < 5; i++) + if (allSectorTypes[iLadder][i] != 0) + { + sectorTypes[nSectors] = allSectorTypes[iLadder][i]; // copy sectors for this ladder + cout << "DE iLadder " << iLadder+1 << " sectorTypes[" << nSectors << "] = " << allSectorTypes[iLadder][i] << ";" << endl; + nSectors++; // count how many sectors are in this ladder + } + + // always set displacement in z between upper and lower half ladder + gapXYZ[iLadder][2] = 2. * shape->GetDZ() + gkSectorGapZ; + + // define additional offset to carbon ladder for half ladders with less than 5 sensors + pitchZ = 2. * shape->GetDZ() + gkSectorGapZ; + + if (allSectorTypes[iLadder][5] == 0) + align = 'l'; + else + align = 'r'; + hlname = Form("HalfLadder%02du", iLadder+1); + // build upper half ladder + Int_t Ustart = 0; // 1; + if (iLadder < 8) + Ustart = 1; // 0; + halfLadderU = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2., Ustart); // mirrored + + if (allSectorTypes[iLadder][5] == 0) + align = 'r'; + else + align = 'l'; + hlname = Form("HalfLadder%02dd", iLadder+1); + // build lower half ladder + Int_t Dstart = 1; // 0; + if (iLadder < 8) + Dstart = 0; // 1; + halfLadderD = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2., Dstart); // mirrored + + // at this point half ladders are constructed + + // build all 4 possible ladders types for this sensor arrangement + ConstructLadder( iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19a + ConstructLadder( 100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19b + + ConstructLadder(1000+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19k + ConstructLadder(1100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19k + + nLadders++; + } + + return nLadders; +} +/** ======================================================================= **/ + + + +// **************************************************************************** +// ***** ***** +// ***** Generic functions for the construction of STS elements ***** +// ***** ***** +// ***** module: volume (made of a sector and a cable) ***** +// ***** haf ladder: assembly (made of modules) ***** +// ***** ladder: assembly (made of two half ladders) ***** +// ***** station: volume (made of ladders) ***** +// ***** ***** +// **************************************************************************** + + + +/** =========================================================================== + ** Construct a module + ** + ** A module is a sector plus the readout cable extending from the + ** top of the sector. The cable is made from passive silicon. + ** The cable has the same x size as the sector. + ** Its thickness is given by the global variable gkCableThickness. + ** The cable length is a parameter. + ** The sensor(s) of the sector is/are placed directly in the module; + ** the sector is just auxiliary for the proper placement. + ** + ** Arguments: + ** name volume name + ** sector pointer to sector volume + ** cableLength length of cable + **/ +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength) { + + // --- Check sector volume + if ( ! sector ) Fatal("CreateModule", "Sector volume not found!"); + + // --- Get size of sector + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + + // --- Get size of cable + Double_t cableX = sectorX; + Double_t cableY = cableLength; + Double_t cableZ = gkCableThickness; + + // --- Create module volume + Double_t moduleX = TMath::Max(sectorX, cableX); + Double_t moduleY = sectorY + cableLength; + + Double_t moduleZ = TMath::Max(sectorZ, cableZ); + + TGeoVolume* module = gGeoManager->MakeBox(name, gStsMedium, + moduleX/2., + moduleY/2., + moduleZ/2.); + + // --- Position of sector in module + // --- Sector is centred in x and z and aligned to the bottom + Double_t sectorXpos = 0.; + Double_t sectorYpos = 0.5 * (sectorY - moduleY); + Double_t sectorZpos = 0.; + + + // --- Get sensor(s) from sector + Int_t nSensors = sector->GetNdaughters(); + for (Int_t iSensor = 0; iSensor < nSensors; iSensor++) { + TGeoNode* sensor = sector->GetNode(iSensor); + + // --- Calculate position of sensor in module + const Double_t* xSensTrans = sensor->GetMatrix()->GetTranslation(); + Double_t sensorXpos = sectorXpos + xSensTrans[0]; + Double_t sensorYpos = sectorYpos + xSensTrans[1]; + Double_t sensorZpos = sectorZpos + xSensTrans[2]; + TGeoTranslation* sensTrans = new TGeoTranslation("sensTrans", + sensorXpos, + sensorYpos, + sensorZpos); + + // --- Add sensor volume to module + TGeoVolume* sensVol = sensor->GetVolume(); + module->AddNode(sensor->GetVolume(), iSensor+1, sensTrans); + module->GetShape()->ComputeBBox(); + } + + + // --- Create cable volume, if necessary, and place it in module + // --- Cable is centred in x and z and aligned to the top + if ( gkConstructCables && cableLength > 0.0001 ) { + TString cableName = TString(name) + "_cable"; + TGeoMedium* cableMedium = gGeoMan->GetMedium("STScable"); + if ( ! cableMedium ) Fatal("CreateModule", "Medium STScable not found!"); + TGeoVolume* cable = gGeoManager->MakeBox(cableName.Data(), + cableMedium, + cableX / 2., + cableY / 2., + cableZ / 2.); + // add color to cables + cable->SetLineColor(kOrange); + cable->SetTransparency(60); + Double_t cableXpos = 0.; + Double_t cableYpos = sectorY + 0.5 * cableY - 0.5 * moduleY; + Double_t cableZpos = 0.; + TGeoTranslation* cableTrans = new TGeoTranslation("cableTrans", + cableXpos, + cableYpos, + cableZpos); + module->AddNode(cable, 1, cableTrans); + module->GetShape()->ComputeBBox(); + } + + return module; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a half ladder + ** + ** A half ladder is a virtual volume (TGeoVolumeAssembly) consisting + ** of several modules arranged on top of each other. The modules + ** have a given overlap in y and a displacement in z to allow for the + ** overlap. + ** + ** The typ of sectors / modules to be placed must be specified: + ** 1 = sensor01 + ** 2 = sensor02 + ** 3 = sensor03 + ** 4 = sensor04 + ** 5 = 2 x sensor04 (chained) + ** 6 = 3 x sensor04 (chained) + ** The cable is added automatically from the top of each sensor to + ** the top of the half ladder. + ** The alignment can be left (l) or right (r), which matters in the + ** case of different x sizes of sensors (e.g. SensorType01). + ** + ** Arguments: + ** name volume name + ** nSectors number of sectors + ** sectorTypes array with sector types + ** align horizontal alignment of sectors + * ladderLength full length of the ladder towards FEE + * offsetY gap in the beam-pipe region + **/ +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY, + Int_t start) { + + // --- Create half ladder volume assembly + TGeoVolumeAssembly* halfLadder = new TGeoVolumeAssembly(name); + + // --- Determine size of ladder + Double_t ladderX = 0.; + Double_t ladderY = 0.; + Double_t ladderZ = 0.; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + if ( ! sector ) + Fatal("ConstructHalfLadder", Form("Volume %s not found", sectorName.Data())); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + // --- Ladder x size equals largest sector x size + ladderX = TMath::Max(ladderX, 2. * box->GetDX()); + // --- Ladder y size is sum of sector ysizes + ladderY += 2. * box->GetDY(); + // --- Ladder z size is sum of sector z sizes + ladderZ += 2. * box->GetDZ(); + + cout << "DETT " << ladderX << " ; " << ladderY << " ; " << ladderZ << endl; + } + // --- Subtract overlaps in y + ladderY -= Double_t(nSectors-1) * gkSectorOverlapY; + // --- Add gaps in z direction + ladderZ += Double_t(nSectors-1) * gkSectorGapZ; + + ladderY = TMath::Max(ladderLength - offsetY, ladderY); + + // --- Create and place modules + Double_t yPosSect = -0.5 * ladderY; + Double_t zPosMod = -0.5 * ladderZ; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + yPosSect += 0.5 * sectorY; // Position of sector in ladder + Double_t cableLength = 0.5 * ladderY - yPosSect - 0.5 * sectorY; + TString moduleName = name + "_" + Form("Module%02d", + sectorTypes[iSector]); + TGeoVolume* module = ConstructModule(moduleName.Data(), + sector, cableLength); + + TGeoBBox* shapeMod = (TGeoBBox*) module->GetShape(); + Double_t moduleX = 2. * shapeMod->GetDX(); + Double_t moduleY = 2. * shapeMod->GetDY(); + Double_t moduleZ = 2. * shapeMod->GetDZ(); + Double_t xPosMod = 0.; + if ( align == 'l' ) + xPosMod = 0.5 * (moduleX - ladderX); // left aligned + else if ( align == 'r' ) + xPosMod = 0.5 * (ladderX - moduleX); // right aligned + else + xPosMod = 0.; // centred in x + Double_t yPosMod = 0.5 * (ladderY - moduleY); // top aligned + zPosMod += 0.5 * moduleZ; + +// Int_t angle = 0; // set default rotation angle to 0 +// if (iSector%2 == 1) // set rotation angle for every 2nd sensor +// angle = 180; + + Int_t angle = start * 180; + start = (start + 1) % 2; + + TGeoRotation* rmod = new TGeoRotation(); + // rmod->RotateY(angle); + rmod->RotateY(180); // v19v + // rmod->RotateY(0); // v19w + TGeoCombiTrans* cmod = new TGeoCombiTrans (xPosMod, yPosMod, zPosMod, rmod); + halfLadder->AddNode(module, iSector+1, cmod); + +// old style +// TGeoTranslation* trans = new TGeoTranslation("t", xPosMod, yPosMod, zPosMod); +// halfLadder->AddNode(module, iSector+1, trans); + + halfLadder->GetShape()->ComputeBBox(); + yPosSect += 0.5 * sectorY - gkSectorOverlapY; + zPosMod += 0.5 * moduleZ + gkSectorGapZ; + } + + CheckVolume(halfLadder); + cout << endl; + + return halfLadder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Add a carbon support to a ladder + ** + ** Arguments: + ** LadderIndex ladder number + ** ladder pointer to ladder + ** xu size of halfladder + ** ladderY height of ladder along y + ** ladderZ thickness of ladder along z + **/ +void AddCarbonLadder(Int_t LadderIndex, + TGeoVolume* ladder, + Double_t xu, + Double_t ladderY, + Double_t ladderZ) { + + // --- Some variables + TString name = Form("LadderType%04d", LadderIndex); // v19k + Int_t i; + Double_t j; + + Int_t YnumOfFrameBoxes = round(ladderY / gkFrameStep); + + // cout << "DEXZ: lad " << LadderIndex << " inum " << YnumOfFrameBoxes << endl; + + Double_t ladderDZ = (xu/2. + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2)/2.; + cout << "DEFR: frame Z size " << 2 * ladderDZ << " cm" << endl; + + TGeoBBox* fullFrameShp = new TGeoBBox (name+"_CarbonElement_shp", xu/2., gkFrameStep/2., ladderDZ); + TGeoVolume* fullFrameBoxVol = new TGeoVolume(name+"_CarbonElement", fullFrameShp, gStsMedium); + + ConstructFrameElement("CarbonElement", fullFrameBoxVol, xu/2.); + TGeoRotation* fullFrameRot = new TGeoRotation; + fullFrameRot->RotateY(180); + + Int_t inum = YnumOfFrameBoxes; + for (i=1; i<=inum; i++) + { + j=-(inum-1)/2.+(i-1); + // -(10-1)/2. +0 +10-1 -> -4.5 .. +4.5 -> -0.5, +0.5 (= 2) + // -(11-1)/2. +0 +11-1 -> -5.0 .. +5.0 -> -1, 0, 1 (= 3) + // cout << "DE: i " << i << " j " << j << endl; + + if (LadderIndex % 100 <= 3) // central ladders in stations 1 to 3 + { + if ((j>=-1) && (j<=1)) // keep the inner 2 (even) or 3 (odd) elements free for the cone + continue; + } + else if (LadderIndex % 100 <= 8) // central ladders in stations 4 to 8 + { + if ((j>=-2) && (j<=2)) // keep the inner 4 elements free for the cone + continue; + } + + cout << "DELZ: ladderDZ " << ladderDZ << " cm " << -ladderZ/2. - ladderDZ << " cm " << endl; + ladder->AddNode(fullFrameBoxVol, i, new TGeoCombiTrans(name+"_CarbonElement_posrot", 0., j*gkFrameStep, -(ladderZ/2.+ladderDZ), fullFrameRot)); + } + + ladder->GetShape()->ComputeBBox(); + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Construct a ladder out of two half ladders with vertical gap + ** + ** The second half ladder will be rotated by 180 degrees + ** in the x-y plane. The two half ladders will be put on top of each + ** other with a vertical gap. + ** + ** Arguments: + ** name volume name + ** halfLadderU pointer to upper half ladder + ** halfLadderD pointer to lower half ladder + ** gapY vertical gap + ** shiftZ relative displacement along the z axis + **/ + + TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ, + Double_t pitchZ, + Int_t nSectors) { + + // --- Some variables + TGeoBBox* shape = NULL; + + // define additional offset to carbon ladder for half ladders with less than 5 sensors + Double_t offsetZ = (5 - nSectors) * pitchZ; + + // --- Dimensions of half ladders + shape = (TGeoBBox*) halfLadderU->GetShape(); // up + Double_t xu = 2. * shape->GetDX(); + Double_t yu = 2. * shape->GetDY(); + Double_t zu = 2. * shape->GetDZ(); + + shape = (TGeoBBox*) halfLadderD->GetShape(); // down + Double_t xd = 2. * shape->GetDX(); + Double_t yd = 2. * shape->GetDY(); + Double_t zd = 2. * shape->GetDZ(); + + // --- Create ladder volume assembly + TString name = Form("LadderType%04d", LadderIndex); // v19k + TGeoVolumeAssembly* ladder = new TGeoVolumeAssembly(name); + Double_t ladderX = TMath::Max(xu, xd); + Double_t ladderY = yu + yd + gapY; + Double_t ladderZ = TMath::Max(zu, zd + shiftZ + offsetZ); // there are 6 slots - 5 x 1.5 mm + 0.3 mm = 7.8 mm + // Double_t ladderZ = TMath::Max(zu, zd + shiftZ); + + cout << "DERR iladder " << LadderIndex << " nSec " << nSectors + << " zu " << zu << " zd " << zd + << " zd+shi " << zd+shiftZ << " ladderZ " << ladderZ + << " offsetZ " << offsetZ << endl; + + // --- Place half ladders + Double_t xPosU = 0.0; // centred in x + Double_t yPosU = 0.5 * ( ladderY - yu ); // top aligned + Double_t zPosU = 0; + zPosU = 0.5 * ( ladderZ - zu ); // front aligned + if (LadderIndex >= 1000) + zPosU = -0.5 * ( ladderZ - zu ) + offsetZ; // back aligned with possible offset + //zPosU = -zPosU; + + TGeoTranslation* tu = new TGeoTranslation("tu", xPosU, yPosU, zPosU); + ladder->AddNode(halfLadderU, 1, tu); + + Double_t xPosD = 0.0; // centred in x + Double_t yPosD = 0.5 * -( ladderY - yd ); // bottom aligned + Double_t zPosD = 0; + zPosD = 0.5 * -( ladderZ - zd ) + offsetZ; // back aligned with possible offset + if (LadderIndex >= 1000) + zPosD = -0.5 * -( ladderZ - zd ); // front aligned + //zPosD = -zPosD; + + TGeoRotation* rd = new TGeoRotation(); + rd->RotateZ(180.); + TGeoCombiTrans* cd = new TGeoCombiTrans(xPosD, yPosD, zPosD, rd); + ladder->AddNode(halfLadderD, 2, cd); + + ladder->GetShape()->ComputeBBox(); + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD0ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + cout << "DDDD ladder" << LadderIndex << endl; + cout << "DDDD1ladder" << LadderIndex << " ladderX " << ladderX << " ladderY " << ladderY << " ladderZ " << ladderZ << endl; + + // ---------------- Create and place frame boxes ------------------------ + + if (gkConstructFrames) + AddCarbonLadder(LadderIndex, ladder, ladderX, ladderY, ladderZ); + + // -------------------------------------------------------------------------- + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD2ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + return ladder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a unit + ** + ** The unit volume is the minimal box comprising all ladders + ** minus a tube accomodating the beam pipe. + ** + ** The ladders are arranged horizontally from left to right with + ** a given overlap in x. + ** Every second ladder is slightly displaced upstream from the centre + ** z plane and facing downstream, the others are slightly displaced + ** downstream and facing upstream (rotated around the y axis). + ** + ** Arguments: + ** name volume name + ** nLadders number of ladders + ** ladderTypes array of ladder types + **/ + + TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation) { + + Bool_t isFirstPartOfHalfUnit = kFALSE; + + // TString name = Form("Unit%02d", iUnit); // 0,1,2,3,4,5,6,7 - Unit00 missing in output + // TString name = Form("Unit%02d", iUnit+1); // 1,2,3,4,5,6,7,8 + + TGeoVolume* unit = gGeoMan->GetVolume(unitName[iUnit]); + if ( ! unit ) // if it does not yet exist, create a new one + { + unit = new TGeoVolumeAssembly(unitName[iUnit]); + isFirstPartOfHalfUnit = kTRUE; + } + + // --- Some local variables + TGeoBBox* ladderShape = NULL; + TGeoVolume* ladder = NULL; + TString ladderName; + Double_t subtractedVal; + + // --- Determine size of unit from ladders + Double_t statX = 0.; + // Double_t statY = 0.; + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) + { + Int_t ladderType = ladderTypes[iLadder]; // v19k + +// if (iSide == 0) cout << "DWER " << ladderTypes[iLadder] << " " << ladderType << endl; + + if (ladderType > 0) + { + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + if ( ! ladder ) Fatal("ConstructUnit", + Form("Volume %s not found", ladderName.Data())); + ladderShape = (TGeoBBox*) ladder->GetShape(); + statX += 2. * ladderShape->GetDX(); + } + else + statX += gkSensorSizeX; // empty ladder in unit + } + statX -= Double_t(nLadders-1) * gkLadderOverlapX; + +// if (iSide == 0) cout << "DWER -" << endl; + + // --- Place ladders in unit + cout << "xPos0: " << statX << endl; + Double_t xPos = -0.5 * statX; + cout << "xPos1: " << xPos << endl; + Double_t yPos = 0.; + Double_t zPos = 0.; + + Double_t maxdz = 0.; + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) // find maximum dz in this unit + { + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + if (maxdz < ladderShape->GetDZ()) + maxdz = ladderShape->GetDZ(); + } + } + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) + { + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + xPos += ladderShape->GetDX(); + cout << "xPos2: " << xPos << endl; + yPos = 0.; // vertically centred + TGeoRotation* rot = new TGeoRotation(); + + if (gkConstructFrames) + subtractedVal = ladderShape->GetDX() + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2; + else + subtractedVal = 0.; + + zPos = 0.5 * gkLadderGapZ + (2*maxdz-ladderShape->GetDZ()-subtractedVal/2.); // z-aligned ladders + +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " dx: " << ladderShape->GetDX() + << " dy: " << ladderShape->GetDY() + << " dz: " << ladderShape->GetDZ() + << " max dz: " << maxdz << endl; + +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " fra: " << gkFrameThickness/2. + << " sub: " << subtractedVal + << " zpo: " << zPos << endl << endl; + +// v19k + if (ladderTypes[iLadder]/1000 == 1) // flip some of the ladders to reproduce the CAD layout + rot->RotateY(180.); + else + zPos = -zPos; + + if (!isFirstPartOfHalfUnit) + zPos += 10.5; // v19d +// zPos += 10.0; // initial version + + TGeoCombiTrans* trans = new TGeoCombiTrans(xPos, yPos, zPos, rot); +// start +// cout << "DEEE** iLadder " << iLadder << " " << nLadders/2 << " " << nLadders << endl; + + if (iSide == 0) + { + if (iLadder < nLadders/2) // right side - only half unit -x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + else + { + if (iLadder >= nLadders/2) // left side - only half unit +x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + unit->GetShape()->ComputeBBox(); +// stop + xPos += ladderShape->GetDX() - gkLadderOverlapX; + cout << "xPos3: " << xPos << endl; + } + else + xPos += gkSensorSizeX - gkLadderOverlapX; + } + + return unit; + } +/** ======================================================================= **/ + + +/** =========================================================================== + ** Import and add the passive materials to the STS volume + **/ +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile) +{ + TString passiveName = TString("sts_passive_") + geoTag; + TString basePath = gSystem->Getenv("VMCWORKDIR"); + TString relPath = "/geometry/sts/passive/" + passiveName + ".gdml"; + TString passiveFileName = basePath + relPath; + infoFile << std::endl << std::endl; + infoFile << "Importing STS passive materials from GDML file '" << relPath << "'." << std::endl; + + TGDMLParse parser; + TGeoVolume* gdmlVolume = parser.GDMLReadFile(passiveFileName); + PostProcessGdml(gdmlVolume); + gdmlVolume->SetName(passiveName); + + TGeoTranslation* passiveTrans = new TGeoTranslation(0., 0., 4.68 - 2.); + infoFile << "Passive assembly is translated for Z=2.68 cm downstream with respect to parent volume" << std::endl << std::endl; + + gdmlVolume->GetShape()->ComputeBBox(); + CheckVolume(gdmlVolume, infoFile); + + infoFile << std::endl; + for (Int_t iNode = 0; iNode < gdmlVolume->GetNdaughters(); iNode++) { + CheckVolume(gdmlVolume->GetNode(iNode)->GetVolume(), infoFile, kFALSE); + } + + stsVolume->AddNode(gdmlVolume, stsVolume->GetNdaughters(), passiveTrans, ""); +} + +/** =========================================================================== + ** Assign visual properties to the imported gdml volumes + **/ +void PostProcessGdml(TGeoVolume* gdmlVolume) +{ + const UInt_t kPOBColor = kRed-6; + const UInt_t kPOBTransparency = 0;// 5; + + const UInt_t kFEBColor = kOrange-6; + const UInt_t kFEBTransparency = 0;// 5; + + const UInt_t kUnitColor = kCyan-10; + const UInt_t kUnitTransparency = 0;// 5; + + const UInt_t kCfColor = kGray+3; + const UInt_t kCfTransparency = 0;// 10; + + // name <Color, Transparency> + std::map<std::string, std::tuple<UInt_t,UInt_t> > props { + { "passive_POB", std::tuple<UInt_t,UInt_t> {kPOBColor, kPOBTransparency} }, + { "passive_FEB", std::tuple<UInt_t,UInt_t> {kFEBColor, kFEBTransparency} }, + { "passive_unit", std::tuple<UInt_t,UInt_t> {kUnitColor, kUnitTransparency} }, + { "passive_Box_Wall", std::tuple<UInt_t,UInt_t> {kCfColor, kCfTransparency} }, + { "passive_Box_Wall_Front_CF2", std::tuple<UInt_t,UInt_t> {kCfColor-3, kCfTransparency} }, + }; + + // Match volume name and apply visual properties + const TObjArray* volumes = gGeoManager->GetListOfVolumes(); + for (auto& entry : props) { + TIter next(volumes); + TGeoVolume *vol = nullptr; + while ((vol=(TGeoVolume*)next())) { + if (TString(vol->GetName()).Contains(entry.first.c_str())) { + vol->SetLineColor(std::get<0>(entry.second)); + vol->SetTransparency(std::get<1>(entry.second)); + } + } + } +} + +/** =========================================================================== + ** Volume information for debugging + **/ +void CheckVolume(TGeoVolume* volume) { + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + cout << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) cout << ", assembly"; + else { + if ( volume->GetMedium() ) + cout << ", medium " << volume->GetMedium()->GetName(); + else cout << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + cout << endl; + if ( volume->GetNdaughters() ) { + cout << "Daughters: " << endl; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) { + TGeoNode* node = volume->GetNode(iNode); + TGeoBBox* shape = (TGeoBBox*) node->GetVolume()->GetShape(); + cout << setw(15) << node->GetName() << ", size " + << fixed << setprecision(3) + << setw(6) << 2. * shape->GetDX() << " x " + << setw(6) << 2. * shape->GetDY() << " x " + << setw(6) << 2. * shape->GetDZ() << ", position ( "; + TGeoMatrix* matrix = node->GetMatrix(); + const Double_t* pos = matrix->GetTranslation(); + cout << setfill(' '); + cout << fixed << setw(8) << pos[0] << ", " + << setw(8) << pos[1] << ", " + << setw(8) << pos[2] << " )" << endl; + } + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Volume information for output to file + **/ +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren) { + if ( ! file ) return; + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + file << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) file << ", assembly"; + else { + if ( volume->GetMedium() ) + file << ", medium " << volume->GetMedium()->GetName(); + else file << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + file << endl; + if ( volume->GetNdaughters() && listChildren) { + file << "Contains: "; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) + file << volume->GetNode(iNode)->GetVolume()->GetName() << " "; + file << endl; + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Calculate beam pipe outer radius for a given z + **/ +Double_t BeamPipeRadius(Double_t z) { + if ( z < gkPipeZ2 ) return gkPipeR1; + Double_t slope = (gkPipeR3 - gkPipeR2 ) / (gkPipeZ3 - gkPipeZ2); + return gkPipeR2 + slope * (z - gkPipeZ2); +} +/** ======================================================================= **/ + + + +/** ======================================================================= **/ +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + TGeoBBox* frameVertPillarShp; + + Double_t t = gkFrameThickness/2.; + + // --- Main vertical pillars +// TGeoBBox* frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, gkFrameStep/2., t); // square crossection, along y +// TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); +// frameVertPillarVol->SetLineColor(kGreen); +// frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoTranslation(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2.)); +// frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoTranslation(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkCylindricalFrames) + // TGeoBBox* frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", 0, t, gkFrameStep/2.); // circle crossection, along z + frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", gkCylinderDiaInner/2., gkCylinderDiaOuter/2., gkFrameStep/2.); // circle crossection, along z + else + frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, t, gkFrameStep/2.); // square crossection, along z + TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); + frameVertPillarVol->SetLineColor(kGreen); + + TGeoRotation* xRot90 = new TGeoRotation; + xRot90->RotateX(90.); + frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoCombiTrans(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoCombiTrans(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + + // TGeoRotation* vertRot = new TGeoRotation(name + "_vertpillar_rot_1", 90., 45., -90.); + TGeoRotation* vertRot = new TGeoRotation; + vertRot->RotateX(90.); + vertRot->RotateY(45.); + frameBoxVol->AddNode(frameVertPillarVol, 3, new TGeoCombiTrans(name + "_vertpillar_pos_3", 0., 0., (x-sqrt(2.)*t)/2., vertRot)); + + // --- Small horizontal pillar + // TGeoBBox* frameHorPillarShp = new TGeoBBox(name + "_horpillar_shape", x-2.*t, gkThinFrameThickness/2., gkThinFrameThickness/2.); + // TGeoVolume* frameHorPillarVol = new TGeoVolume(name + "_horpillar", frameHorPillarShp, framesMaterial); + // frameHorPillarVol->SetLineColor(kCyan); + // frameBoxVol->AddNode(frameHorPillarVol, 1, new TGeoTranslation(name + "_horpillar_pos_1", 0., -gkFrameStep/2.+gkThinFrameThickness/2., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkConstructSmallFrames) { + + // --- Small sloping pillars + TGeoPara* frameSlopePillarShp = new TGeoPara(name + "_slopepillar_shape", + (x-2.*t)/TMath::Cos(31.4/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., 31.4, 0., 90.); + TGeoVolume* frameSlopePillarVol = new TGeoVolume(name + "_slopepillar", frameSlopePillarShp, framesMaterial); + frameSlopePillarVol->SetLineColor(kCyan); + TGeoRotation* slopeRot = new TGeoRotation(name + "_slopepillar_rot_1", 0., 0., 31.4); + TGeoRotation* slopeRot2 = new TGeoRotation(name + "_slopepillar_rot_2", 0., 0., -31.4); + TGeoCombiTrans* slopeTrRot = new TGeoCombiTrans(name + "_slopepillar_posrot_1", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot); + TGeoCombiTrans* slopeTrRot2 = new TGeoCombiTrans(name + "_slopepillar_posrot_2", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot2); + + frameBoxVol->AddNode(frameSlopePillarVol, 1, slopeTrRot); + frameBoxVol->AddNodeOverlap(frameSlopePillarVol, 2, slopeTrRot2); + + + Double_t angl = 23.; + // --- Small sub pillar + TGeoPara* frameSubPillarShp = new TGeoPara(name + "_subpillar_shape", + (sqrt(2)*(x/2.-t)-t/2.)/TMath::Cos(angl/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., angl, 0., 90.); + TGeoVolume* frameSubPillarVol = new TGeoVolume(name + "_subpillar", frameSubPillarShp, framesMaterial); + frameSubPillarVol->SetLineColor(kMagenta); + + Double_t posZ = t * (1. - 3. / ( 2.*sqrt(2.) )); + + // one side of X direction + TGeoRotation* subRot1 = new TGeoRotation(name + "_subpillar_rot_1", 90., 45., -90.+angl); + TGeoCombiTrans* subTrRot1 = new TGeoCombiTrans(name + "_subpillar_posrot_1", -(-x/2.+t-t/(2.*sqrt(2.))), 1., posZ, subRot1); + + TGeoRotation* subRot2 = new TGeoRotation(name + "_subpillar_rot_2", 90., -90.-45., -90.+angl); + TGeoCombiTrans* subTrRot2 = new TGeoCombiTrans(name + "_subpillar_posrot_2", -(-x/2.+t-t/(2.*sqrt(2.))), -1., posZ, subRot2); + + // other side of X direction + TGeoRotation* subRot3 = new TGeoRotation(name + "_subpillar_rot_3", 90., 90.+45., -90.+angl); + TGeoCombiTrans* subTrRot3 = new TGeoCombiTrans(name + "_subpillar_posrot_3", -x/2.+t-t/(2.*sqrt(2.)), 1., posZ, subRot3); + + TGeoRotation* subRot4 = new TGeoRotation(name + "_subpillar_rot_4", 90., -45., -90.+angl); + TGeoCombiTrans* subTrRot4 = new TGeoCombiTrans(name + "_subpillar_posrot_4", -x/2.+t-t/(2.*sqrt(2.)), -1., posZ, subRot4); + + frameBoxVol->AddNode(frameSubPillarVol, 1, subTrRot1); + frameBoxVol->AddNode(frameSubPillarVol, 2, subTrRot2); + frameBoxVol->AddNode(frameSubPillarVol, 3, subTrRot3); + frameBoxVol->AddNode(frameSubPillarVol, 4, subTrRot4); + // frameBoxVol->GetShape()->ComputeBBox(); + } + + return frameBoxVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructSmallCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 6., 7.6, 6., 6.04, 0., 180.); +// TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + Double_t radius = 3.0; + Double_t thickness = 0.04; // 0.4 mm +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 3., 3.2, 3., 3.2, 0., 180.); + TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, radius, radius+thickness, radius, radius+thickness, 0., 180.); + TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + TGeoCombiTrans* M = new TGeoCombiTrans ("M"); + M->RotateX (45.); + M->SetDy (-5.575); + M->SetDz (6.935); + M->RegisterYourself(); + + TGeoShape* coneShp = new TGeoCompositeShape ("Cone_shp", "A-B:M"); + TGeoVolume* coneVol = new TGeoVolume ("Cone", coneShp, framesMaterial); + coneVol->SetLineColor(kGreen); +// coneVol->RegisterYourself(); + +// // --- Inner cone +// Double_t thickness = 0.02; +// Double_t thickness2 = 0.022; +// // TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); +// TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 3.+thickness, 4.6-thickness2, 2.99+thickness, 3.05-thickness2, 0., 180.); +// +// TGeoCombiTrans* M2 = new TGeoCombiTrans ("M2"); +// M2->RotateX (45.); +// M2->SetDy (-5.575+thickness*sqrt(2.)); +// M2->SetDz (6.935); +// M2->RegisterYourself(); +// +// TGeoShape* coneShp2 = new TGeoCompositeShape ("Cone2_shp", "A2-B:M2"); +// TGeoVolume* coneVol2 = new TGeoVolume ("Cone2", coneShp2, gStsMedium); +// coneVol2->SetLineColor(kGreen); +//// coneVol2->RegisterYourself(); +// +// coneVol->AddNode(coneVol2, 1); + + return coneVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructBigCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone + TGeoConeSeg* bA = new TGeoConeSeg ("bA", coneDz, 6., 7.6, 6., 6.04, 0., 180.); + TGeoBBox* bB = new TGeoBBox ("bB", 8., 6., 10.); + + TGeoCombiTrans* bM = new TGeoCombiTrans ("bM"); + bM->RotateX (45.); + bM->SetDy (-5.575); + bM->SetDz (6.935); + bM->RegisterYourself(); + + TGeoShape* coneBigShp = new TGeoCompositeShape ("ConeBig_shp", "bA-bB:bM"); + TGeoVolume* coneBigVol = new TGeoVolume ("ConeBig", coneBigShp, framesMaterial); + coneBigVol->SetLineColor(kGreen); +// coneBigVol->RegisterYourself(); + + // --- Inner cone + Double_t thickness = 0.02; + Double_t thickness2 = 0.022; + TGeoConeSeg* bA2 = new TGeoConeSeg ("bA2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); + + TGeoCombiTrans* bM2 = new TGeoCombiTrans ("bM2"); + bM2->RotateX (45.); + bM2->SetDy (-5.575+thickness*sqrt(2.)); + bM2->SetDz (6.935); + bM2->RegisterYourself(); + + TGeoShape* coneBigShp2 = new TGeoCompositeShape ("ConeBig2_shp", "bA2-bB:bM2"); + TGeoVolume* coneBigVol2 = new TGeoVolume ("ConeBig2", coneBigShp2, gStsMedium); + coneBigVol2->SetLineColor(kGreen); +// coneBigVol2->RegisterYourself(); + + coneBigVol->AddNode(coneBigVol2, 1); + + return coneBigVol; +} + +/** ======================================================================= **/ diff --git a/macro/sts/geometry/create_stsgeo_v19w.C b/macro/sts/geometry/create_stsgeo_v19w.C new file mode 100644 index 0000000000000000000000000000000000000000..9215297d20de5da1f40517a173c113b298b09234 --- /dev/null +++ b/macro/sts/geometry/create_stsgeo_v19w.C @@ -0,0 +1,2408 @@ +/****************************************************************************** + ** Creation of STS geometry in ROOT format (TGeo). + ** + ** @file create_stsgeo_v19w.C + ** @author Volker Friese <v.friese@gsi.de> + ** @since 15 June 2012 + ** @date 09.05.2014 + ** @author Tomas Balog <T.Balog@gsi.de> + ** + ** v19w: based on v19t: do not rotate any sensor (0 degrees around y) + ** v19v: based on v19t: rotate all sensors by 180 degrees around y + ** v19u: rotate the opposite sensors as compared to v19t + ** v19t: application of pp-nn sensor orientation to v19r (as tested in v19s) + ** v19s: introducing pp-nn sensor orientation - only for visualisation using blue and red surfaces + ** v19r: bugfix of v19q - align all halfladders + ** v19q: based on v19l - align ladders to virtual plane in station center, closing the gaps in z + ** v19p: based on v19k - parameters : delta Z prime = 0.70 cm - delta Z pitch = 0.20 cm + ** v19o: based on v19k - parameters : delta Z prime = 0.30 cm - delta Z pitch = 0.20 cm + ** v19n: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.20 cm (bug fix of v19m) + ** v19m: based on v19k - parameters : delta Z prime = 0.55 cm - delta Z pitch = 0.20 cm (bug) + ** v19l: based on v19k - parameters : delta Z prime = 0.50 cm - delta Z pitch = 0.15 cm + ** v19k: ladders on upstream side of units get upper half ladders installed first, + ** ladders on downstream side of units get lower half ladders installed first, + ** this saves 1.5 mm space in z per station, 12 mm in total (LadderType went from 3 to 4 digits) + ** parameters : delta Z prime = 1.00 cm - delta Z pitch = 0.15 cm + ** v19j: use overlap and distance parameters from CAD model + ** v19h: put STS stations from v19d at z-positions = 260; 365; 470; 575; 680; 785; 890; 995 mm + ** v19g: place a box with services around v19e + ** v19f: place a box with services around v19d + ** v19e: increase spacing between stations by +10 mm from 100 mm + ** v19d: increase spacing between stations by + 5 mm from 100 mm + ** v19c: drop station 8 and increase spacing between remaining 7 stations from 10 cm to 12 c + ** v19b: introduce FEB orientation in ladder numbering (LadderType went from 2 to 3 digits) + ** v19a: import passive materials from gdml file + ** extend CF ladder structures and cables towards FEE plane + ** change CF ladder frame shape + ** v18d: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu (based on v18b) + ** v18c: fixed cut-out windows in cooling plates, improve the box shape/materials + ** v18b: increases thickness of sensors within a 7.5 degree cone from 300 mu to 400 mu + ** v18a: adds 9 cooling/holding plates and a box around the setup + ** v16g: v16g is the new standard geometry from November 2017 + ** v16g: switch from stations to units - left / right ("Unit01L", "Unit01R") + ** v16f: switch from stations to units + ** - split in upstream / downstream and left / right parts + ** - named Unit0xUR, Unit0xUL, Unit0xDR, Unit0xDL + ** v16e: switch from stations to units - upstream / downstream ("Unit01U", "Unit01D") + ** v16d: skip keeping volumes of sts and stations + ** v16c: like v16b, but senors of ladders beampipe next to beampipe + ** shifted closer to the pipe, like in the CAD model + ** v16b: like v16a, but yellow sensors removed + ** v16a: derived from v15c (no cones), but with sensor types renamed: + ** 2 -> 1, 3 -> 2, 4 -> 3, 5 -> 4, 1 -> 5 + ** + ** v15c: as v15b without cones + ** v15b: introduce modified carbon ladders from v13z + ** v15a: with flipped ladder orientation for stations 0,2,4,6 to match CAD design + ** + ** TODO: + ** + ** DONE: + ** v15b - use carbon macaroni as ladder support + ** v15b - introduce a small gap between lowest sensor and carbon ladder + ** v15b - build small cones for the first 2 stations + ** v15b - within a station the ladders of adjacent units should not touch eachother - set gkLadderGapZ to 10 mm + ** v15b - for all ladders set an even number of ladder elements + ** v15b - z offset of cones to ladders should not be 0.3 by default, but 0.26 + ** v15b - within a station the ladders should be aligned in z, defined either by the unit or the ladder with most sensors + ** v15b - get rid of cone overlap in stations 7 and 8 - done by adapting rHole size + ** + ** The geometry hierarachy is: + ** + ** 1. Sensors (see function CreateSensors) + ** The sensors are the active volumes and the lowest geometry level. + ** They are built as TGeoVolumes, shape box, material silicon. + ** x size is determined by strip pitch 58 mu and 1024 strips + ** plus guard ring of 1.3 mm at each border -> 6.1992 cm. + ** Sensor type 1 is half of that (3.0792 cm). + ** y size is determined by strip length (2.2 / 4.2 / 6.3 cm) plus + ** guard ring of 1.3 mm at top and bottom -> 2.46 / 4.46 / 6.46 cm. + ** z size is a parameter, to be set by gkSensorThickness. + ** + ** 2. Sectors (see function CreateSectors) + ** Sectors consist of several chained sensors. These are arranged + ** vertically on top of each other with a gap to be set by + ** gkChainGapY. Sectors are constructed as TGeoVolumeAssembly. + ** The sectors are auxiliary volumes used for proper placement + ** of the sensor(s) in the module. They do not show up in the + ** final geometry. + ** + ** 3. Modules (see function ConstructModule) + ** A module is a readout unit, consisting of one sensor or + ** a chain of sensors (see sector) and a cable. + ** The cable extends from the top of the sector vertically to the + ** top of the halfladder the module is placed in. The cable and module + ** volume thus depend on the vertical position of the sector in + ** the halfladder. The cables consist of silicon with a thickness to be + ** set by gkCableThickness. + ** Modules are constructed as TGeoVolume, shape box, medium gStsMedium. + ** The module construction can be switched off (gkConstructCables) + ** to reproduce older geometries. + ** + ** 4. Halfladders (see function ConstructHalfLadder) + ** A halfladder is a vertical assembly of several modules. The modules + ** are placed vertically such that their sectors overlap by + ** gkSectorOverlapY. They are displaced in z direction to allow for the + ** overlap in y by gkSectorGapZ. + ** The horizontal placement of modules in the halfladder can be choosen + ** to left aligned or right aligned, which only matters if sensors of + ** different x size are involved. + ** Halfladders are constructed as TGeoVolumeAssembly. + ** + ** 5. Ladders (see function CreateLadders and ConstructLadder) + ** A ladder is a vertical assembly of two halfladders, and is such the + ** vertical building block of a station. The second (bottom) half ladder + ** is rotated upside down. The vertical arrangement is such that the + ** inner sectors of the two halfladders have the overlap gkSectorOverlapY + ** (function CreateLadder) or that there is a vertical gap for the beam + ** hole (function CreateLadderWithGap). + ** Ladders are constructed as TGeoVolumeAssembly. + ** + ** 6. Stations (see function ConstructStation) + ** A station represents one layer of the STS geometry: one measurement + ** at (approximately) a given z position. It consist of several ladders + ** arranged horizontally to cover the acceptance. + ** The ladders are arranged such that there is a horizontal overlap + ** between neighbouring ladders (gkLadderOverLapX) and a vertical gap + ** to allow for this overlap (gkLadderGapZ). Each second ladder is + ** rotated around its y axis to face away from or into the beam. + ** Stations are constructed as TGeoVolumes, shape box minus tube (for + ** the beam hole), material gStsMedium. + ** + ** 7. STS + ** The STS is a volume hosting the entire detectors system. It consists + ** of several stations located at different z positions. + ** The STS is constructed as TGeoVolume, shape box minus cone (for the + ** beam pipe), material gStsMedium. The size of the box is computed to + ** enclose all stations. + *****************************************************************************/ + + +// Remark: With the proper steering variables, this should exactly reproduce +// the geometry version v11b of A. Kotynia's described in the ASCII format. +// The only exception is a minimal difference in the z position of the +// sectors/sensors. This is because of ladder types 2 and 4 containing the half +// sensors around the beam hole (stations 1,2 and 3). In v11b, the two ladders +// covering the beam hole cannot be transformed into each other by rotations, +// but only by a reflection. This means they are constructionally different. +// To avoid introducing another two ladder types, the difference in z position +// was accepted. + + +// Differences to v12: +// gkChainGap reduced from 1 mm to 0 +// gkCableThickness increased from 100 mum to 200 mum (2 cables per module) +// gkSectorOverlapY reduced from 3 mm to 2.4 mm +// New sensor types 05 and 06 +// New sector types 07 and 08 +// Re-definiton of ladders (17 types instead of 8) +// Re-definiton of station from new ladders + + +#include <iomanip> +#include <iostream> +#include "TGeoManager.h" + +#include "TGeoTube.h" +#include "TGeoPara.h" +#include "TGeoCone.h" +#include "TGeoTrd2.h" +#include "TGeoCompositeShape.h" +#include "TGeoXtru.h" +#include "TGeoPhysicalNode.h" + +// forward declarations +Int_t CreateSensors(); +Int_t CreateSectors(); +Int_t CreateLadders(); +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength); +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY, + Int_t start); +TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ, + Double_t pitchZ, + Int_t nSectors); +TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation); +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile); +void PostProcessGdml(TGeoVolume* gdmlTop); +void CheckVolume(TGeoVolume* volume); +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren = kTRUE); +Double_t BeamPipeRadius(Double_t z); +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x); +TGeoVolume* ConstructSmallCone(Double_t coneDz); +TGeoVolume* ConstructBigCone(Double_t coneDz); + +// ------------- Version highlight ----------------------------------- + +const std::string gVersionHighlight = R"( +Summary: + This version adds passive materials imported from GDML model to the STS geometry: + * Taken from and largely correspond to mechanical CAD drawings of the detector + * Thermal insulation box: + - made out of carbon sandwitch panel (2mm carbon fiber sheet + layer of carbon foam + 2mm carbon fiber sheet) + - front window of complex shape with interface to MVD / target chamber + - back window with large aperture (2000 x 1200 mm) square cut into carbon foam + * Structural units: + - made of 2 complex shape aluminum C-Frames, 15mm thick + - placed at 25, 35, ... ,105 cm absolute Z + - contain front-end and power distribution boxes with equivalent X_0 values + + Scripted geometry tweaks: + * Ladders and cables are extended towards the read-out planes having same lengths in respective rows + * Adjusted form and shape of carbon ladder structures from L-type to X-type + * Reduced verbosity of this file + + Sensor arrangement is the same as in version v16g + + !! Important for this version is the discrepancy from the mechanical CAD w.r.t. front wall. + The square window was replaced by a round one to avoid overlaps with present beam pipe designs, e.g. pipe_v16b_1e +)"; + +// ------------- Steering variables ----------------------------------- + +// ---> Horizontal width of sensors [cm] +const Double_t gkSensorSizeX = 6.2; // was 6.2092; // 6.2 - Oleg CAD 15/05/2020 + +// ---> Thickness of sensors [cm] +const Double_t gkSensorThickness = 0.03; + +// ---> Vertical gap between chained sensors [cm] +const Double_t gkChainGapY = 0.00; + +// ---> Thickness of cables [cm] +const Double_t gkCableThickness = 0.02; + +// ---> Horizontal overlap of neighbouring ladders [cm] +const Double_t gkLadderOverlapX = 0.25; // delta X - Oleg CAD 14/05/2020 + +// ---> Vertical overlap of neighbouring sectors in a ladder [cm] +const Double_t gkSectorOverlapY = 0.46; // delta Y - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring sectors in a ladder [cm] +const Double_t gkSectorGapZ = 0.12; // gap + thickness = pitch // delta Z pitch = 0.15 - Oleg CAD 14/05/2020 + +// ---> Gap in z between neighbouring ladders [cm] +const Double_t gkLadderGapZ = 0.50 - 0.15; // for asym // 0.5 for sym // delta Z prime + +// ---> Gap in z between lowest sector to carbon support structure [cm] +const Double_t gkSectorGapZFrame = 0.280 - 0.025; // Oleg CAD 05/05/2020 // there is a 2.8 mm gap between the bottom side of the sensor and the top ledge of the carbon ladder + +// ---> Switch to construct / not to construct readout cables +const Bool_t gkConstructCables = kTRUE; + +// ---> Switch to construct / not to construct frames +const Bool_t gkConstructCones = kFALSE; // kTRUE; // switch this false by default for v15c and v16x +const Bool_t gkConstructFrames = kTRUE; // kFALSE; // switch this true by default for v15c and v16x +const Bool_t gkConstructSmallFrames = kTRUE; // kFALSE; +const Bool_t gkCylindricalFrames = kTRUE; // kFALSE; + +// ---> Size of the frame +const Double_t gkFrameThickness = 0.2; +const Double_t gkThinFrameThickness = 0.05; +const Double_t gkFrameStep = 4.0; // size of frame cell along y direction + +const Double_t gkCylinderDiaInner = 0.07; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) +const Double_t gkCylinderDiaOuter = 0.15; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015) + +// ---> Switch to import / not to import the Passive materials from GDML file +//const Bool_t gkImportPassive = kTRUE; +const Bool_t gkImportPassive = kFALSE; + +// ---------------------------------------------------------------------------- + + +// -------------- Parameters of beam pipe in the STS region -------------- +// ---> Needed to compute stations and STS such as to avoid overlaps +const Double_t gkPipeZ1 = 22.0; +const Double_t gkPipeR1 = 1.8; +const Double_t gkPipeZ2 = 50.0; +const Double_t gkPipeR2 = 1.8; +const Double_t gkPipeZ3 = 125.0; +const Double_t gkPipeR3 = 5.5; + +//DE const Double_t gkPipeZ1 = 27.0; +//DE const Double_t gkPipeR1 = 1.05; +//DE const Double_t gkPipeZ2 = 160.0; +//DE const Double_t gkPipeR2 = 3.25; +// ---------------------------------------------------------------------------- + +//TString unitName[16] = // names of units for v16e +// { "Unit00D", +// "Unit01U", "Unit01D", +// "Unit02U", "Unit02D", +// "Unit03U", "Unit03D", +// "Unit04U", "Unit04D", +// "Unit05U", "Unit05D", +// "Unit06U", "Unit06D", +// "Unit07U", "Unit07D", +// "Unit08U" }; + +//TString unitName[32] = // names of units for v16f +// { "Unit00DR", "Unit00DL", +// "Unit01UR", "Unit01UL", "Unit01DR", "Unit01DL", +// "Unit02UR", "Unit02UL", "Unit02DR", "Unit02DL", +// "Unit03UR", "Unit03UL", "Unit03DR", "Unit03DL", +// "Unit04UR", "Unit04UL", "Unit04DR", "Unit04DL", +// "Unit05UR", "Unit05UL", "Unit05DR", "Unit05DL", +// "Unit06UR", "Unit06UL", "Unit06DR", "Unit06DL", +// "Unit07UR", "Unit07UL", "Unit07DR", "Unit07DL", +// "Unit08UR", "Unit08UL" }; + +TString unitName[32] = // names of units for v16g - while merging D and U parts + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", "Unit01R", "Unit01L", + "Unit02R", "Unit02L", "Unit02R", "Unit02L", + "Unit03R", "Unit03L", "Unit03R", "Unit03L", + "Unit04R", "Unit04L", "Unit04R", "Unit04L", + "Unit05R", "Unit05L", "Unit05R", "Unit05L", + "Unit06R", "Unit06L", "Unit06R", "Unit06L", + "Unit07R", "Unit07L", "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +TString unitName18[18] = // names of units for v16g + { "Unit00R", "Unit00L", + "Unit01R", "Unit01L", + "Unit02R", "Unit02L", + "Unit03R", "Unit03L", + "Unit04R", "Unit04L", + "Unit05R", "Unit05L", + "Unit06R", "Unit06L", + "Unit07R", "Unit07L", + "Unit08R", "Unit08L" }; + +// ------------- Other global variables ----------------------------------- +// ---> STS medium (for every volume except silicon) +TGeoMedium* gStsMedium = NULL; // will be set later +// ---> TGeoManager (too lazy to write out 'Manager' all the time +TGeoManager* gGeoMan = NULL; // will be set later +// ---------------------------------------------------------------------------- + + + + +// ============================================================================ +// ====== Main function ===== +// ============================================================================ + +void create_stsgeo_v19w(const char* geoTag="v19w") +{ + + // ------- Geometry file name (output) ---------------------------------- + TString geoFileName = "sts_"; + geoFileName = geoFileName + geoTag + ".geo.root"; + // -------------------------------------------------------------------------- + + + // ------- Open info file ----------------------------------------------- + TString infoFileName = geoFileName; + infoFileName.ReplaceAll("root", "info"); + fstream infoFile; + infoFile.open(infoFileName.Data(), fstream::out); + infoFile << "STS geometry created with create_stsgeo_v19w.C" << endl; + infoFile << gVersionHighlight << endl; + infoFile << "Global variables: " << endl; + infoFile << "Sensor thickness = " << gkSensorThickness << " cm" << endl; + infoFile << "Vertical gap in sensor chain = " + << gkChainGapY << " cm" << endl; + infoFile << "Vertical overlap of sensors = " + << gkSectorOverlapY << " cm" << endl; + infoFile << "Gap in z between neighbour sensors = " + << gkSectorGapZ << " cm" << endl; + infoFile << "Horizontal overlap of sensors = " + << gkLadderOverlapX << " cm" << endl; + infoFile << "Gap in z between neighbour ladders = " + << gkLadderGapZ << " cm" << endl; + if ( gkConstructCables ) + infoFile << "Cable thickness = " << gkCableThickness << " cm" << endl; + else + infoFile << "No cables" << endl; + infoFile << endl; + infoFile << "Beam pipe: R1 = " << gkPipeR1 << " cm at z = " + << gkPipeZ1 << " cm" << endl; + infoFile << "Beam pipe: R2 = " << gkPipeR2 << " cm at z = " + << gkPipeZ2 << " cm" << endl; + infoFile << "Beam pipe: R3 = " << gkPipeR3 << " cm at z = " + << gkPipeZ3 << " cm" << endl; + // -------------------------------------------------------------------------- + + + // ------- Load media from media file ----------------------------------- + FairGeoLoader* geoLoad = new FairGeoLoader("TGeo","FairGeoLoader"); + FairGeoInterface* geoFace = geoLoad->getGeoInterface(); + TString geoPath = gSystem->Getenv("VMCWORKDIR"); + TString medFile = geoPath + "/geometry/media.geo"; + geoFace->setMediaFile(medFile); + geoFace->readMedia(); + gGeoMan = gGeoManager; + // -------------------------------------------------------------------------- + + + // ----------------- Get and create the required media ----------------- + FairGeoMedia* geoMedia = geoFace->getMedia(); + FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder(); + + // ---> air + FairGeoMedium* mAir = geoMedia->getMedium("air"); + if ( ! mAir ) Fatal("Main", "FairMedium air not found"); + geoBuild->createMedium(mAir); + TGeoMedium* air = gGeoMan->GetMedium("air"); + if ( ! air ) Fatal("Main", "Medium air not found"); + + // ---> silicon + FairGeoMedium* mSilicon = geoMedia->getMedium("silicon"); + if ( ! mSilicon ) Fatal("Main", "FairMedium silicon not found"); + geoBuild->createMedium(mSilicon); + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + if ( ! silicon ) Fatal("Main", "Medium silicon not found"); + + // ---> carbon + FairGeoMedium* mCarbon = geoMedia->getMedium("carbon"); + if ( ! mCarbon ) Fatal("Main", "FairMedium carbon not found"); + geoBuild->createMedium(mCarbon); + TGeoMedium* carbon = gGeoMan->GetMedium("carbon"); + if ( ! carbon ) Fatal("Main", "Medium carbon not found"); + + // ---> STSBoxCarbonFoam + FairGeoMedium* mSTSBoxCarbonFoam = geoMedia->getMedium("STSBoxCarbonFoam"); + if ( ! mSTSBoxCarbonFoam ) Fatal("Main", "FairMedium STSBoxCarbonFoam not found"); + geoBuild->createMedium(mSTSBoxCarbonFoam); + TGeoMedium* STSBoxCarbonFoam = gGeoMan->GetMedium("STSBoxCarbonFoam"); + if ( ! STSBoxCarbonFoam ) Fatal("Main", "Medium STSBoxCarbonFoam not found"); + + // ---> STSBoxCarbonFibre + FairGeoMedium* mSTSBoxCarbonFibre = geoMedia->getMedium("STSBoxCarbonFibre"); + if ( ! mSTSBoxCarbonFibre ) Fatal("Main", "FairMedium STSBoxCarbonFibre not found"); + geoBuild->createMedium(mSTSBoxCarbonFibre); + TGeoMedium* STSBoxCarbonFibre = gGeoMan->GetMedium("STSBoxCarbonFibre"); + if ( ! STSBoxCarbonFibre ) Fatal("Main", "Medium STSBoxCarbonFibre not found"); + + // ---> STScable + FairGeoMedium* mSTScable = geoMedia->getMedium("STScable"); + if ( ! mSTScable ) Fatal("Main", "FairMedium STScable not found"); + geoBuild->createMedium(mSTScable); + TGeoMedium* STScable = gGeoMan->GetMedium("STScable"); + if ( ! STScable ) Fatal("Main", "Medium STScable not found"); + + // ---> Aluminium + FairGeoMedium* mAluminium = geoMedia->getMedium("aluminium"); + if ( ! mAluminium ) Fatal("Main", "FairMedium aluminium not found"); + geoBuild->createMedium(mAluminium); + TGeoMedium* aluminium = gGeoMan->GetMedium("aluminium"); + if ( ! aluminium ) Fatal("Main", "Medium aluminium not found"); + + // --- + gStsMedium = air; + // -------------------------------------------------------------------------- + + + // -------------- Create geometry and top volume ------------------------- + gGeoMan = (TGeoManager*)gROOT->FindObject("FAIRGeom"); +// gGeoMan->SetName("STSgeom"); + TGeoVolume* top = new TGeoVolumeAssembly("top"); +// TGeoBBox* topbox= new TGeoBBox("", 120., 120., 120.); +// TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air")); + gGeoMan->SetTopVolume(top); + // -------------------------------------------------------------------------- + + + // -------------- Create media ------------------------------------------ + /* + cout << endl; + cout << "===> Creating media...."; + cout << CreateMedia(); + cout << " media created" << endl; + TList* media = gGeoMan->GetListOfMedia(); + for (Int_t iMedium = 0; iMedium < media->GetSize(); iMedium++ ) { + cout << "Medium " << iMedium << ": " + << ((TGeoMedium*) media->At(iMedium))->GetName() << endl; + } + gStsMedium = gGeoMan->GetMedium("air"); + if ( ! gStsMedium ) Fatal("Main", "medium sts_air not found"); + */ + // -------------------------------------------------------------------------- + + + // --------------- Create sensors --------------------------------------- + cout << endl << endl; + cout << "===> Creating sensors...." << endl << endl; + infoFile << endl << "Sensors: " << endl; + Int_t nSensors = CreateSensors(); + for (Int_t iSensor = 1; iSensor <= nSensors; iSensor++) { + TString name = Form("Sensor%02d",iSensor); + TGeoVolume* sensor = gGeoMan->GetVolume(name); + + // add color to sensors + if (iSensor == 1) + sensor->SetLineColor(kRed); + if (iSensor == 2) + sensor->SetLineColor(kGreen); + if (iSensor == 3) + sensor->SetLineColor(kBlue); + if (iSensor == 4) + sensor->SetLineColor(kAzure); + if (iSensor == 5) + sensor->SetLineColor(kYellow); + if (iSensor == 6) + sensor->SetLineColor(kYellow); + if (iSensor == 7) + sensor->SetLineColor(kYellow); + + CheckVolume(sensor); + CheckVolume(sensor, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create sectors -------------------------------------- + cout << endl << endl; + cout << "===> Creating sectors...." << endl; + // infoFile << endl << "Sectors: " << endl; + Int_t nSectors = CreateSectors(); + for (Int_t iSector = 1; iSector <= nSectors; iSector++) { + // cout << endl; + TString name = Form("Sector%02d", iSector); + TGeoVolume* sector = gGeoMan->GetVolume(name); + CheckVolume(sector); + // CheckVolume(sector, infoFile); + } + // -------------------------------------------------------------------------- + + + // ---------------- Create ladders -------------------------------------- + cout << endl << endl; + cout << "===> Creating ladders...." << endl; + infoFile << endl << "Ladders:" << endl; + + TString name = ""; + TGeoVolume* ladder; + + + Int_t nLadders = CreateLadders(); + + for (Int_t iLadder = 1; iLadder <= nLadders; iLadder++) { + cout << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType0%02d", iLadder); // v19b + name = Form("LadderType00%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF1: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + // name = Form("LadderType1%02d", iLadder); // v19b + name = Form("LadderType01%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF2: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType10%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF3: ladder name: " << name << endl << endl; + + // name = Form("LadderType%02d", iLadder); // v19a + name = Form("LadderType11%02d", iLadder); // v19k + ladder = gGeoMan->GetVolume(name); + CheckVolume(ladder); + CheckVolume(ladder, infoFile, kFALSE); + + cout << "DF4: ladder name: " << name << endl << endl; + } + // -------------------------------------------------------------------------- + + + // ---------------- Create cones ---------------------------------------- + Double_t coneDz = 1.64; + TGeoVolume* coneSmallVolum = ConstructSmallCone(coneDz); + if (!coneSmallVolum) Fatal("ConstructSmallCone", "Volume Cone not found"); + TGeoVolume* coneBigVolum = ConstructBigCone(coneDz); + if (!coneBigVolum) Fatal("ConstructBigCone", "Volume Cone not found"); + // -------------------------------------------------------------------------- + + + // ---------------- Create stations ------------------------------------- + cout << endl << endl; + cout << "===> Creating stations...." << endl; + infoFile << endl << "Stations: " << endl; + Int_t angle = 0; + nLadders = 0; + Int_t ladderTypes[16]; // there are max 16 ladders in one layer + TGeoTranslation* statTrans = NULL; + + TGeoVolume *myunit[32]; // units + +// Int_t statPos[8] = { 30, 40, 50, 60, 70, 80, 90, 100 }; // z positions of stations +// Int_t statPos[16] = { 28, 32, 38, 42, 48, 52, 58, 62, +// 68, 72, 78, 82, 88, 92, 98,102 }; // z positions of units +// Int_t statPos[16] = { 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units +// Int_t statPos18[18] = { 30, 30, // expanded for placement of Unit00 +// 30, 30, 40, 40, 50, 50, 60, 60, +// 70, 70, 80, 80, 90, 90, 100, 100 }; // z positions of units + // v19h + Double_t statPos[16] = { 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of units + Double_t statPos18[18] = { 26.0, 26.0, // expanded for placement of Unit00 + 26.0, 26.0, 36.5, 36.5, 47.0, 47.0, 57.5, 57.5, + 68.0, 68.0, 78.5, 78.5, 89.0, 89.0, 99.5, 99.5 }; // z positions of unit + +// // v19d +// Double_t statPos[16] = { 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units +// Double_t statPos18[18] = { 30.0, 30.0, // expanded for placement of Unit00 +// 30.0, 30.0, 40.5, 40.5, 51.0, 51.0, 61.5, 61.5, +// 72.0, 72.0, 82.5, 82.5, 93.0, 93.0, 103.5, 103.5 }; // z positions of units + +////Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.9 , 3.7 , 3.7 , 4.2 , 4.2 }; // size of cutouts in stations +// Double_t rHole[8] = { 2.0, 2.0, 2.0, 2.43, 3.04, 3.35, 3.96, 4.2 }; // size of cutouts in stations, derived from gapXYZ[x][1]/2 + + Int_t cone_size[8] = { 0, 0, 0, 1, 1, 1, 1, 1 }; // size of cones: 0 = small, 1 = large + + Double_t cone_offset[2] = { 0.305, 0.285 }; + +// Int_t allLadderTypes[8][16]= +// { { -1, -1, -1, -1, 10, 109, 9, 101, 1, 109, 9, 110, -1, -1, -1, -1 }, // station 1 +// { -1, -1, 111, 10, 110, 9, 109, 2, 102, 9, 109, 10, 110, 11, -1, -1 }, // station 2 +// { -1, -1, 14, 113, 12, 112, 12, 103, 3, 112, 12, 112, 13, 114, -1, -1 }, // station 3 +// { -1, 15, 114, 13, 112, 12, 112, 4, 104, 12, 112, 12, 113, 14, 115, -1 }, // station 4 +// { -1, 119, 18, 117, 17, 116, 16, 105, 5, 116, 16, 117, 17, 118, 19, -1 }, // station 5 +// { -1, 19, 118, 17, 117, 16, 116, 6, 106, 16, 116, 17, 117, 18, 119, -1 }, // station 6 +// { 21, 119, 18, 120, 20, 120, 20, 107, 7, 120, 20, 120, 20, 118, 19, 121 }, // station 7 +// { 119, 17, 123, 22, 122, 22, 122, 8, 108, 22, 122, 22, 122, 23, 117, 19 } }; // station 8 + +//============================================================================================== + +// explanation: type xyzz +// where x = carbon ladder orientation +// where y = FEB box orientation +// where zz = sensor arrangement on ladder +// with FEB orientation - v19b + Int_t allUnitTypes[16][16]= + { { -1, -1, -1, -1, 10, 0, 9, 0, 101, 0, 109, 0, -1, -1, -1, -1 }, // unit00D Station01 00 + { -1, -1, -1, -1, 0, 1109, 0, 1101, 0, 1009, 0, 1010, -1, -1, -1, -1 }, // unit01U Station01 01 + + { -1, -1, 0, 10, 0, 9, 0, 2, 0, 109, 0, 110, 0, 111, -1, -1 }, // unit01D Station02 02 + { -1, -1, 1111, 0, 1110, 0, 1109, 0, 1002, 0, 1009, 0, 1010, 0, -1, -1 }, // unit02U Station02 03 + + { -1, -1, 14, 0, 12, 0, 12, 0, 103, 0, 112, 0, 113, 0, -1, -1 }, // unit02D Station03 04 + { -1, -1, 0, 1113, 0, 1112, 0, 1103, 0, 1012, 0, 1012, 0, 1014, -1, -1 }, // unit03U Station03 05 + + { -1, 15, 0, 13, 0, 12, 0, 4, 0, 112, 0, 112, 0, 114, 0, -1 }, // unit03D Station04 06 + { -1, 0, 1114, 0, 1112, 0, 1112, 0, 1004, 0, 1012, 0, 1013, 0, 1015, -1 }, // unit04U Station04 07 + + { -1, 0, 18, 0, 17, 0, 16, 0, 105, 0, 116, 0, 117, 0, 119, -1 }, // unit04D Station05 08 + { -1, 1119, 0, 1117, 0, 1116, 0, 1105, 0, 1016, 0, 1017, 0, 1018, 0, -1 }, // unit05U Station05 09 + + { -1, 19, 0, 17, 0, 16, 0, 6, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05D Station06 10 + { -1, 0, 1118, 0, 1117, 0, 1116, 0, 1006, 0, 1016, 0, 1017, 0, 1019, -1 }, // unit06U Station06 11 + + { 21, 0, 25, 0, 20, 0, 20, 0, 107, 0, 120, 0, 120, 0, 127, 0 }, // unit06D Station07 12 + { 0, 1127, 0, 1120, 0, 1120, 0, 1107, 0, 1020, 0, 1020, 0, 1025, 0, 1021 }, // unit07U Station07 13 + + { 0, 24, 0, 22, 0, 22, 0, 8, 0, 122, 0, 122, 0, 123, 0, 126 }, // unit07D Station08 14 + { 1126, 0, 1123, 0, 1122, 0, 1122, 0, 1008, 0, 1022, 0, 1022, 0, 1024, 0 } }; // unit08U Station08 15 + +//============================================================================================== + +// without FEB orientation - v19a +// v19a Int_t allUnitTypes[16][16]= +// v19a { { -1, -1, -1, -1, 10, 0, 9, 0, 1, 0, 9, 0, -1, -1, -1, -1 }, // unit00D Station01 00 +// v19a { -1, -1, -1, -1, 0, 109, 0, 101, 0, 109, 0, 110, -1, -1, -1, -1 }, // unit01U Station01 01 +// v19a { -1, -1, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, -1, -1 }, // unit01D Station02 02 +// v19a { -1, -1, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, -1, -1 }, // unit02U Station02 03 +// v19a { -1, -1, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, -1, -1 }, // unit02D Station03 04 +// v19a { -1, -1, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, -1, -1 }, // unit03U Station03 05 +// v19a { -1, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, -1 }, // unit03D Station04 06 +// v19a { -1, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, -1 }, // unit04U Station04 07 +// v19a { -1, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, -1 }, // unit04D Station05 08 +// v19a { -1, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, -1 }, // unit05U Station05 09 +// v19a { -1, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, -1 }, // unit05D Station06 10 +// v19a { -1, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, -1 }, // unit06U Station06 11 +// v19a { 21, 0, 25, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 27, 0 }, // unit06D Station07 12 +// v19a { 0, 127, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 125, 0, 121 }, // unit07U Station07 13 +// v19a { 0, 24, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 26 }, // unit07D Station08 14 +// v19a { 126, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 124, 0 } }; // unit08U Station08 15 + + +// unitTypes[0] = { 0, 0, 0, 0, 10, 0, 9, 0, 1, 0, 9, 0, 0, 0, 0, 0 }; // unit 0D +// unitTypes[1] = { 0, 0, 0, 0, 0, 109, 0, 101, 0, 109, 0, 110, 0, 0, 0, 0 }; // unit 1U +// unitTypes[2] = { 0, 0, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, 0, 0 }; // unit 1D +// unitTypes[3] = { 0, 0, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, 0, 0 }; // unit 2U +// unitTypes[4] = { 0, 0, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, 0, 0 }; // unit 2D +// unitTypes[5] = { 0, 0, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, 0, 0 }; // unit 3U +// unitTypes[6] = { 0, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, 0 }; // unit 3D +// unitTypes[7] = { 0, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, 0 }; // unit 4U +// unitTypes[8] = { 0, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, 0 }; // unit 4D +// unitTypes[9] = { 0, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, 0 }; // unit 5U +// unitTypes[10] = { 0, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, 0 }; // unit 5D +// unitTypes[11] = { 0, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, 0 }; // unit 6U +// unitTypes[12] = { 21, 0, 18, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 19, 0 }; // unit 6D +// unitTypes[13] = { 0, 119, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 118, 0, 121 }; // unit 7U +// unitTypes[14] = { 0, 17, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 19 }; // unit 7D +// unitTypes[15] = { 119, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 117, 0 }; // unit 8U + + +// // generate unit +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) +// for (Int_t iLadder = 0; iLadder < 16; iLadder++) +// { +// allUnitTypes[iUnit][iLadder] = 0; +// if ((iUnit % 2 == 0) && (allLadderTypes[iUnit/2][iLadder] < 100)) // if carbon structure is oriented upstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// if ((iUnit % 2 == 1) && (allLadderTypes[iUnit/2][iLadder] >= 100)) // if carbon structure is oriented downstream +// allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit/2][iLadder]; +// } + + + // dump unit + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << "DE unitTypes[" << iUnit << "] = { "; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + { + cout << allUnitTypes[iUnit][iLadder]; + if (iLadder < 15) + cout << ", "; + else + cout << " };"; + } + cout << endl; + } + + + // --- Units 01 - 16 + for (Int_t iUnit = 0; iUnit < 16; iUnit++) + { + cout << endl; + + nLadders = 0; + for (Int_t iLadder = 0; iLadder < 16; iLadder++) + if (allUnitTypes[iUnit][iLadder] >= 0) + { + ladderTypes[nLadders] = allUnitTypes[iUnit][iLadder]; + cout << "DE ladderTypes[" << nLadders << "] = " << allUnitTypes[iUnit][iLadder] << ";" << endl; + nLadders++; + } + myunit[iUnit*2+0] = ConstructUnit(0, iUnit*2+0, nLadders, ladderTypes, iUnit/2+1); + myunit[iUnit*2+1] = ConstructUnit(1, iUnit*2+1, nLadders, ladderTypes, iUnit/2+1); + +// if (gkConstructCones) { +// if (iUnit%2 == 0) +// angle = 90; +// else +// angle = -90; +// +// // upstream +// TGeoRotation* coneRot11 = new TGeoRotation; +// coneRot11->RotateZ(angle); +// coneRot11->RotateY(180); +// TGeoCombiTrans* conePosRot11 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-cone_offset[cone_size[iUnit]]-gkLadderGapZ/2., coneRot11); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 1, conePosRot11); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 1, conePosRot11); +// +// // downstream +// TGeoRotation* coneRot12 = new TGeoRotation; +// coneRot12->RotateZ(angle); +// TGeoCombiTrans* conePosRot12 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+cone_offset[cone_size[iUnit]]+gkLadderGapZ/2., coneRot12); +// if (cone_size[iUnit] == 0) +// myunit[iUnit]->AddNode(coneSmallVolum, 2, conePosRot12); +// else +// myunit[iUnit]->AddNode(coneBigVolum, 2, conePosRot12); +// +// myunit[iUnit]->GetShape()->ComputeBBox(); +// } + +// CheckVolume(myunit[iUnit]); +// CheckVolume(myunit[iUnit], infoFile); + if ((iUnit%2 == 0)||(iUnit == 15)) + { + CheckVolume(myunit[iUnit*2+0]); + CheckVolume(myunit[iUnit*2+0], infoFile); + CheckVolume(myunit[iUnit*2+1]); + CheckVolume(myunit[iUnit*2+1], infoFile); + } + infoFile << "Position z = " << statPos[iUnit] << endl; + } + // -------------------------------------------------------------------------- + + + // --------------- Create STS volume ------------------------------------ + cout << endl << endl; + cout << "===> Creating STS...." << endl; + +// // --- Determine size of STS box +// Double_t stsX = 0.; +// Double_t stsY = 0.; +// Double_t stsZ = 0.; +// Double_t stsBorder = 2*5.; // 5 cm space for carbon ladders on each side +// for (Int_t iStation = 1; iStation<=8; iStation++) { +// TString statName = Form("Station%02d", iStation); +// TGeoVolume* station = gGeoMan->GetVolume(statName); +// TGeoBBox* shape = (TGeoBBox*) station->GetShape(); +// stsX = TMath::Max(stsX, 2.* shape->GetDX() ); +// stsY = TMath::Max(stsY, 2.* shape->GetDY() ); +// cout << "Station " << iStation << ": Y " << stsY << endl; +// } +// // --- Some border around the stations +// stsX += stsBorder; +// stsY += stsBorder; +// stsZ = ( statPos[7] - statPos[0] ) + stsBorder; +// +// // --- Create box around the stations +// new TGeoBBox("stsBox", stsX/2., stsY/2., stsZ/2.); +// cout << "size of STS box: x " << stsX << " - y " << stsY << " - z " << stsZ << endl; +// +// // --- Create cone hosting the beam pipe +// // --- One straight section with constant radius followed by a cone +// Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +// Double_t z2 = gkPipeZ2; +// Double_t z3 = statPos[7] + 0.5 * stsBorder; // end of STS box +// Double_t r1 = BeamPipeRadius(z1); +// Double_t r2 = BeamPipeRadius(z2); +// Double_t r3 = BeamPipeRadius(z3); +// r1 += 0.01; // safety margin +// r2 += 0.01; // safety margin +// r3 += 0.01; // safety margin +// +// cout << endl; +// cout << z1 << " " << r1 << endl; +// cout << z2 << " " << r2 << endl; +// cout << z3 << " " << r3 << endl; +// +// cout << endl; +// cout << "station1 : " << BeamPipeRadius(statPos[0]) << endl; +// cout << "station2 : " << BeamPipeRadius(statPos[1]) << endl; +// cout << "station3 : " << BeamPipeRadius(statPos[2]) << endl; +// cout << "station4 : " << BeamPipeRadius(statPos[3]) << endl; +// cout << "station5 : " << BeamPipeRadius(statPos[4]) << endl; +// cout << "station6 : " << BeamPipeRadius(statPos[5]) << endl; +// cout << "station7 : " << BeamPipeRadius(statPos[6]) << endl; +// cout << "station8 : " << BeamPipeRadius(statPos[7]) << endl; +// +// // TGeoPcon* cutout = new TGeoPcon("stsCone", 0., 360., 3); // 2.*TMath::Pi(), 3); +// // cutout->DefineSection(0, z1, 0., r1); +// // cutout->DefineSection(1, z2, 0., r2); +// // cutout->DefineSection(2, z3, 0., r3); +// new TGeoTrd2("stsCone1", r1, r2, r1, r2, (z2-z1)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans1 = new TGeoTranslation("trans1", 0., 0., -(z3-z1)/2.+(z2-z1)/2.); +// trans1->RegisterYourself(); +// new TGeoTrd2("stsCone2", r2, r3, r2, r3, (z3-z2)/2.+.1); // add .1 in z length for a clean cutout +// TGeoTranslation *trans2 = new TGeoTranslation("trans2", 0., 0., +(z3-z1)/2.-(z3-z2)/2.); +// trans2->RegisterYourself(); +// +////DE Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box +////DE Double_t z2 = statPos[7] + 0.5 * stsBorder; // end of STS box +////DE Double_t slope = (gkPipeR2 - gkPipeR1) / (gkPipeZ2 - gkPipeZ1); +////DE Double_t r1 = gkPipeR1 + slope * (z1 - gkPipeZ1); // at start of STS +////DE Double_t r2 = gkPipeR1 + slope * (z2 - gkPipeZ1); // at end of STS +////DE r1 += 0.1; // safety margin +////DE r2 += 0.1; // safety margin +////DE // new TGeoCone("stsCone", stsZ/2., 0., r1, 0., r2); +////DE new TGeoTrd2("stsCone", r1, r2, r1, r2, stsZ/2.); + + + // // Create holding/cooling plates + // static std::vector< std::vector<Double_t> > plateSizes = { + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 100.0/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 111.5/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // { 177.5/2., 130.0/2., 1.5/2. }, + // }; + + // // 8-vertex cut-outs { minWidth, maxWidth, minHeight, maxHeight } + // static std::vector< std::vector<Double_t> > plateCutOuts = { + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 20.0, 50.0 }, + // { 78.3, 97.5, 17.6, 47.6 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 37.0, 67.0 }, + // { 85.5,105.5, 49.0, 79.0 }, + // { 85.5,115.5, 51.5, 82.8 }, + // { 85.5,115.5, 59.0, 91.4 }, + // { 85.5,115.5, 68.0, 99.0 }, + // }; + + // for (Int_t iPlate = 0; iPlate < 9; iPlate++) { + // Int_t iUnit = iPlate * 2; + // TGeoBBox* outerPlate = new TGeoBBox(Form("outerPlate%02d",iPlate), + // plateSizes[iPlate][0], plateSizes[iPlate][1], plateSizes[iPlate][2]); + + // TGeoBBox* unitShapeR = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+0])->GetShape(); + // TGeoBBox* unitShapeL = (TGeoBBox*) gGeoManager->GetVolume(unitName18[iUnit+1])->GetShape(); + + // Double_t maxDx = (unitShapeR->GetDX() + unitShapeL->GetDX()) / 2.; + // Double_t maxDy = TMath::Max(unitShapeR->GetDY(), unitShapeL->GetDY()); + // cout << maxDy << endl; + + // Double_t* cutOutX = new Double_t[8]; + // Double_t* cutOutY = new Double_t[8]; + + // cutOutX[0] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[0] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[1] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[1] = 1/2. * plateCutOuts[iPlate][3]; + // cutOutX[2] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[2] = 1/2. * plateCutOuts[iPlate][2]; + // cutOutX[3] = 1/2. * plateCutOuts[iPlate][1]; cutOutY[3] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[4] = 1/2. * plateCutOuts[iPlate][0]; cutOutY[4] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[5] = -1/2. * plateCutOuts[iPlate][0]; cutOutY[5] = -1/2. * plateCutOuts[iPlate][3]; + // cutOutX[6] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[6] = -1/2. * plateCutOuts[iPlate][2]; + // cutOutX[7] = -1/2. * plateCutOuts[iPlate][1]; cutOutY[7] = 1/2. * plateCutOuts[iPlate][2]; + + // TGeoXtru* cutOutShape = new TGeoXtru(2); + // cutOutShape->SetName(Form("innerPlate%02d", iPlate)); + // cutOutShape->DefinePolygon(8, cutOutX, cutOutY); + // cutOutShape->DefineSection(0, -1*plateSizes[iPlate][2]-1e-7); + // cutOutShape->DefineSection(1, +1*plateSizes[iPlate][2]+1e-7); + + // TGeoShape* plateShape = new TGeoCompositeShape(Form("PlateShape%02d",iPlate), Form("outerPlate%02d-innerPlate%02d",iPlate,iPlate)); + // TGeoVolume* plate = new TGeoVolume(Form("Plate%02d", iPlate), plateShape, gGeoManager->GetMedium("aluminium")); + // plate->SetLineColor(kRed); + // plate->SetTransparency(65); + // plate->GetShape()->ComputeBBox(); + // } + + // --- Create STS volume + TString stsName = "sts_"; + stsName += geoTag; + +// TGeoShape* stsShape = new TGeoCompositeShape("stsShape", +// "stsBox-stsCone1:trans1-stsCone2:trans2"); +// TGeoVolume* sts = new TGeoVolume(stsName.Data(), stsShape, gStsMedium); + + Double_t stsBorder = 2 * 5.; + + TGeoVolume* sts = new TGeoVolumeAssembly(stsName.Data()); + + // --- Place stations in the STS + Double_t stsPosZ = 0.5 * ( statPos[15] + statPos[0] ); // todo units: update statPos[7] + // cout << "stsPosZ " << stsPosZ << " " << statPos[15] << " " << statPos[0] << "*****" << endl; + +// for (Int_t iUnit = 0; iUnit < 16; iUnit++) { + for (Int_t iUnit = 0; iUnit < 18; iUnit++) { +// for (Int_t iUnit = 0; iUnit < 32; iUnit++) { + TGeoVolume* station = gGeoMan->GetVolume(unitName18[iUnit]); +// Double_t posZ = statPos[iUnit] - stsPosZ; + Double_t posZ = statPos18[iUnit] - stsPosZ; +// Double_t posZ = statPos[iUnit/2] - stsPosZ; + TGeoTranslation* trans = new TGeoTranslation(0., 0., posZ); + sts->AddNode(station, iUnit+1, trans); + sts->GetShape()->ComputeBBox(); + } + + // --- Import passive elements from GDML file + if (gkImportPassive) { + ImportPassive(sts, geoTag, infoFile); + } + + cout << endl; + CheckVolume(sts); + // -------------------------------------------------------------------------- + + + // --------------- Finish ----------------------------------------------- + TGeoTranslation* stsTrans = new TGeoTranslation(0., 0., stsPosZ); + top->AddNode(sts, 1, stsTrans); + top->GetShape()->ComputeBBox(); + cout << endl << endl; + + CheckVolume(top); + cout << endl << endl; + gGeoMan->CloseGeometry(); + gGeoMan->CheckOverlaps(0.0001); + gGeoMan->PrintOverlaps(); + gGeoMan->CheckOverlaps(0.0001, "s"); + gGeoMan->PrintOverlaps(); + gGeoMan->Test(); + + TFile* geoFile = new TFile(geoFileName, "RECREATE"); + top->Write(); + cout << endl; + cout << "Geometry " << top->GetName() << " written to " + << geoFileName << endl; + geoFile->Close(); + + TString geoFileName_ = "sts_"; + geoFileName_ = geoFileName_ + geoTag + "_geo.root"; + + geoFile = new TFile(geoFileName_, "RECREATE"); + gGeoMan->Write(); // use this is you want GeoManager format in the output + geoFile->Close(); + + TString geoFileName__ = "sts_"; + geoFileName_ = geoFileName__ + geoTag + "-geo.root"; + sts->Export(geoFileName_); + + geoFile = new TFile(geoFileName_, "UPDATE"); + stsTrans->Write(); + geoFile->Close(); + + // gGeoManager->FindVolumeFast("LadderType10_CarbonElement")->Draw("ogl"); + top->Draw("ogl"); + gGeoManager->SetVisLevel(8); + + infoFile.close(); + +} +// ============================================================================ +// ====== End of main function ===== +// ============================================================================ + + + + + +// **************************************************************************** +// ***** Definition of media, sensors, sectors and ladders ***** +// ***** ***** +// ***** Decoupled from main function for better readability ***** +// **************************************************************************** + + +/** =========================================================================== + ** Create media + ** + ** Currently created: air, active silicon, passive silion + ** + ** Not used for the time being + **/ +Int_t CreateMedia() { + + Int_t nMedia = 0; + Double_t density = 0.; + + // --- Material air + density = 1.205e-3; // [g/cm^3] + TGeoMixture* matAir = new TGeoMixture("sts_air", 3, density); + matAir->AddElement(14.0067, 7, 0.755); // Nitrogen + matAir->AddElement(15.999, 8, 0.231); // Oxygen + matAir->AddElement(39.948, 18, 0.014); // Argon + + // --- Material silicon + density = 2.33; // [g/cm^3] + TGeoElement* elSi = gGeoMan->GetElementTable()->GetElement(14); + TGeoMaterial* matSi = new TGeoMaterial("matSi", elSi, density); + + + // --- Air (passive) + TGeoMedium* medAir = new TGeoMedium("air", nMedia++, matAir); + medAir->SetParam(0, 0.); // is passive + medAir->SetParam(1, 1.); // is in magnetic field + medAir->SetParam(2, 20.); // max. field [kG] + medAir->SetParam(6, 0.001); // boundary crossing precision [cm] + + + // --- Active silicon for sensors + TGeoMedium* medSiAct = new TGeoMedium("silicon", + nMedia++, matSi); + medSiAct->SetParam(0, 1.); // is active + medSiAct->SetParam(1, 1.); // is in magnetic field + medSiAct->SetParam(2, 20.); // max. field [kG] + medSiAct->SetParam(6, 0.001); // boundary crossing precisison [cm] + + // --- Passive silicon for cables + TGeoMedium* medSiPas = new TGeoMedium("carbon", + nMedia++, matSi); + medSiPas->SetParam(0, 0.); // is passive + medSiPas->SetParam(1, 1.); // is in magnetic field + medSiPas->SetParam(2, 20.); // max. field [kG] + medSiPas->SetParam(6, 0.001); // boundary crossing precisison [cm] + + return nMedia; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sensors + ** + ** Sensors are created as volumes with box shape and active silicon as medium. + ** Four kinds of sensors: 3.2x2.2, 6.2x2.2, 6.2x4.2, 6.2x6.2 + **/ +Int_t CreateSensors() { + + Int_t nSensors = 0; + + Double_t xSize = 0.; + Double_t ySize = 0.; + Double_t zSize = gkSensorThickness; + TGeoMedium* silicon = gGeoMan->GetMedium("silicon"); + + + // --- Sensor type 01: Small sensor (6.2 cm x 2.2 cm) + xSize = gkSensorSizeX; + ySize = 2.2; + TGeoBBox* shape_sensor01 = new TGeoBBox("sensor01", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor01", shape_sensor01, silicon); + nSensors++; + + + // --- Sensor type 02: Medium sensor (6.2 cm x 4.2 cm) + xSize = gkSensorSizeX; + ySize = 4.2; + TGeoBBox* shape_sensor02 = new TGeoBBox("sensor02", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor02", shape_sensor02, silicon); + nSensors++; + + + // --- Sensor type 03: Big sensor (6.2 cm x 6.2 cm) + xSize = gkSensorSizeX; + ySize = 6.2; + TGeoBBox* shape_sensor03 = new TGeoBBox("sensor03", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor03", shape_sensor03, silicon); + nSensors++; + + + // --- Sensor type 04: Big sensor (6.2 cm x 12.4 cm) + xSize = gkSensorSizeX; + ySize = 12.4; + TGeoBBox* shape_sensor04 = new TGeoBBox("sensor04", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor04", shape_sensor04, silicon); + nSensors++; + + + // below are extra small sensors, those are not available in the CAD model + + // --- Sensor Type 05: Half small sensor (4 cm x 2.5 cm) + xSize = 4.0; + ySize = 2.5; + TGeoBBox* shape_sensor05 = new TGeoBBox("sensor05", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor05", shape_sensor05, silicon); + nSensors++; + + + // --- Sensor type 06: Additional "in hole" sensor (3.1 cm x 4.2 cm) + xSize = 3.1; + ySize = 4.2; + TGeoBBox* shape_sensor06 = new TGeoBBox("sensor06", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor06", shape_sensor06, silicon); + nSensors++; + + + // --- Sensor type 07: Mini Medium sensor (1.5 cm x 4.2 cm) + xSize = 1.5; + ySize = 4.2; + TGeoBBox* shape_sensor07 = new TGeoBBox("sensor07", + xSize/2., ySize/2., zSize/2.); + new TGeoVolume("Sensor07", shape_sensor07, silicon); + nSensors++; + + + return nSensors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create sectors + ** + ** A sector is either a single sensor or several chained sensors. + ** It is implemented as TGeoVolumeAssembly. + ** Currently available: + ** - single sensors of type 1 - 4 + ** - two chained sensors of type 4 + ** - three chained sensors of type 4 + **/ +Int_t CreateSectors() { + + Int_t nSectors = 0; + + TGeoVolume* sensor01 = gGeoMan->GetVolume("Sensor01"); + TGeoVolume* sensor02 = gGeoMan->GetVolume("Sensor02"); + TGeoVolume* sensor03 = gGeoMan->GetVolume("Sensor03"); + TGeoVolume* sensor04 = gGeoMan->GetVolume("Sensor04"); + TGeoVolume* sensor05 = gGeoMan->GetVolume("Sensor05"); + TGeoVolume* sensor06 = gGeoMan->GetVolume("Sensor06"); + TGeoVolume* sensor07 = gGeoMan->GetVolume("Sensor07"); + // TGeoBBox* box4 = (TGeoBBox*) sensor04->GetShape(); + + // --- Sector type 1: single sensor of type 1 + TGeoVolumeAssembly* sector01 = new TGeoVolumeAssembly("Sector01"); + sector01->AddNode(sensor01, 1); + sector01->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 2: single sensor of type 2 + TGeoVolumeAssembly* sector02 = new TGeoVolumeAssembly("Sector02"); + sector02->AddNode(sensor02, 1); + sector02->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 3: single sensor of type 3 + TGeoVolumeAssembly* sector03 = new TGeoVolumeAssembly("Sector03"); + sector03->AddNode(sensor03, 1); + sector03->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 4: single sensor of type 4 + TGeoVolumeAssembly* sector04 = new TGeoVolumeAssembly("Sector04"); + sector04->AddNode(sensor04, 1); + sector04->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 5: single sensor of type 5 + TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); + sector05->AddNode(sensor05, 1); + sector05->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 6: single sensor of type 6 + TGeoVolumeAssembly* sector06 = new TGeoVolumeAssembly("Sector06"); + sector06->AddNode(sensor06, 1); + sector06->GetShape()->ComputeBBox(); + nSectors++; + + // --- Sector type 7: single sensor of type 7 + TGeoVolumeAssembly* sector07 = new TGeoVolumeAssembly("Sector07"); + sector07->AddNode(sensor07, 1); + sector07->GetShape()->ComputeBBox(); + nSectors++; + +// // --- Sector type 5: two sensors of type 4 +// TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05"); +// Double_t shift5 = 0.5 * gkChainGapY + box4->GetDY(); +// TGeoTranslation* transD5 = +// new TGeoTranslation("td", 0., -1. * shift5, 0.); +// TGeoTranslation* transU5 = +// new TGeoTranslation("tu", 0., shift5, 0.); +// sector05->AddNode(sensor04, 1, transD5); +// sector05->AddNode(sensor04, 2, transU5); +// sector05->GetShape()->ComputeBBox(); +// nSectors++; + + return nSectors; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Create ladders + ** + ** Ladders are the building blocks of the stations. They contain + ** several modules placed one after the other along the z axis + ** such that the sectors are arranged vertically (with overlap). + ** + ** A ladder is constructed out of two half ladders, the second of which + ** is rotated in the x-y plane by 180 degrees and displaced + ** in z direction. + **/ +Int_t CreateLadders() { + + Int_t nLadders = 0; + + // --- Some variables + Int_t nSectors = 0; + Int_t sectorTypes[10]; + TGeoBBox* shape = NULL; + TString s0name; + TString hlname; + char align; + TGeoVolume* s0vol = NULL; + TGeoVolume* halfLadderU = NULL; + TGeoVolume* halfLadderD = NULL; + + // --- Ladders 01-23 + Int_t allSectorTypes[27][6] = { { 1, 2, 3, 3, 0, -1 }, // ladder 01 - 5 - last column defines alignment of small sensors + { 1, 2, 3, 3, 0, 0 }, // ladder 02 - 5 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, -1 }, // ladder 03 - 6 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 04 - 6 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, -1 }, // ladder 05 - 7 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 06 - 7 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 07 - last column defines alignment of small sensors + { 3, 4, 4, 4, 0, 0 }, // ladder 08 - last column defines alignment of small sensors + + { 1, 1, 2, 3, 3, 0 }, // ladder 09 - last column defines alignment of small sensors + { 1, 1, 2, 2, 3, 0 }, // ladder 10 - last column defines alignment of small sensors + { 2, 2, 0, 0, 0, 0 }, // ladder 11 - last column defines alignment of small sensors + { 2, 2, 2, 3, 4, 0 }, // ladder 12 - last column defines alignment of small sensors + { 2, 2, 3, 4, 0, 0 }, // ladder 13 - last column defines alignment of small sensors + + { 2, 3, 4, 0, 0, 0 }, // ladder 14 - last column defines alignment of small sensors + { 3, 3, 0, 0, 0, 0 }, // ladder 15 - last column defines alignment of small sensors + { 2, 2, 3, 4, 4, 0 }, // ladder 16 - last column defines alignment of small sensors + { 2, 3, 4, 4, 0, 0 }, // ladder 17 - last column defines alignment of small sensors + { 3, 4, 4, 0, 0, 0 }, // ladder 18 - last column defines alignment of small sensors + + { 4, 4, 0, 0, 0, 0 }, // ladder 19 - last column defines alignment of small sensors + { 1, 2, 4, 4, 4, 0 }, // ladder 20 - last column defines alignment of small sensors + { 4, 0, 0, 0, 0, 0 }, // ladder 21 - last column defines alignment of small sensors + { 2, 3, 4, 4, 4, 0 }, // ladder 22 - last column defines alignment of small sensors + { 2, 3, 3, 4, 4, 0 }, // ladder 23 - last column defines alignment of small sensors + + { 2, 3, 4, 4, 0, 0 }, // ladder 24 - copy of 17 with different total length + { 3, 4, 4, 0, 0, 0 }, // ladder 25 - copy of 18 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 26 - copy of 19 with different total length + { 4, 4, 0, 0, 0, 0 }, // ladder 27 - copy of 19 with different total length + }; // 8 full - 19 partial ladders + +// Issue #405 +// Counting from the most upstream ladder, the gaps between sensors are as follows: +// 01 (most upstream): 41.3mm +// 02: 41.3mm +// 03: 42.0mm +// 04: 48.6mm +// 05: 60.8mm +// 06: 67.0mm +// 07: 79.2mm +// 08 (most downstream): 88.0mm + + Double_t pitchZ = 0; + Double_t gapXYZ[27][3] = { + { 0., 4.13, 0. }, // ladder 01 + { 0., 4.13, 0. }, // ladder 02 + { 0., 4.20, 0. }, // ladder 03 + { 0., 4.86, 0. }, // ladder 04 + { 0., 6.08, 0. }, // ladder 05 + { 0., 6.70, 0. }, // ladder 06 + { 0., 7.92, 0. }, // ladder 07 + { 0., 8.80, 0. }, // ladder 08 + { 0., -gkSectorOverlapY, 0. }, // ladder 09 + { 0., -gkSectorOverlapY, 0. }, // ladder 10 + { 0., -gkSectorOverlapY, 0. }, // ladder 11 + { 0., -gkSectorOverlapY, 0. }, // ladder 12 + { 0., -gkSectorOverlapY, 0. }, // ladder 13 + { 0., -gkSectorOverlapY, 0. }, // ladder 14 + { 0., -gkSectorOverlapY, 0. }, // ladder 15 + { 0., -gkSectorOverlapY, 0. }, // ladder 16 + { 0., -gkSectorOverlapY, 0. }, // ladder 17 + { 0., -gkSectorOverlapY, 0. }, // ladder 18 + { 0., -gkSectorOverlapY, 0. }, // ladder 19 + { 0., -gkSectorOverlapY, 0. }, // ladder 20 + { 0., -gkSectorOverlapY, 0. }, // ladder 21 + { 0., -gkSectorOverlapY, 0. }, // ladder 22 + { 0., -gkSectorOverlapY, 0. }, // ladder 23 + + { 0., -gkSectorOverlapY, 0. }, // ladder 24 - copy of 17 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 25 - copy of 18 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 26 - copy of 19 with different total length + { 0., -gkSectorOverlapY, 0. }, // ladder 27 - copy of 19 with different total length + }; + + Double_t ladderLength[27] = { + 48.0, // ladder 01 + 48.0, // ladder 02 + 64.0, // ladder 03 + 64.0, // ladder 04 + 80.0, // ladder 05 + 80.0, // ladder 06 + 92.0, // ladder 07 + 96.0, // ladder 08 + 48.0, // ladder 09 + 48.0, // ladder 10 + 48.0, // ladder 11 + 64.0, // ladder 12 + 64.0, // ladder 13 + 64.0, // ladder 14 + 64.0, // ladder 15 + 80.0, // ladder 16 + 80.0, // ladder 17 + 80.0, // ladder 18 + 80.0, // ladder 19 + 92.0, // ladder 20 + 92.0, // ladder 21 + 96.0, // ladder 22 + 96.0, // ladder 23 + + 96.0, // ladder 24 - copy of 17 with different total length + 92.0, // ladder 25 - copy of 18 with different total length + 96.0, // ladder 26 - copy of 19 with different total length + 92.0, // ladder 27 - copy of 19 with different total length + }; +// ======================================================================== + + // calculate Z shift for ladders with and without gaps in the center + s0name = Form("Sector%02d", allSectorTypes[0][0]); + s0vol = gGeoMan->GetVolume(s0name); + shape = (TGeoBBox*) s0vol->GetShape(); + +// ======================================================================== + + for (Int_t iLadder = 0; iLadder < 27; iLadder++) + { + cout << endl; + nSectors = 0; + for (Int_t i=0; i < 5; i++) + if (allSectorTypes[iLadder][i] != 0) + { + sectorTypes[nSectors] = allSectorTypes[iLadder][i]; // copy sectors for this ladder + cout << "DE iLadder " << iLadder+1 << " sectorTypes[" << nSectors << "] = " << allSectorTypes[iLadder][i] << ";" << endl; + nSectors++; // count how many sectors are in this ladder + } + + // always set displacement in z between upper and lower half ladder + gapXYZ[iLadder][2] = 2. * shape->GetDZ() + gkSectorGapZ; + + // define additional offset to carbon ladder for half ladders with less than 5 sensors + pitchZ = 2. * shape->GetDZ() + gkSectorGapZ; + + if (allSectorTypes[iLadder][5] == 0) + align = 'l'; + else + align = 'r'; + hlname = Form("HalfLadder%02du", iLadder+1); + // build upper half ladder + Int_t Ustart = 0; // 1; + if (iLadder < 8) + Ustart = 1; // 0; + halfLadderU = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2., Ustart); // mirrored + + if (allSectorTypes[iLadder][5] == 0) + align = 'r'; + else + align = 'l'; + hlname = Form("HalfLadder%02dd", iLadder+1); + // build lower half ladder + Int_t Dstart = 1; // 0; + if (iLadder < 8) + Dstart = 0; // 1; + halfLadderD = ConstructHalfLadder(hlname, nSectors, sectorTypes, align, + ladderLength[iLadder]/2., gapXYZ[iLadder][1]/2., Dstart); // mirrored + + // at this point half ladders are constructed + + // build all 4 possible ladders types for this sensor arrangement + ConstructLadder( iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19a + ConstructLadder( 100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19b + + ConstructLadder(1000+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19k + ConstructLadder(1100+iLadder+1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2], pitchZ, nSectors); // v19k + + nLadders++; + } + + return nLadders; +} +/** ======================================================================= **/ + + + +// **************************************************************************** +// ***** ***** +// ***** Generic functions for the construction of STS elements ***** +// ***** ***** +// ***** module: volume (made of a sector and a cable) ***** +// ***** haf ladder: assembly (made of modules) ***** +// ***** ladder: assembly (made of two half ladders) ***** +// ***** station: volume (made of ladders) ***** +// ***** ***** +// **************************************************************************** + + + +/** =========================================================================== + ** Construct a module + ** + ** A module is a sector plus the readout cable extending from the + ** top of the sector. The cable is made from passive silicon. + ** The cable has the same x size as the sector. + ** Its thickness is given by the global variable gkCableThickness. + ** The cable length is a parameter. + ** The sensor(s) of the sector is/are placed directly in the module; + ** the sector is just auxiliary for the proper placement. + ** + ** Arguments: + ** name volume name + ** sector pointer to sector volume + ** cableLength length of cable + **/ +TGeoVolume* ConstructModule(const char* name, + TGeoVolume* sector, + Double_t cableLength) { + + // --- Check sector volume + if ( ! sector ) Fatal("CreateModule", "Sector volume not found!"); + + // --- Get size of sector + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + + // --- Get size of cable + Double_t cableX = sectorX; + Double_t cableY = cableLength; + Double_t cableZ = gkCableThickness; + + // --- Create module volume + Double_t moduleX = TMath::Max(sectorX, cableX); + Double_t moduleY = sectorY + cableLength; + + Double_t moduleZ = TMath::Max(sectorZ, cableZ); + + TGeoVolume* module = gGeoManager->MakeBox(name, gStsMedium, + moduleX/2., + moduleY/2., + moduleZ/2.); + + // --- Position of sector in module + // --- Sector is centred in x and z and aligned to the bottom + Double_t sectorXpos = 0.; + Double_t sectorYpos = 0.5 * (sectorY - moduleY); + Double_t sectorZpos = 0.; + + + // --- Get sensor(s) from sector + Int_t nSensors = sector->GetNdaughters(); + for (Int_t iSensor = 0; iSensor < nSensors; iSensor++) { + TGeoNode* sensor = sector->GetNode(iSensor); + + // --- Calculate position of sensor in module + const Double_t* xSensTrans = sensor->GetMatrix()->GetTranslation(); + Double_t sensorXpos = sectorXpos + xSensTrans[0]; + Double_t sensorYpos = sectorYpos + xSensTrans[1]; + Double_t sensorZpos = sectorZpos + xSensTrans[2]; + TGeoTranslation* sensTrans = new TGeoTranslation("sensTrans", + sensorXpos, + sensorYpos, + sensorZpos); + + // --- Add sensor volume to module + TGeoVolume* sensVol = sensor->GetVolume(); + module->AddNode(sensor->GetVolume(), iSensor+1, sensTrans); + module->GetShape()->ComputeBBox(); + } + + + // --- Create cable volume, if necessary, and place it in module + // --- Cable is centred in x and z and aligned to the top + if ( gkConstructCables && cableLength > 0.0001 ) { + TString cableName = TString(name) + "_cable"; + TGeoMedium* cableMedium = gGeoMan->GetMedium("STScable"); + if ( ! cableMedium ) Fatal("CreateModule", "Medium STScable not found!"); + TGeoVolume* cable = gGeoManager->MakeBox(cableName.Data(), + cableMedium, + cableX / 2., + cableY / 2., + cableZ / 2.); + // add color to cables + cable->SetLineColor(kOrange); + cable->SetTransparency(60); + Double_t cableXpos = 0.; + Double_t cableYpos = sectorY + 0.5 * cableY - 0.5 * moduleY; + Double_t cableZpos = 0.; + TGeoTranslation* cableTrans = new TGeoTranslation("cableTrans", + cableXpos, + cableYpos, + cableZpos); + module->AddNode(cable, 1, cableTrans); + module->GetShape()->ComputeBBox(); + } + + return module; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a half ladder + ** + ** A half ladder is a virtual volume (TGeoVolumeAssembly) consisting + ** of several modules arranged on top of each other. The modules + ** have a given overlap in y and a displacement in z to allow for the + ** overlap. + ** + ** The typ of sectors / modules to be placed must be specified: + ** 1 = sensor01 + ** 2 = sensor02 + ** 3 = sensor03 + ** 4 = sensor04 + ** 5 = 2 x sensor04 (chained) + ** 6 = 3 x sensor04 (chained) + ** The cable is added automatically from the top of each sensor to + ** the top of the half ladder. + ** The alignment can be left (l) or right (r), which matters in the + ** case of different x sizes of sensors (e.g. SensorType01). + ** + ** Arguments: + ** name volume name + ** nSectors number of sectors + ** sectorTypes array with sector types + ** align horizontal alignment of sectors + * ladderLength full length of the ladder towards FEE + * offsetY gap in the beam-pipe region + **/ +TGeoVolume* ConstructHalfLadder(const TString& name, + Int_t nSectors, + Int_t* sectorTypes, + char align, + Double_t ladderLength, + Double_t offsetY, + Int_t start) { + + // --- Create half ladder volume assembly + TGeoVolumeAssembly* halfLadder = new TGeoVolumeAssembly(name); + + // --- Determine size of ladder + Double_t ladderX = 0.; + Double_t ladderY = 0.; + Double_t ladderZ = 0.; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + if ( ! sector ) + Fatal("ConstructHalfLadder", Form("Volume %s not found", sectorName.Data())); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + // --- Ladder x size equals largest sector x size + ladderX = TMath::Max(ladderX, 2. * box->GetDX()); + // --- Ladder y size is sum of sector ysizes + ladderY += 2. * box->GetDY(); + // --- Ladder z size is sum of sector z sizes + ladderZ += 2. * box->GetDZ(); + + cout << "DETT " << ladderX << " ; " << ladderY << " ; " << ladderZ << endl; + } + // --- Subtract overlaps in y + ladderY -= Double_t(nSectors-1) * gkSectorOverlapY; + // --- Add gaps in z direction + ladderZ += Double_t(nSectors-1) * gkSectorGapZ; + + ladderY = TMath::Max(ladderLength - offsetY, ladderY); + + // --- Create and place modules + Double_t yPosSect = -0.5 * ladderY; + Double_t zPosMod = -0.5 * ladderZ; + for (Int_t iSector = 0; iSector < nSectors; iSector++) { + TString sectorName = Form("Sector%02d", + sectorTypes[iSector]); + TGeoVolume* sector = gGeoMan->GetVolume(sectorName); + TGeoBBox* box = (TGeoBBox*) sector->GetShape(); + Double_t sectorX = 2. * box->GetDX(); + Double_t sectorY = 2. * box->GetDY(); + Double_t sectorZ = 2. * box->GetDZ(); + yPosSect += 0.5 * sectorY; // Position of sector in ladder + Double_t cableLength = 0.5 * ladderY - yPosSect - 0.5 * sectorY; + TString moduleName = name + "_" + Form("Module%02d", + sectorTypes[iSector]); + TGeoVolume* module = ConstructModule(moduleName.Data(), + sector, cableLength); + + TGeoBBox* shapeMod = (TGeoBBox*) module->GetShape(); + Double_t moduleX = 2. * shapeMod->GetDX(); + Double_t moduleY = 2. * shapeMod->GetDY(); + Double_t moduleZ = 2. * shapeMod->GetDZ(); + Double_t xPosMod = 0.; + if ( align == 'l' ) + xPosMod = 0.5 * (moduleX - ladderX); // left aligned + else if ( align == 'r' ) + xPosMod = 0.5 * (ladderX - moduleX); // right aligned + else + xPosMod = 0.; // centred in x + Double_t yPosMod = 0.5 * (ladderY - moduleY); // top aligned + zPosMod += 0.5 * moduleZ; + +// Int_t angle = 0; // set default rotation angle to 0 +// if (iSector%2 == 1) // set rotation angle for every 2nd sensor +// angle = 180; + + Int_t angle = start * 180; + start = (start + 1) % 2; + + TGeoRotation* rmod = new TGeoRotation(); + // rmod->RotateY(angle); + // rmod->RotateY(180); // v19v + rmod->RotateY(0); // v19w + TGeoCombiTrans* cmod = new TGeoCombiTrans (xPosMod, yPosMod, zPosMod, rmod); + halfLadder->AddNode(module, iSector+1, cmod); + +// old style +// TGeoTranslation* trans = new TGeoTranslation("t", xPosMod, yPosMod, zPosMod); +// halfLadder->AddNode(module, iSector+1, trans); + + halfLadder->GetShape()->ComputeBBox(); + yPosSect += 0.5 * sectorY - gkSectorOverlapY; + zPosMod += 0.5 * moduleZ + gkSectorGapZ; + } + + CheckVolume(halfLadder); + cout << endl; + + return halfLadder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Add a carbon support to a ladder + ** + ** Arguments: + ** LadderIndex ladder number + ** ladder pointer to ladder + ** xu size of halfladder + ** ladderY height of ladder along y + ** ladderZ thickness of ladder along z + **/ +void AddCarbonLadder(Int_t LadderIndex, + TGeoVolume* ladder, + Double_t xu, + Double_t ladderY, + Double_t ladderZ) { + + // --- Some variables + TString name = Form("LadderType%04d", LadderIndex); // v19k + Int_t i; + Double_t j; + + Int_t YnumOfFrameBoxes = round(ladderY / gkFrameStep); + + // cout << "DEXZ: lad " << LadderIndex << " inum " << YnumOfFrameBoxes << endl; + + Double_t ladderDZ = (xu/2. + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2)/2.; + cout << "DEFR: frame Z size " << 2 * ladderDZ << " cm" << endl; + + TGeoBBox* fullFrameShp = new TGeoBBox (name+"_CarbonElement_shp", xu/2., gkFrameStep/2., ladderDZ); + TGeoVolume* fullFrameBoxVol = new TGeoVolume(name+"_CarbonElement", fullFrameShp, gStsMedium); + + ConstructFrameElement("CarbonElement", fullFrameBoxVol, xu/2.); + TGeoRotation* fullFrameRot = new TGeoRotation; + fullFrameRot->RotateY(180); + + Int_t inum = YnumOfFrameBoxes; + for (i=1; i<=inum; i++) + { + j=-(inum-1)/2.+(i-1); + // -(10-1)/2. +0 +10-1 -> -4.5 .. +4.5 -> -0.5, +0.5 (= 2) + // -(11-1)/2. +0 +11-1 -> -5.0 .. +5.0 -> -1, 0, 1 (= 3) + // cout << "DE: i " << i << " j " << j << endl; + + if (LadderIndex % 100 <= 3) // central ladders in stations 1 to 3 + { + if ((j>=-1) && (j<=1)) // keep the inner 2 (even) or 3 (odd) elements free for the cone + continue; + } + else if (LadderIndex % 100 <= 8) // central ladders in stations 4 to 8 + { + if ((j>=-2) && (j<=2)) // keep the inner 4 elements free for the cone + continue; + } + + cout << "DELZ: ladderDZ " << ladderDZ << " cm " << -ladderZ/2. - ladderDZ << " cm " << endl; + ladder->AddNode(fullFrameBoxVol, i, new TGeoCombiTrans(name+"_CarbonElement_posrot", 0., j*gkFrameStep, -(ladderZ/2.+ladderDZ), fullFrameRot)); + } + + ladder->GetShape()->ComputeBBox(); + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Construct a ladder out of two half ladders with vertical gap + ** + ** The second half ladder will be rotated by 180 degrees + ** in the x-y plane. The two half ladders will be put on top of each + ** other with a vertical gap. + ** + ** Arguments: + ** name volume name + ** halfLadderU pointer to upper half ladder + ** halfLadderD pointer to lower half ladder + ** gapY vertical gap + ** shiftZ relative displacement along the z axis + **/ + + TGeoVolume* ConstructLadder(Int_t LadderIndex, + TGeoVolume* halfLadderU, + TGeoVolume* halfLadderD, + Double_t gapY, + Double_t shiftZ, + Double_t pitchZ, + Int_t nSectors) { + + // --- Some variables + TGeoBBox* shape = NULL; + + // define additional offset to carbon ladder for half ladders with less than 5 sensors + Double_t offsetZ = (5 - nSectors) * pitchZ; + + // --- Dimensions of half ladders + shape = (TGeoBBox*) halfLadderU->GetShape(); // up + Double_t xu = 2. * shape->GetDX(); + Double_t yu = 2. * shape->GetDY(); + Double_t zu = 2. * shape->GetDZ(); + + shape = (TGeoBBox*) halfLadderD->GetShape(); // down + Double_t xd = 2. * shape->GetDX(); + Double_t yd = 2. * shape->GetDY(); + Double_t zd = 2. * shape->GetDZ(); + + // --- Create ladder volume assembly + TString name = Form("LadderType%04d", LadderIndex); // v19k + TGeoVolumeAssembly* ladder = new TGeoVolumeAssembly(name); + Double_t ladderX = TMath::Max(xu, xd); + Double_t ladderY = yu + yd + gapY; + Double_t ladderZ = TMath::Max(zu, zd + shiftZ + offsetZ); // there are 6 slots - 5 x 1.5 mm + 0.3 mm = 7.8 mm + // Double_t ladderZ = TMath::Max(zu, zd + shiftZ); + + cout << "DERR iladder " << LadderIndex << " nSec " << nSectors + << " zu " << zu << " zd " << zd + << " zd+shi " << zd+shiftZ << " ladderZ " << ladderZ + << " offsetZ " << offsetZ << endl; + + // --- Place half ladders + Double_t xPosU = 0.0; // centred in x + Double_t yPosU = 0.5 * ( ladderY - yu ); // top aligned + Double_t zPosU = 0; + zPosU = 0.5 * ( ladderZ - zu ); // front aligned + if (LadderIndex >= 1000) + zPosU = -0.5 * ( ladderZ - zu ) + offsetZ; // back aligned with possible offset + //zPosU = -zPosU; + + TGeoTranslation* tu = new TGeoTranslation("tu", xPosU, yPosU, zPosU); + ladder->AddNode(halfLadderU, 1, tu); + + Double_t xPosD = 0.0; // centred in x + Double_t yPosD = 0.5 * -( ladderY - yd ); // bottom aligned + Double_t zPosD = 0; + zPosD = 0.5 * -( ladderZ - zd ) + offsetZ; // back aligned with possible offset + if (LadderIndex >= 1000) + zPosD = -0.5 * -( ladderZ - zd ); // front aligned + //zPosD = -zPosD; + + TGeoRotation* rd = new TGeoRotation(); + rd->RotateZ(180.); + TGeoCombiTrans* cd = new TGeoCombiTrans(xPosD, yPosD, zPosD, rd); + ladder->AddNode(halfLadderD, 2, cd); + + ladder->GetShape()->ComputeBBox(); + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD0ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + cout << "DDDD ladder" << LadderIndex << endl; + cout << "DDDD1ladder" << LadderIndex << " ladderX " << ladderX << " ladderY " << ladderY << " ladderZ " << ladderZ << endl; + + // ---------------- Create and place frame boxes ------------------------ + + if (gkConstructFrames) + AddCarbonLadder(LadderIndex, ladder, ladderX, ladderY, ladderZ); + + // -------------------------------------------------------------------------- + + shape = (TGeoBBox*) ladder->GetShape(); + cout << "DDDD2ladder" << LadderIndex << " ladderX " << 2. * shape->GetDX() + << " ladderY " << 2. * shape->GetDY() + << " ladderZ " << 2. * shape->GetDZ() << endl; + + return ladder; +} +/** ======================================================================= **/ + + + + +/** =========================================================================== + ** Construct a unit + ** + ** The unit volume is the minimal box comprising all ladders + ** minus a tube accomodating the beam pipe. + ** + ** The ladders are arranged horizontally from left to right with + ** a given overlap in x. + ** Every second ladder is slightly displaced upstream from the centre + ** z plane and facing downstream, the others are slightly displaced + ** downstream and facing upstream (rotated around the y axis). + ** + ** Arguments: + ** name volume name + ** nLadders number of ladders + ** ladderTypes array of ladder types + **/ + + TGeoVolume* ConstructUnit(Int_t iSide, + Int_t iUnit, + Int_t nLadders, + Int_t* ladderTypes, + Int_t iStation) { + + Bool_t isFirstPartOfHalfUnit = kFALSE; + + // TString name = Form("Unit%02d", iUnit); // 0,1,2,3,4,5,6,7 - Unit00 missing in output + // TString name = Form("Unit%02d", iUnit+1); // 1,2,3,4,5,6,7,8 + + TGeoVolume* unit = gGeoMan->GetVolume(unitName[iUnit]); + if ( ! unit ) // if it does not yet exist, create a new one + { + unit = new TGeoVolumeAssembly(unitName[iUnit]); + isFirstPartOfHalfUnit = kTRUE; + } + + // --- Some local variables + TGeoBBox* ladderShape = NULL; + TGeoVolume* ladder = NULL; + TString ladderName; + Double_t subtractedVal; + + // --- Determine size of unit from ladders + Double_t statX = 0.; + // Double_t statY = 0.; + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) + { + Int_t ladderType = ladderTypes[iLadder]; // v19k + +// if (iSide == 0) cout << "DWER " << ladderTypes[iLadder] << " " << ladderType << endl; + + if (ladderType > 0) + { + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + if ( ! ladder ) Fatal("ConstructUnit", + Form("Volume %s not found", ladderName.Data())); + ladderShape = (TGeoBBox*) ladder->GetShape(); + statX += 2. * ladderShape->GetDX(); + } + else + statX += gkSensorSizeX; // empty ladder in unit + } + statX -= Double_t(nLadders-1) * gkLadderOverlapX; + +// if (iSide == 0) cout << "DWER -" << endl; + + // --- Place ladders in unit + cout << "xPos0: " << statX << endl; + Double_t xPos = -0.5 * statX; + cout << "xPos1: " << xPos << endl; + Double_t yPos = 0.; + Double_t zPos = 0.; + + Double_t maxdz = 0.; + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) // find maximum dz in this unit + { + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + if (maxdz < ladderShape->GetDZ()) + maxdz = ladderShape->GetDZ(); + } + } + + for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) + { + Int_t ladderType = ladderTypes[iLadder]; // v19k + + if (ladderType > 0) + { + ladderName = Form("LadderType%04d", ladderType); // v19k + + ladder = gGeoManager->GetVolume(ladderName); + ladderShape = (TGeoBBox*) ladder->GetShape(); + xPos += ladderShape->GetDX(); + cout << "xPos2: " << xPos << endl; + yPos = 0.; // vertically centred + TGeoRotation* rot = new TGeoRotation(); + + if (gkConstructFrames) + subtractedVal = ladderShape->GetDX() + sqrt(2.)*gkFrameThickness/2. + gkSectorGapZFrame*2; + else + subtractedVal = 0.; + + zPos = 0.5 * gkLadderGapZ + (2*maxdz-ladderShape->GetDZ()-subtractedVal/2.); // z-aligned ladders + +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " dx: " << ladderShape->GetDX() + << " dy: " << ladderShape->GetDY() + << " dz: " << ladderShape->GetDZ() + << " max dz: " << maxdz << endl; + +// v19k + cout << "DE ladder" << ladderTypes[iLadder] + << " fra: " << gkFrameThickness/2. + << " sub: " << subtractedVal + << " zpo: " << zPos << endl << endl; + +// v19k + if (ladderTypes[iLadder]/1000 == 1) // flip some of the ladders to reproduce the CAD layout + rot->RotateY(180.); + else + zPos = -zPos; + + if (!isFirstPartOfHalfUnit) + zPos += 10.5; // v19d +// zPos += 10.0; // initial version + + TGeoCombiTrans* trans = new TGeoCombiTrans(xPos, yPos, zPos, rot); +// start +// cout << "DEEE** iLadder " << iLadder << " " << nLadders/2 << " " << nLadders << endl; + + if (iSide == 0) + { + if (iLadder < nLadders/2) // right side - only half unit -x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + else + { + if (iLadder >= nLadders/2) // left side - only half unit +x + { + unit->AddNode(ladder, iStation*100 + iLadder+1, trans); + // calculate Station number to encode the ladder copy number + cout << "DEFG** iLadder: " << iLadder << " iStation: " << iStation << endl; + } + } + unit->GetShape()->ComputeBBox(); +// stop + xPos += ladderShape->GetDX() - gkLadderOverlapX; + cout << "xPos3: " << xPos << endl; + } + else + xPos += gkSensorSizeX - gkLadderOverlapX; + } + + return unit; + } +/** ======================================================================= **/ + + +/** =========================================================================== + ** Import and add the passive materials to the STS volume + **/ +void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile) +{ + TString passiveName = TString("sts_passive_") + geoTag; + TString basePath = gSystem->Getenv("VMCWORKDIR"); + TString relPath = "/geometry/sts/passive/" + passiveName + ".gdml"; + TString passiveFileName = basePath + relPath; + infoFile << std::endl << std::endl; + infoFile << "Importing STS passive materials from GDML file '" << relPath << "'." << std::endl; + + TGDMLParse parser; + TGeoVolume* gdmlVolume = parser.GDMLReadFile(passiveFileName); + PostProcessGdml(gdmlVolume); + gdmlVolume->SetName(passiveName); + + TGeoTranslation* passiveTrans = new TGeoTranslation(0., 0., 4.68 - 2.); + infoFile << "Passive assembly is translated for Z=2.68 cm downstream with respect to parent volume" << std::endl << std::endl; + + gdmlVolume->GetShape()->ComputeBBox(); + CheckVolume(gdmlVolume, infoFile); + + infoFile << std::endl; + for (Int_t iNode = 0; iNode < gdmlVolume->GetNdaughters(); iNode++) { + CheckVolume(gdmlVolume->GetNode(iNode)->GetVolume(), infoFile, kFALSE); + } + + stsVolume->AddNode(gdmlVolume, stsVolume->GetNdaughters(), passiveTrans, ""); +} + +/** =========================================================================== + ** Assign visual properties to the imported gdml volumes + **/ +void PostProcessGdml(TGeoVolume* gdmlVolume) +{ + const UInt_t kPOBColor = kRed-6; + const UInt_t kPOBTransparency = 0;// 5; + + const UInt_t kFEBColor = kOrange-6; + const UInt_t kFEBTransparency = 0;// 5; + + const UInt_t kUnitColor = kCyan-10; + const UInt_t kUnitTransparency = 0;// 5; + + const UInt_t kCfColor = kGray+3; + const UInt_t kCfTransparency = 0;// 10; + + // name <Color, Transparency> + std::map<std::string, std::tuple<UInt_t,UInt_t> > props { + { "passive_POB", std::tuple<UInt_t,UInt_t> {kPOBColor, kPOBTransparency} }, + { "passive_FEB", std::tuple<UInt_t,UInt_t> {kFEBColor, kFEBTransparency} }, + { "passive_unit", std::tuple<UInt_t,UInt_t> {kUnitColor, kUnitTransparency} }, + { "passive_Box_Wall", std::tuple<UInt_t,UInt_t> {kCfColor, kCfTransparency} }, + { "passive_Box_Wall_Front_CF2", std::tuple<UInt_t,UInt_t> {kCfColor-3, kCfTransparency} }, + }; + + // Match volume name and apply visual properties + const TObjArray* volumes = gGeoManager->GetListOfVolumes(); + for (auto& entry : props) { + TIter next(volumes); + TGeoVolume *vol = nullptr; + while ((vol=(TGeoVolume*)next())) { + if (TString(vol->GetName()).Contains(entry.first.c_str())) { + vol->SetLineColor(std::get<0>(entry.second)); + vol->SetTransparency(std::get<1>(entry.second)); + } + } + } +} + +/** =========================================================================== + ** Volume information for debugging + **/ +void CheckVolume(TGeoVolume* volume) { + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + cout << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) cout << ", assembly"; + else { + if ( volume->GetMedium() ) + cout << ", medium " << volume->GetMedium()->GetName(); + else cout << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + cout << endl; + if ( volume->GetNdaughters() ) { + cout << "Daughters: " << endl; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) { + TGeoNode* node = volume->GetNode(iNode); + TGeoBBox* shape = (TGeoBBox*) node->GetVolume()->GetShape(); + cout << setw(15) << node->GetName() << ", size " + << fixed << setprecision(3) + << setw(6) << 2. * shape->GetDX() << " x " + << setw(6) << 2. * shape->GetDY() << " x " + << setw(6) << 2. * shape->GetDZ() << ", position ( "; + TGeoMatrix* matrix = node->GetMatrix(); + const Double_t* pos = matrix->GetTranslation(); + cout << setfill(' '); + cout << fixed << setw(8) << pos[0] << ", " + << setw(8) << pos[1] << ", " + << setw(8) << pos[2] << " )" << endl; + } + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Volume information for output to file + **/ +void CheckVolume(TGeoVolume* volume, fstream& file, Bool_t listChildren) { + if ( ! file ) return; + + TGeoBBox* shape = (TGeoBBox*) volume->GetShape(); + file << volume->GetName() << ": size " << fixed << setprecision(4) + << setw(7) << 2. * shape->GetDX() << " x " << setw(7) + << 2. * shape->GetDY() << " x " << setw(7) + << 2. * shape->GetDZ(); + if ( volume->IsAssembly() ) file << ", assembly"; + else { + if ( volume->GetMedium() ) + file << ", medium " << volume->GetMedium()->GetName(); + else file << ", " << "\033[31m" << " no medium" << "\033[0m"; + } + file << endl; + if ( volume->GetNdaughters() && listChildren) { + file << "Contains: "; + for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) + file << volume->GetNode(iNode)->GetVolume()->GetName() << " "; + file << endl; + } + +} +/** ======================================================================= **/ + + +/** =========================================================================== + ** Calculate beam pipe outer radius for a given z + **/ +Double_t BeamPipeRadius(Double_t z) { + if ( z < gkPipeZ2 ) return gkPipeR1; + Double_t slope = (gkPipeR3 - gkPipeR2 ) / (gkPipeZ3 - gkPipeZ2); + return gkPipeR2 + slope * (z - gkPipeZ2); +} +/** ======================================================================= **/ + + + +/** ======================================================================= **/ +TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + TGeoBBox* frameVertPillarShp; + + Double_t t = gkFrameThickness/2.; + + // --- Main vertical pillars +// TGeoBBox* frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, gkFrameStep/2., t); // square crossection, along y +// TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); +// frameVertPillarVol->SetLineColor(kGreen); +// frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoTranslation(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2.)); +// frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoTranslation(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkCylindricalFrames) + // TGeoBBox* frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", 0, t, gkFrameStep/2.); // circle crossection, along z + frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", gkCylinderDiaInner/2., gkCylinderDiaOuter/2., gkFrameStep/2.); // circle crossection, along z + else + frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, t, gkFrameStep/2.); // square crossection, along z + TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial); + frameVertPillarVol->SetLineColor(kGreen); + + TGeoRotation* xRot90 = new TGeoRotation; + xRot90->RotateX(90.); + frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoCombiTrans(name + "_vertpillar_pos_1", x-t, 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoCombiTrans(name + "_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2., xRot90)); + + // TGeoRotation* vertRot = new TGeoRotation(name + "_vertpillar_rot_1", 90., 45., -90.); + TGeoRotation* vertRot = new TGeoRotation; + vertRot->RotateX(90.); + vertRot->RotateY(45.); + frameBoxVol->AddNode(frameVertPillarVol, 3, new TGeoCombiTrans(name + "_vertpillar_pos_3", 0., 0., (x-sqrt(2.)*t)/2., vertRot)); + + // --- Small horizontal pillar + // TGeoBBox* frameHorPillarShp = new TGeoBBox(name + "_horpillar_shape", x-2.*t, gkThinFrameThickness/2., gkThinFrameThickness/2.); + // TGeoVolume* frameHorPillarVol = new TGeoVolume(name + "_horpillar", frameHorPillarShp, framesMaterial); + // frameHorPillarVol->SetLineColor(kCyan); + // frameBoxVol->AddNode(frameHorPillarVol, 1, new TGeoTranslation(name + "_horpillar_pos_1", 0., -gkFrameStep/2.+gkThinFrameThickness/2., -(x+sqrt(2.)*t-2.*t)/2.)); + + if (gkConstructSmallFrames) { + + // --- Small sloping pillars + TGeoPara* frameSlopePillarShp = new TGeoPara(name + "_slopepillar_shape", + (x-2.*t)/TMath::Cos(31.4/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., 31.4, 0., 90.); + TGeoVolume* frameSlopePillarVol = new TGeoVolume(name + "_slopepillar", frameSlopePillarShp, framesMaterial); + frameSlopePillarVol->SetLineColor(kCyan); + TGeoRotation* slopeRot = new TGeoRotation(name + "_slopepillar_rot_1", 0., 0., 31.4); + TGeoRotation* slopeRot2 = new TGeoRotation(name + "_slopepillar_rot_2", 0., 0., -31.4); + TGeoCombiTrans* slopeTrRot = new TGeoCombiTrans(name + "_slopepillar_posrot_1", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot); + TGeoCombiTrans* slopeTrRot2 = new TGeoCombiTrans(name + "_slopepillar_posrot_2", 0., 0., -(x+sqrt(2.)*t-2.*t)/2., slopeRot2); + + frameBoxVol->AddNode(frameSlopePillarVol, 1, slopeTrRot); + frameBoxVol->AddNodeOverlap(frameSlopePillarVol, 2, slopeTrRot2); + + + Double_t angl = 23.; + // --- Small sub pillar + TGeoPara* frameSubPillarShp = new TGeoPara(name + "_subpillar_shape", + (sqrt(2)*(x/2.-t)-t/2.)/TMath::Cos(angl/180.*TMath::Pi()), gkThinFrameThickness/2., gkThinFrameThickness/2., angl, 0., 90.); + TGeoVolume* frameSubPillarVol = new TGeoVolume(name + "_subpillar", frameSubPillarShp, framesMaterial); + frameSubPillarVol->SetLineColor(kMagenta); + + Double_t posZ = t * (1. - 3. / ( 2.*sqrt(2.) )); + + // one side of X direction + TGeoRotation* subRot1 = new TGeoRotation(name + "_subpillar_rot_1", 90., 45., -90.+angl); + TGeoCombiTrans* subTrRot1 = new TGeoCombiTrans(name + "_subpillar_posrot_1", -(-x/2.+t-t/(2.*sqrt(2.))), 1., posZ, subRot1); + + TGeoRotation* subRot2 = new TGeoRotation(name + "_subpillar_rot_2", 90., -90.-45., -90.+angl); + TGeoCombiTrans* subTrRot2 = new TGeoCombiTrans(name + "_subpillar_posrot_2", -(-x/2.+t-t/(2.*sqrt(2.))), -1., posZ, subRot2); + + // other side of X direction + TGeoRotation* subRot3 = new TGeoRotation(name + "_subpillar_rot_3", 90., 90.+45., -90.+angl); + TGeoCombiTrans* subTrRot3 = new TGeoCombiTrans(name + "_subpillar_posrot_3", -x/2.+t-t/(2.*sqrt(2.)), 1., posZ, subRot3); + + TGeoRotation* subRot4 = new TGeoRotation(name + "_subpillar_rot_4", 90., -45., -90.+angl); + TGeoCombiTrans* subTrRot4 = new TGeoCombiTrans(name + "_subpillar_posrot_4", -x/2.+t-t/(2.*sqrt(2.)), -1., posZ, subRot4); + + frameBoxVol->AddNode(frameSubPillarVol, 1, subTrRot1); + frameBoxVol->AddNode(frameSubPillarVol, 2, subTrRot2); + frameBoxVol->AddNode(frameSubPillarVol, 3, subTrRot3); + frameBoxVol->AddNode(frameSubPillarVol, 4, subTrRot4); + // frameBoxVol->GetShape()->ComputeBBox(); + } + + return frameBoxVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructSmallCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 6., 7.6, 6., 6.04, 0., 180.); +// TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + Double_t radius = 3.0; + Double_t thickness = 0.04; // 0.4 mm +// TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 3., 3.2, 3., 3.2, 0., 180.); + TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, radius, radius+thickness, radius, radius+thickness, 0., 180.); + TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.); + + TGeoCombiTrans* M = new TGeoCombiTrans ("M"); + M->RotateX (45.); + M->SetDy (-5.575); + M->SetDz (6.935); + M->RegisterYourself(); + + TGeoShape* coneShp = new TGeoCompositeShape ("Cone_shp", "A-B:M"); + TGeoVolume* coneVol = new TGeoVolume ("Cone", coneShp, framesMaterial); + coneVol->SetLineColor(kGreen); +// coneVol->RegisterYourself(); + +// // --- Inner cone +// Double_t thickness = 0.02; +// Double_t thickness2 = 0.022; +// // TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); +// TGeoConeSeg* A2 = new TGeoConeSeg ("A2", coneDz-thickness, 3.+thickness, 4.6-thickness2, 2.99+thickness, 3.05-thickness2, 0., 180.); +// +// TGeoCombiTrans* M2 = new TGeoCombiTrans ("M2"); +// M2->RotateX (45.); +// M2->SetDy (-5.575+thickness*sqrt(2.)); +// M2->SetDz (6.935); +// M2->RegisterYourself(); +// +// TGeoShape* coneShp2 = new TGeoCompositeShape ("Cone2_shp", "A2-B:M2"); +// TGeoVolume* coneVol2 = new TGeoVolume ("Cone2", coneShp2, gStsMedium); +// coneVol2->SetLineColor(kGreen); +//// coneVol2->RegisterYourself(); +// +// coneVol->AddNode(coneVol2, 1); + + return coneVol; +} +/** ======================================================================= **/ + +/** ======================================================================= **/ +TGeoVolume* ConstructBigCone(Double_t coneDz) +{ + // --- Material of the frames + TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon"); + + // --- Outer cone + TGeoConeSeg* bA = new TGeoConeSeg ("bA", coneDz, 6., 7.6, 6., 6.04, 0., 180.); + TGeoBBox* bB = new TGeoBBox ("bB", 8., 6., 10.); + + TGeoCombiTrans* bM = new TGeoCombiTrans ("bM"); + bM->RotateX (45.); + bM->SetDy (-5.575); + bM->SetDz (6.935); + bM->RegisterYourself(); + + TGeoShape* coneBigShp = new TGeoCompositeShape ("ConeBig_shp", "bA-bB:bM"); + TGeoVolume* coneBigVol = new TGeoVolume ("ConeBig", coneBigShp, framesMaterial); + coneBigVol->SetLineColor(kGreen); +// coneBigVol->RegisterYourself(); + + // --- Inner cone + Double_t thickness = 0.02; + Double_t thickness2 = 0.022; + TGeoConeSeg* bA2 = new TGeoConeSeg ("bA2", coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); + + TGeoCombiTrans* bM2 = new TGeoCombiTrans ("bM2"); + bM2->RotateX (45.); + bM2->SetDy (-5.575+thickness*sqrt(2.)); + bM2->SetDz (6.935); + bM2->RegisterYourself(); + + TGeoShape* coneBigShp2 = new TGeoCompositeShape ("ConeBig2_shp", "bA2-bB:bM2"); + TGeoVolume* coneBigVol2 = new TGeoVolume ("ConeBig2", coneBigShp2, gStsMedium); + coneBigVol2->SetLineColor(kGreen); +// coneBigVol2->RegisterYourself(); + + coneBigVol->AddNode(coneBigVol2, 1); + + return coneBigVol; +} + +/** ======================================================================= **/