Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • a.bercuci/cbmroot_geometry
  • d.ramirez/cbmroot_geometry
  • m.shiroya/cbmroot_geometry
  • ajit.kumar/cbmroot_geometry
  • n.herrmann/cbmroot_geometry
  • a.weber/cbmroot_geometry
  • a.agarwal_AT_vecc.gov.in/cbmroot_geometry
  • l.chlad/cbmroot_geometry
  • a.toia/cbmroot_geometry
  • ma.beyer/cbmroot_geometry
  • a_meye37_AT_uni-muenster.de/cbmroot_geometry
  • praisig/cbmroot_geometry
  • aksharma/cbmroot_geometry
  • hofmanond_AT_fjfi.cvut.cz/cbmroot_geometry
  • r.karabowicz/cbmroot_geometry
  • i.deppner/cbmroot_geometry
  • s.lebedev/cbmroot_geometry
  • osingh/cbmroot_geometry
  • CbmSoft/cbmroot_geometry
  • p.-a.loizeau/cbmroot_geometry
  • f.uhlig/cbmroot_geometry
  • d.emschermann/cbmroot_geometry
  • e.clerkin/cbmroot_geometry
  • rishat.sultanov_AT_cern.ch/cbmroot_geometry
  • se.gorbunov/cbmroot_geometry
  • s.roy/cbmroot_geometry
  • p.chudoba/cbmroot_geometry
  • o.golosov/cbmroot_geometry
  • apuntke/cbmroot_geometry
  • v.singhal/cbmroot_geometry
30 results
Show changes
Commits on Source (40)
Showing
with 12153 additions and 16 deletions
FSD geometry v25e created with create_fsdgeo_firstRealistic.C
Position for maximum deflection angle, e.g. E_kin_beam = 5A GeV and 100% magnetic field strength
Number of SMALL modules per quadrant: 5 x 3
Number of MEDIUM modules per quadrant: 4 x 3
Number of LARGE modules per quadrant: 2 x 2
FSD thickness: 5 cm
FSD front plane center coordinates: (31.6478, 0, 1000) cm
FSD rotation around y axis: 0.0329867 rad
Hole in the wall has a radii of 10 cm
Parameters of module fsdmodule:
Size: 4 cm x 4 cm
Thickness: 5 cm
Channel Depth (ratio of thickness): 0.75
Channel Width: 0.2 cm
Channel distance from the edge of scintillator: 0.5 cm
Channel radius at corners: 1 cm
Parameters of module fsdmodule:
Size: 8 cm x 8 cm
Thickness: 5 cm
Channel Depth (ratio of thickness): 0.75
Channel Width: 0.2 cm
Channel distance from the edge of scintillator: 0.5 cm
Channel radius at corners: 1 cm
Parameters of module fsdmodule:
Size: 16 cm x 16 cm
Thickness: 5 cm
Channel Depth (ratio of thickness): 0.75
Channel Width: 0.2 cm
Channel distance from the edge of scintillator: 0.5 cm
Channel radius at corners: 1 cm
FSD size is 192 cm x 160 cm x 5 cm
FSD contains 372 modules in total,
small sized modules: 156
medium sized modules: 144
large sized modules: 72
FSD volume center coordinates: (31.7302, 0, 1002.5) cm
File added
FSD geometry v25h created with create_fsdgeo_firstRealistic.C
Position for Au beam at 12A GeV/c and 100% magnetic field strength
Number of SMALL modules per quadrant: 5 x 3
Number of MEDIUM modules per quadrant: 4 x 3
Number of LARGE modules per quadrant: 2 x 2
FSD thickness: 5 cm
FSD front plane center coordinates: (15.1229, 0, 1000) cm
FSD rotation around y axis: 0.0171042 rad
Hole in the wall has a radii of 10 cm
Parameters of module fsdmodule:
Size: 4 cm x 4 cm
Thickness: 5 cm
Channel Depth (ratio of thickness): 0.75
Channel Width: 0.2 cm
Channel distance from the edge of scintillator: 0.5 cm
Channel radius at corners: 1 cm
Parameters of module fsdmodule:
Size: 8 cm x 8 cm
Thickness: 5 cm
Channel Depth (ratio of thickness): 0.75
Channel Width: 0.2 cm
Channel distance from the edge of scintillator: 0.5 cm
Channel radius at corners: 1 cm
Parameters of module fsdmodule:
Size: 16 cm x 16 cm
Thickness: 5 cm
Channel Depth (ratio of thickness): 0.75
Channel Width: 0.2 cm
Channel distance from the edge of scintillator: 0.5 cm
Channel radius at corners: 1 cm
FSD size is 192 cm x 160 cm x 5 cm
FSD contains 372 modules in total,
small sized modules: 156
medium sized modules: 144
large sized modules: 72
FSD volume center coordinates: (15.1657, 0, 1002.5) cm
File added
FSD geometry v25i created with create_fsdgeo_firstRealistic.C
Position for Au beam at 11 AGeV/c (10 AGeV) and 100% magnetic field strength
Number of SMALL modules per quadrant: 5 x 3
Number of MEDIUM modules per quadrant: 4 x 3
Number of LARGE modules per quadrant: 2 x 2
FSD thickness: 5 cm
FSD front plane center coordinates: (16.3936, 0, 1000) cm
FSD rotation around y axis: 0.018326 rad
Hole in the wall has a radii of 10 cm
Parameters of module fsdmodule:
Size: 4 cm x 4 cm
Thickness: 5 cm
Channel Depth (ratio of thickness): 0.75
Channel Width: 0.2 cm
Channel distance from the edge of scintillator: 0.5 cm
Channel radius at corners: 1 cm
Parameters of module fsdmodule:
Size: 8 cm x 8 cm
Thickness: 5 cm
Channel Depth (ratio of thickness): 0.75
Channel Width: 0.2 cm
Channel distance from the edge of scintillator: 0.5 cm
Channel radius at corners: 1 cm
Parameters of module fsdmodule:
Size: 16 cm x 16 cm
Thickness: 5 cm
Channel Depth (ratio of thickness): 0.75
Channel Width: 0.2 cm
Channel distance from the edge of scintillator: 0.5 cm
Channel radius at corners: 1 cm
FSD size is 192 cm x 160 cm x 5 cm
FSD contains 372 modules in total,
small sized modules: 156
medium sized modules: 144
large sized modules: 72
FSD volume center coordinates: (16.4394, 0, 1002.5) cm
File added
/* Copyright (C) 2023 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen
/* Copyright (C) 2023-2025 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen
SPDX-License-Identifier: GPL-3.0-only
Authors: Volker Friese, Lukas Chlad [committer] */
Authors: Radim Dvorak, Volker Friese, Lukas Chlad [committer] */
/** @file create_fsdgeo_firstRealistic.C
** @author Lukas Chlad <l.chlad@gsi.de>
......@@ -8,8 +8,8 @@
** @version 1.0
**
** This macro creates a FSD geometry in ROOT format to be used as input
** for the transport simulation. The labeling of versions is ment
** to correspond with beampipe versions v21[e-h]. Letter 'z' is reserved
** for the transport simulation. The labeling of versions is ment
** to correspond with beampipe versions v24[e-h]. Letter 'z' is reserved
** for parking position.
**
** It allows to create module stacks of varying sizes.
......@@ -32,7 +32,7 @@ std::pair<Bool_t, std::pair<Double_t,Double_t> > calc_x_trans_and_y_rot(Double_t
// ====== Main function =====
// ============================================================================
void create_fsdgeo_firstRealistic(TString geoTag = "v23i")
void create_fsdgeo_firstRealistic(TString geoTag = "v25i")
{
// ----- Steering variables ---------------------------------------------
Double_t fsdX; // x position (cm) of FSD in cave (front plane center)
......@@ -49,22 +49,25 @@ void create_fsdgeo_firstRealistic(TString geoTag = "v23i")
fsdX = calcPosxRoty.second.first;
fsdRotY = calcPosxRoty.second.second;
if (geoTag == "v23e") {
if (geoTag == "v25e") {
comment = "Position for maximum deflection angle, e.g. E_kin_beam = 5A GeV and 100% magnetic field strength";
}
else if (geoTag == "v23f") {
else if (geoTag == "v25f") {
comment = "Position for NO deflection angle";
}
else if (geoTag == "v23g") {
comment = "Position for Au beam at 3.3A GeV/c and 50% magnetic field strength";
else if (geoTag == "v25g") {
comment = "to be add later";
}
else if (geoTag == "v23h") {
else if (geoTag == "v25h") {
comment = "Position for Au beam at 12A GeV/c and 100% magnetic field strength";
}
else if (geoTag == "v23i") {
else if (geoTag == "v25i") {
comment = "Position for Au beam at 11 AGeV/c (10 AGeV) and 100% magnetic field strength";
}
else if (geoTag == "v23z") {
else if (geoTag == "v25i") {
comment = "Position for Au beam at 11 AGeV/c (10 AGeV) and 100% magnetic field strength";
}
else if (geoTag == "v25z") {
fsdX = -90;
fsdY = -70;
fsdZ = 1756;
......@@ -212,7 +215,7 @@ void create_fsdgeo_firstRealistic(TString geoTag = "v23i")
const Double_t plasticSizeZ = 0.5*wallThickness; // half-thickness
const TString plasticUnitName = "unit_Plastic";
TGeoVolume* plasticUnit = new TGeoVolumeAssembly(plasticUnitName);
std::cout << "Module array in one quadrant is "
<< std::ceil(holeRadius/smallCellSize) << "x" << std::ceil(holeRadius/smallCellSize) << " small module size is taken by hole in FSD,"
<< nSmallCells_X << "x" << nSmallCells_Y << " small modules, "
......@@ -500,7 +503,7 @@ TGeoVolume* ConstructGeneralModule(const char* name, Double_t sizeXY, Double_t c
shiftFiberDownRight->RegisterYourself();
TGeoTranslation *shiftFiberDownLeft = new TGeoTranslation(Form("shiftFiberDownLeft%s",suffix.Data()) ,-0.5*sizeXY+edgeMargin+bendRadius,-0.5*sizeXY+edgeMargin+bendRadius,0.5*cellThickness*(1.-fiberDepth));
shiftFiberDownLeft->RegisterYourself();
//fiber parts
TGeoBBox *fiberBoxHorizontal = new TGeoBBox(Form("fiberBoxHorizontal%s",suffix.Data()), 0.5*sizeXY-edgeMargin-bendRadius, 0.5*fiberWidth, 0.5*fiberDepth*cellThickness);
......@@ -563,7 +566,7 @@ TGeoVolume* ConstructGeneralModule(const char* name, Double_t sizeXY, Double_t c
std::pair<Bool_t, std::pair<Double_t,Double_t> > calc_x_trans_and_y_rot(Double_t zpos, TString geoTag)
{
const TString strPsdTube = "psd_tube"; // node of beampipe containing this string is what we need
TString strPipeFile = "${VMCWORKDIR}/geometry/pipe/pipe_v21" + geoTag(3,geoTag.Length()) + ".geo.root";
TString strPipeFile = "${VMCWORKDIR}/geometry/pipe/pipe_v24" + geoTag(3,geoTag.Length()) + ".geo.root";
if(gSystem->ExpandPathName(strPipeFile)){
std::cout << __func__ << ": Error while expanding path to beampipe file!!" << std::endl;
return std::make_pair(kFALSE,std::make_pair(0.,0.));
......@@ -632,7 +635,7 @@ std::pair<Bool_t, std::pair<Double_t,Double_t> > calc_x_trans_and_y_rot(Double_t
// | .
// | / . /<-.
// | / . / `. angle of rotation around y axis
// | / . / ;
// | / . / ;
// ^ value of x_lt / x /-------- "this is 0 but in principle can be different"
// | / . / tan(phi_y) = (x_FSD - x_lt "-x_glob") / (z_FSD - z_lt - z_glob)
// | / . / from here we get:
......
/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Abhishek Kumar Sharma, Omveer Singh, Shreya Roy, Florian Uhlig [committer] */
/*** @author Abhishek Kumar Sharma, Omveer Singh <omvir.ch@gmail.com>
** @date 17 May 2020
** For more details see info file*/
// clang-format off
// 2025-01-28 - AKS- v24a - 2 GEMs as per CBM actual position
// 2022-05-23 - DE - v22k - 2 GEMs out of acceptance / RPC downstream of TOF stack at 25 degrees
// 2022-04-29 - DE - v22j - 2 GEMs in acceptance x = -5 cm / RPC downstream of TOF stack
// 2022-03-27 - DE - v22i - 2 GEMs in acceptance x = -3 cm / RPC downstream of TOF stack
// 2022-03-27 - DE - v22h - 2 GEMs out of acceptance / RPC downstream of TOF stack
// 2022-03-26 - DE - v22g - 2 GEMs out of acceptance / RPC upstream of TOF stack out of acceptance
// 2022-03-25 - DE - v22f - 2 GEMs in acceptance / RPC upstream of TOF stack on z-axis
#include "TClonesArray.h"
#include "TDatime.h"
#include "TFile.h"
#include "TGeoBBox.h"
#include "TGeoCompositeShape.h"
#include "TGeoCone.h"
#include "TGeoManager.h"
#include "TGeoMaterial.h"
#include "TGeoMatrix.h"
#include "TGeoMedium.h"
#include "TGeoPgon.h"
#include "TGeoTube.h"
#include "TGeoVolume.h"
#include "TGeoXtru.h"
#include "TList.h"
#include "TMath.h"
#include "TObjArray.h"
#include "TRandom3.h"
#include "TString.h"
#include "TSystem.h"
#include <cassert>
#include <fstream>
#include <iostream>
#include <stdexcept>
TObjArray* fStations = new TObjArray();
CbmMuchStation* muchSt;
CbmMuchLayer* muchLy;
CbmMuchLayerSide* muchLySd;
// Name of output file with geometry
const TString tagVersion = "_v24a";
//const TString subVersion = "_sis100_1m_lmvm";
const TString geoVersion = "much"; // + tagVersion + subVersion;
const TString FileNameSim = geoVersion + tagVersion + "_mcbm.geo.root?reproducible";
const TString FileNameGeo = geoVersion + tagVersion + "_mcbm_geo.root?reproducible";
const TString FileNameInfo = geoVersion + tagVersion + "_mcbm.geo.info";
const TString FileNamePar = geoVersion + tagVersion + "_mcbm.par.root?reproducible";
// Names of the different used materials which are used to build the modules
// The materials are defined in the global media.geo file
const TString KeepingVolumeMedium = "air";
const TString activemedium = "MUCHargon";
const TString spacermedium = "MUCHnoryl";
const TString Al = "aluminium"; //Al for cooling & support purpose
const TString copper = "copper";
const TString g10 = "G10";
const TString RPCm= "RPCgas";
const TString RPCg= "RPCglass";
// Input parameters for MUCH stations
//********************************************
const Int_t fNst = 2; // Number of stations
Double_t TOF_Z_Front_Stand = 244.5; // this is the TOF box front
Int_t fNlayers = 1; // Number of layers
Double_t fLayersZ0[fNst] = {77.2525, 98.5535}; // Layers Positions
//Double_t fLayersZ0[fNst] = {65.7, 88.7, RpcPositionZ}; // Layers Positions
Int_t fDetType[fNst] = {3, 3}; // Detector type
Double_t fSupportLz[fNst] = {1., 1.}; // (cooling + support)
Double_t fDriftDz = 0.0035; //35 micron copper Drift
Double_t fG10Dz = 0.30; // 3 mm G10
Double_t fActiveLzSector[fNst] = {0.3, 0.3}; // Active volume thickness [cm]
Double_t fFrameLzSector[fNst] = {.3, .3}; // Frame thickness [cm]
Double_t fRpcGlassDz[fNst] = {0.0,0.0}; //Rpc Glass thickness [cm]
Double_t fSpacerPhi = 2.0; // Spacer width in Phi [cm]
Double_t fOverlapR = 2.0; // Overlap in R direction [cm]
Double_t fSpacerR1 = 6.0; // Spacer width in R at low Z[cm]
Double_t fSpacerR2 = 7.0; // Spacer width in R at high Z[cm]
//Size of Modules
//GEM
Double_t dx = 40.0;
Double_t dy1 = 3.75;
Double_t dy2 = 20;
Double_t fX[fNst] = {39.50, 39.0}; //Placement of modules in X [cm]
Double_t fY[fNst] = {0.50, 0.00}; //Placement of modules in Y [cm]
//***********************************************************
// some global variables
TGeoManager* gGeoMan = NULL; // Pointer to TGeoManager instance
TGeoVolume* gModules_station[fNst]; // Global storage for module types
// Forward declarations
void create_materials_from_media_file();
TGeoVolume* CreateStations(int ist);
TGeoVolume* CreateLayersGem(int istn, int ily);
//void SegmentLayerSide(CbmMuchStation *station, CbmMuchLayerSide *layerSide);
fstream infoFile;
void create_MUCH_geometry_v24a_mcbm()
{
// Load FairRunSim to ensure the correct unit system
FairRunSim* sim = new FairRunSim();
// ------- Open info file -----------------------------------------------
TString infoFileName = FileNameInfo;
infoFileName.ReplaceAll("root", "info");
infoFile.open(infoFileName.Data(), fstream::out);
infoFile << "MUCH geometry created with create_MUCH_geometry_v24a_real_mcbm.C" << endl << endl;
infoFile << "Build a mMUCH setup for mCBM with 2 GEM." << endl;
infoFile << "10 mm thick Al plates are used for support and cooling in the "
"GEM modules."
<< endl;
infoFile << "Drift and read-out PCBs (copper coated G10 plates) inserted for "
"realistic material budget for both GEM and RPC modules."
<< endl
<< endl;
infoFile << "No of Modules: " << fNst << " ( GEM )" << endl;
infoFile << "Position of Modules Z [cm]: ";
for (int i = 0; i < fNst; i++)
infoFile << fLayersZ0[i] << " ";
infoFile << endl << endl << "Placement of Modules:" << endl;
infoFile << "Module"
<< "\t"
<< "X [cm]"
<< "\t"
<< "Y [cm]"
<< "\t" << endl;
infoFile << "----------------------" << endl;
for (int i = 0; i < fNst; i++)
infoFile << " " << i + 1 << "\t" << fX[i] << "\t" << fY[i] << endl;
infoFile << "----------------------" << endl;
infoFile << endl << "Al Cooling Plate Thickness [cm]: ";
for (int i = 0; i < fNst; i++)
infoFile << fSupportLz[i] << " ";
infoFile << endl << "Active Volume Thickness [cm]: ";
for (int i = 0; i < fNst; i++)
infoFile << fActiveLzSector[i] << " ";
infoFile << endl << endl << endl << " GEM Module:" << endl;
infoFile << "--------------------------" << 2 * dx << "= cm -------------------------------" << endl;
infoFile << "<--------------------------2*dx------------------------------->" << endl;
infoFile << "^ . |" << endl;
infoFile << "| .... |" << endl;
infoFile << "| ........ |" << endl;
infoFile << "| .............. |" << endl;
infoFile << "| .................. |" << endl;
infoFile << "| ..................... |" << endl;
infoFile << "| ........................ |" << endl;
infoFile << "| ........................... |" << endl;
infoFile << "| .............................. |^" << endl;
infoFile << "| ................................. ||" << endl;
infoFile << "| ................................. |2*dy1 = " << 2 * dy1 << " cm" << endl;
infoFile << 2 * dy2 << " cm = "<<"2*dy2................................. ||" << endl;
infoFile << "| .............................. |^" << endl;
infoFile << "| ........................... |" << endl;
infoFile << "| ........................ |" << endl;
infoFile << "| ..................... |" << endl;
infoFile << "| ................. |" << endl;
infoFile << "| ............. |" << endl;
infoFile << "| ......... |" << endl;
infoFile << "| ...... |" << endl;
infoFile << "| ... |" << endl;
infoFile << "^ . |" << endl;
infoFile << endl;
// Load needed material definition from media.geo file
create_materials_from_media_file();
// Get the GeoManager for later usage
gGeoMan = (TGeoManager*) gROOT->FindObject("FAIRGeom");
gGeoMan->SetVisLevel(10);
// Create the top volume
TGeoBBox* topbox = new TGeoBBox("", 1000., 1000., 2000.);
TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air"));
gGeoMan->SetTopVolume(top);
TString topName = geoVersion + tagVersion + "_mcbm";
TGeoVolume* much = new TGeoVolumeAssembly(topName);
top->AddNode(much, 1);
TGeoVolume* sttn = new TGeoVolumeAssembly("station");
much->AddNode(sttn, 1);
for (Int_t istn = 0; istn < fNst; istn++) {
Double_t stGlobalZ0 = fLayersZ0[istn];
muchSt = new CbmMuchStation(istn, stGlobalZ0);
muchSt->SetRmin(0.);
muchSt->SetRmax(0.);
fStations->Add(muchSt);
gModules_station[istn] = CreateStations(istn);
sttn->AddNode(gModules_station[istn], istn);
}
gGeoMan->CloseGeometry();
gGeoMan->CheckOverlaps(0.0001, "s");
gGeoMan->PrintOverlaps();
much->Export(FileNameSim); // an alternative way of writing the much
TFile* outfile = new TFile(FileNameSim, "UPDATE");
TGeoTranslation* much_placement = new TGeoTranslation("much_trans", -6., 0., 0.);
much_placement->Write();
outfile->Close();
outfile = new TFile(FileNameGeo, "RECREATE");
gGeoMan->Write(); // use this if you want GeoManager format in the output
outfile->Close();
/*
// create medialist for this geometry
TString createmedialist = gSystem->Getenv("VMCWORKDIR");
createmedialist += "/macro/geometry/create_medialist.C";
std::cout << "Loading macro " << createmedialist << std::endl;
gROOT->LoadMacro(createmedialist);
gROOT->ProcessLine("create_medialist(\"\", false)");
*/
top->Draw("ogl");
infoFile.close();
TFile* parfile = new TFile(FileNamePar, "RECREATE");
fStations->Write("stations", 1); // for geometry parameters
parfile->Close();
infoFile.close();
// cout << "par file created" << parfile << endl;
}
void create_materials_from_media_file()
{
// Use the FairRoot geometry interface to load the media which are already defined
FairGeoLoader* geoLoad = new FairGeoLoader("TGeo", "FairGeoLoader");
FairGeoInterface* geoFace = geoLoad->getGeoInterface();
TString geoPath = gSystem->Getenv("VMCWORKDIR");
TString geoFile = geoPath + "/geometry/media.geo";
geoFace->setMediaFile(geoFile);
geoFace->readMedia();
// Read the required media and create them in the GeoManager
FairGeoMedia* geoMedia = geoFace->getMedia();
FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder();
FairGeoMedium* Air = geoMedia->getMedium(KeepingVolumeMedium);
geoBuild->createMedium(Air);
FairGeoMedium* MUCHargon = geoMedia->getMedium(activemedium);
geoBuild->createMedium(MUCHargon);
FairGeoMedium* MUCHnoryl = geoMedia->getMedium(spacermedium);
geoBuild->createMedium(MUCHnoryl);
FairGeoMedium* MUCHsupport = geoMedia->getMedium(Al);
geoBuild->createMedium(MUCHsupport);
FairGeoMedium* copperplate = geoMedia->getMedium(copper);
geoBuild->createMedium(copperplate);
FairGeoMedium* g10plate = geoMedia->getMedium(g10);
geoBuild->createMedium(g10plate);
FairGeoMedium* RPCmedium = geoMedia->getMedium(RPCm);
geoBuild->createMedium(RPCmedium);
FairGeoMedium* RPCmaterial = geoMedia->getMedium(RPCg);
geoBuild->createMedium(RPCmaterial);
}
TGeoVolume* CreateStations(int ist)
{
TString stationName = Form("muchstation%02i", ist + 1);
TGeoVolumeAssembly* station = new TGeoVolumeAssembly(stationName); //, shStation, air);
TGeoVolume* gLayer[fNlayers + 1];
for (int ii = 0; ii < fNlayers; ii++) { // 2 Layers
// Double_t sideDz = fSupportLz[istn] / 2. + fActiveLzSector[istn] / 2.; // distance between side's and layer's centers
muchLy = new CbmMuchLayer(ist, ii, fLayersZ0[ist], 0.);
muchLy->GetSideB()->SetZ(fLayersZ0[ist] );
muchSt->AddLayer(muchLy);
gLayer[ii] = CreateLayersGem(ist, ii);
station->AddNode(gLayer[ii], ii);
}
return station;
}
TGeoVolume* CreateLayersGem(int istn, int ily)
{
TString layerName = Form("muchstation%02ilayer%i", istn + 1, ily + 1);
TGeoVolumeAssembly* volayer = new TGeoVolumeAssembly(layerName);
Double_t SupportDz = fSupportLz[istn] / 2.;
Double_t driftDz = fActiveLzSector[istn] / 2 + fDriftDz / 2.;
Double_t g10Dz = driftDz + fDriftDz / 2. + fG10Dz / 2.;
//Double_t airDz = 0.2;
Double_t moduleZ = fLayersZ0[istn];
Double_t driftZIn = moduleZ - driftDz;
Double_t driftZOut = moduleZ + driftDz;
Double_t g10ZIn = moduleZ - g10Dz;
Double_t g10ZOut = moduleZ + g10Dz ;
Double_t cool_z;
if(istn == 1) {cool_z = g10ZOut + fG10Dz / 2. + SupportDz;}
else {
cool_z = g10ZIn - fG10Dz / 2. - SupportDz;
}
Double_t dz = fActiveLzSector[istn] / 2.; // Active Volume Thickness
Int_t Nsector = 16.0;
Double_t phi0 = TMath::Pi() / Nsector; // azimuthal half widh of each module
//define the spacer dimensions
Double_t tg = (dy2 - dy1) / 2 / dx;
Double_t dd1 = fSpacerPhi * tg;
Double_t dd2 = fSpacerPhi * sqrt(1 + tg * tg);
Double_t sdy1 = dy1 + dd2 - dd1;
Double_t sdy2 = dy2 + dd2 + dd1;
Double_t sdx1 = dx + fSpacerR1; // frame width added
Double_t sdx2 = dx + fSpacerR2; // frame width added
Double_t sdz = fFrameLzSector[istn] / 2.;
//define Additional material as realistic GEM module
Double_t dz_sD = fDriftDz / 2.; //35 micron copper Drift
Double_t dz_sG = fG10Dz / 2.; // 3mm G10
Double_t sdx = sdx2;
Double_t pos[10];
Int_t iMod = 0;
for (Int_t iSide = 0; iSide < 1; iSide++) {
//muchLySd = muchLy->GetSide(iSide);
// Now start adding the GEM modules
for (Int_t iModule = 0; iModule < 1; iModule++) {
Double_t phi = 0; // add 0.5 to not overlap with y-axis for left-right layer separation
Bool_t isBack = iModule % 2;
Char_t cside = (isBack == 0) ? 'f' : 'b';
// correct the x, y positions
pos[0] = fX[istn];
pos[1] = fY[istn];
// different z positions for odd/even modules
pos[2] = moduleZ;
pos[3] = driftZIn;
pos[4] = driftZOut;
pos[5] = g10ZIn;
pos[6] = g10ZOut;
//pos[7] = airDz;
pos[7] = cool_z;
if (iSide != isBack) continue;
if (iModule != 0) iMod = iModule / 2;
muchLySd = muchLy->GetSide(0);
TGeoMedium* argon = gGeoMan->GetMedium(activemedium); // active medium
TGeoMedium* noryl = gGeoMan->GetMedium(spacermedium); // spacer medium
TGeoMedium* copperplate = gGeoMan->GetMedium(copper); // copper Drift medium
TGeoMedium* g10plate = gGeoMan->GetMedium(g10); // G10 medium
TGeoMedium* coolMat = gGeoMan->GetMedium(Al);
//TGeoMedium* Air = gGeoMan->GetMedium(KeepingVolumeMedium); // Air
// Define and place the shape of the modules
TGeoTrap* shapeGem = new TGeoTrap(dz, 0, 0, dx, dy1, dy2, 0, dx, dy1, dy2, 0);
shapeGem->SetName(Form("shStation%02iLayer%i%cModule%03iActiveGemNoHole", istn, ily, cside, iModule));
//------------------------------------------------------Al Cooling Plate--------------------------------------------------------------------
TGeoVolume* voActive;
TGeoTrap* coolGem;
TGeoVolume* voCool;
TGeoVolume* voAir;
coolGem = new TGeoTrap(SupportDz, 0, phi, sdx2, sdy1, sdy2, 0, sdx2, sdy1, sdy2, 0);
coolGem->SetName(Form("shStation%02iLayer%i%cModule%03icoolGem", istn, ily, cside, iModule));
TString CoolName = Form("muchstation%02ilayer%i%ccoolGem%03iAluminum", istn + 1, ily + 1, cside, iModule + 1);
voCool = new TGeoVolume(CoolName, coolGem, coolMat);
voCool->SetLineColor(kYellow);
//-----------------------------------------------------Air-----------------------------------------------
/*TGeoTrap* shapeAir = new TGeoTrap(airDz, 0, 0, dx, dy1, dy2, 0, dx, dy1, dy2, 0);
shapeAir->SetName(Form("shStation%02iLayer%i%cModule%03iActiveNoHole", istn, ily, cside, iModule));
TString airName = Form("muchstation%02ilayer%i%cactive%03igasArgon", istn + 1, ily + 1, cside, iMod + 1);
voAir = new TGeoVolume(airName, shapeAir, Air);
voAir->SetLineColor(kCyan);*/
//------------------------------------------------------Active Volume-----------------------------------------------------
//GEM
TGeoTrap* shapeActive = new TGeoTrap(dz, 0, 0, dx, dy1, dy2, 0, dx, dy1, dy2, 0);
shapeActive->SetName(Form("shStation%02iLayer%i%cModule%03iActiveNoHole", istn, ily, cside, iModule));
TString activeName = Form("muchstation%02ilayer%i%cactive%03igasArgon", istn + 1, ily + 1, cside, iMod + 1);
voActive = new TGeoVolume(activeName, shapeActive, argon);
voActive->SetLineColor(kGreen);
//---------------------------------------------------------Drift & PCB's---------------------------------------------------------------
TString DriftName[2], G10Name[2], AlName;
TGeoVolume *voDrift[2], *voG10[2];
TGeoTrap *DriftGem[2], *G10Gem[2];
for (int iPos = 0; iPos < 2; iPos++) {
Char_t cpos = (iPos == 0) ? 'i' : 'o';
DriftGem[iPos] = new TGeoTrap(dz_sD, 0, phi, sdx, sdy1, sdy2, 0, sdx, sdy1, sdy2, 0);
G10Gem[iPos] = new TGeoTrap(dz_sG, 0, phi, sdx, sdy1, sdy2, 0, sdx, sdy1, sdy2, 0);
DriftGem[iPos]->SetName(Form("shStation%02iLayer%i%cModule%03i%cDrift", istn, ily, cside, iModule, cpos));
DriftName[iPos] =
Form("muchstation%02ilayer%i%cside%03i%ccopperDrift", istn + 1, ily + 1, cside, iMod + 1, cpos);
G10Gem[iPos]->SetName(Form("shStation%02iLayer%i%cModule%03i%cG10", istn, ily, cside, iModule, cpos));
G10Name[iPos] = Form("muchstation%02ilayer%i%cside%03i%cG10", istn + 1, ily + 1, cside, iMod + 1, cpos);
voDrift[iPos] = new TGeoVolume(DriftName[iPos], DriftGem[iPos], copperplate);
voDrift[iPos]->SetLineColor(kRed);
voG10[iPos] = new TGeoVolume(G10Name[iPos], G10Gem[iPos], g10plate);
voG10[iPos]->SetLineColor(28);
}
//------------------------------------------------------------Frame-----------------------------------------------------------------
// Define the trapezoidal Frame
TGeoTrap* shapeFrame = new TGeoTrap(sdz, 0, 0, sdx, sdy1, sdy2, 0, sdx, sdy1, sdy2, 0);
shapeFrame->SetName(Form("shStation%02iLayer%i%cModule%03iFullFrameGemNoHole", istn, ily, cside, iModule));
TString expression = Form("shStation%02iLayer%i%cModule%03iFullFrameGemNoHole-shStation%"
"02iLayer%i%cModule%03iActiveGemNoHole",
istn, ily, cside, iModule, istn, ily, cside, iModule);
TGeoCompositeShape* shFrame = new TGeoCompositeShape(
Form("shStation%02iLayer%i%cModule%03iFinalFrameNoHole", istn, ily, cside, iModule), expression);
TString frameName = Form("muchstation%02ilayer%i%csupport%03i", istn + 1, ily + 1, cside, iMod + 1);
TGeoVolume* voFrame = new TGeoVolume(frameName, shFrame, noryl); // Frame for GEM
voFrame->SetLineColor(kMagenta);
//----------------------------------------------------Placement----------------------------------------------------------------------
// Calculate the phi angle of the sector where it has to be placed
Double_t angle = 90.0; //- (180. / TMath::Pi() * phi0); // convert angle phi from rad to deg
//Double_t angle1 = 180.0;
TGeoRotation* r2 = new TGeoRotation("r2");
//rotate in the vertical plane (per to z axis) with angle
r2->RotateZ(angle);
// if(istn == 0) {r2->RotateX(angle1);}
// if(istn == 1) {r2->RotateX(180.0);}
TGeoTranslation* trans[10];
TGeoHMatrix* incline_mod[10];
for (int i = 0; i < 6; i++) {
trans[i] = new TGeoTranslation("", pos[0] - 58.0, pos[1], pos[i + 2]); // shift GEMs in x, y, z here
incline_mod[i] = new TGeoHMatrix("");
(*incline_mod[i]) = (*trans[i]) * (*r2);
}
volayer->AddNode(voFrame, iMod, incline_mod[0]); // add spacer
volayer->AddNode(voActive, iMod, incline_mod[0]); // add active volume
volayer->AddNode(voDrift[0], iMod, incline_mod[1]); //Drift In
volayer->AddNode(voDrift[1], iMod, incline_mod[2]); //Drift Out
volayer->AddNode(voG10[0], iMod, incline_mod[3]); //G10 In
volayer->AddNode(voG10[1], iMod, incline_mod[4]); //G10 Out
volayer->AddNode(voCool, iMod, incline_mod[5]); // Al Cooling Plate
//volayer->AddNode(voAir, iMod, incline_mod[6]); //Air
TVector3 Position;
Position.SetXYZ(pos[0], pos[1], pos[2]);
cout << pos[2] << " " << pos[3] << " " << pos[4] << " " << pos[5] << " " << pos[6] << " " << pos[7]
<< endl;
muchLySd->AddModule(new CbmMuchModuleGemRadial(fDetType[istn], istn, ily, 0., iModule, Position, dy1,
dy2, dx, dz, muchSt->GetRmin()));
cout<<"stn: "<<istn<<" module: "<<iModule<<endl;
}
}
return volayer;
}
/* Copyright (C) 2020-2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Florian Uhlig, David Emschermann [committer] */
// 2024-12-12 - v24a - DE - first version for PAnda STrAws in mCBM, 4 modules
// 2024-11-25 - v01a - RK - first version
// details concering the copynr of layers, modules and straw assemblies
// 1 0 4 0 1 0 6 4 sample copy number of a straw
// | | / | / \---- number of straw in module (1-128, 3 decimal digits, 7 bits -127)
// | | \-------- number of module in layer (1-36, 2 decimal digits, 6 bits - 63)
// | \------------ number of layer in MuST (1-12, 2 decimal digits, 4 bits - 15)
// \-------------- leading 1 to allow for 0s in layer number
// clang-format off
#include <iostream>
#include "TGeoBBox.h"
#include "TGeoManager.h"
#include "TGeoVolume.h"
void dump_info_file();
using namespace std;
// Name of output file with geometry
const TString tagVersion = "v24a";
// const TString geoVersion = "must_" + tagVersion;
const TString geoVersion = "must_" + tagVersion + "_mcbm";
const TString FileNameSim = geoVersion + ".geo.root?reproducible"; // Reproducible flag removes changing timestamps etc...
const TString FileNameGeo = geoVersion + "_geo.root";
const TString FileNameInfo = geoVersion + ".geo.info";
// Double_t fTranslationZ = 0.; // cm - Z Translation of the whole Geometry
Double_t fTranslation[3] = { 50., 0., 340. + 1.5 }; // cm - Translation of the whole Geometry
// DE-1layer const Int_t nLayer = 1; // number of layers
// DE-1layer Double_t StereoAngle[nLayer] = { 0. }; // X,U,V,X stereo angle of straws
// DE-1layer const Int_t mustlayout[nLayer][nModule] = { { 1 } };
// mCBM 2025
const Int_t nLayer = 4; // number of layers
const Int_t nModule = 1; // number of modules
const Int_t nModuleType = 4; // number of modules types
const Double_t zLayerPitch = 4.0; // distance of module front to module front in z
Double_t StereoAngle[nLayer] = { 0., -5., 5., 0.}; // X,U,V,X stereo angle of straws - mCBM 2025
// Double_t StereoAngle[nLayer] = { 0., 0., 0., 0.}; // X,U,V,X stereo angle of straws
// Double_t StereoAngle[nLayer] = { 0., 5., -5., 0.}; // X,U,V,X stereo angle of straws
const Int_t mustlayout[nLayer][nModule] = { { 1 }, { 1 }, { 1 }, { 1 } };
// mCBM ------------
// DE4 // CBM FAIR
// DE4 const Int_t nLayer = 12; // number of layers
// DE4 const Int_t nModule = 36; // number of modules
// DE4
// DE4 const Int_t mustlayout[nLayer][nModule] =
// DE4 // station 1
// DE4 { { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 // station 2
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 // station 3
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 } };
// DE5 // conical beampipe support in S2 and S3 modules
// DE5 const Int_t mustlayout[nLayer][nModule] =
// DE5 // station 1
// DE5 { { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 // station 2
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 5, 6, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 5, 6, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 5, 6, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 5, 6, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 5, 6, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 5, 6, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 5, 6, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 5, 6, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 // station 3
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 7, 8, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 7, 8, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 7, 8, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 7, 8, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 7, 8, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 7, 8, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 7, 8, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 7, 8, 2, 1, 1, 1, 1, 1, 1, 1 } };
// some global variables
TGeoManager* gGeoMan = NULL; // Pointer to TGeoManager instance
TGeoVolume* gModules[nModuleType]; // Global storage for module types
// Forward declarations
void create_materials_from_media_file();
TGeoVolume* create_must_module_type(Int_t moduleType, Int_t modulecopynr);
void Create_MUST_Geometry_v24a()
{
// Load FairRunSim to ensure the correct unit system
FairRunSim* sim = new FairRunSim();
// Load needed material definition from media.geo file
create_materials_from_media_file();
// Get the GeoManager for later usage
gGeoMan = (TGeoManager*) gROOT->FindObject("FAIRGeom");
gGeoMan->SetVisLevel(10);
// Create the top volume
// TGeoBBox* topbox = new TGeoBBox("", 1000., 1000., 2000.);
TGeoBBox* topbox = new TGeoBBox("", 100., 1000., 2000.);
TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air"));
gGeoMan->SetTopVolume(top);
TGeoVolume* must = new TGeoVolumeAssembly(geoVersion);
top->AddNode(must, 1);
for (Int_t iLayer=1; iLayer <= nLayer; iLayer++)
{
// add layer keeping volume
TString layername = Form("layer%02d", iLayer);
TGeoVolume* layer = new TGeoVolumeAssembly(layername);
Int_t layercopynr = 100 + iLayer;
// cout << "layercopynr " << layercopynr << endl;
must->AddNode(layer, layercopynr);
for (Int_t iModule=1; iModule <= nModule; iModule++)
{
Int_t modulecopynr = layercopynr * 100 + iModule;
// cout << "modulecopynr " << modulecopynr << endl;
gModules[iModule] = create_must_module_type(iModule, modulecopynr);
TGeoRotation* module_rotation = new TGeoRotation();
module_rotation->RotateZ(StereoAngle[iLayer-1]);
TGeoCombiTrans* module_placement = new TGeoCombiTrans(0., 0., (iLayer-1) * zLayerPitch, module_rotation);
layer->AddNode(gModules[iModule], modulecopynr, module_placement);
}
}
gGeoMan->CloseGeometry();
gGeoMan->CheckOverlaps(0.001);
gGeoMan->PrintOverlaps();
gGeoMan->Test();
must->Export(FileNameSim); // an alternative way of writing the must volume
TFile* outfile = new TFile(FileNameSim, "UPDATE");
TGeoTranslation* must_placement =
new TGeoTranslation("must_trans", fTranslation[0], fTranslation[1], fTranslation[2]);
must_placement->Write();
outfile->Close();
outfile = new TFile(FileNameGeo, "RECREATE");
gGeoMan->Write(); // use this is you want GeoManager format in the output
outfile->Close();
dump_info_file();
top->Draw("ogl");
}
void create_materials_from_media_file()
{
// Use the FairRoot geometry interface to load the media which are already defined
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();
// Read the required media and create them in the GeoManager
FairGeoMedia* geoMedia = geoFace->getMedia();
FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder();
//Media
FairGeoMedium *mcarbon = geoMedia->getMedium("TRDcarbon");
if (mcarbon == NULL) Fatal("Main", "FairMedium TRDcarbon not found");
geoBuild->createMedium(mcarbon);
FairGeoMedium *mkapton = geoMedia->getMedium("MUCHkapton");
if (mkapton == NULL) Fatal("Main", "FairMedium MUCHkapton not found");
geoBuild->createMedium(mkapton);
FairGeoMedium *mMUCHargon_co2 = geoMedia->getMedium("MUCHGEMmixture");
if (mMUCHargon_co2 == NULL) Fatal("Main", "FairMedium mMUCHargon_co2 not found");
geoBuild->createMedium(mMUCHargon_co2);
//---------------------------------------------------------------------------------
// FairGeoMedium* mAluminium = geoMedia->getMedium("aluminium");
// if (mAluminium == NULL) Fatal("Main", "FairMedium aluminium not found");
// geoBuild->createMedium(mAluminium);
//
// FairGeoMedium* mMylar = geoMedia->getMedium("mylar");
// if (mMylar == NULL) Fatal("Main", "FairMedium mylar not found");
// geoBuild->createMedium(mMylar);
//
// FairGeoMedium* mIron = geoMedia->getMedium("iron"); // TODO should be tungsten?
// if (mIron == NULL) Fatal("Main", "FairMedium iron not found");
// geoBuild->createMedium(mIron);
//
// FairGeoMedium* mAir = geoMedia->getMedium("air");
// if (mAir == NULL) Fatal("Main", "FairMedium air not found");
// geoBuild->createMedium(mAir);
}
TGeoVolume* create_must_module_type(Int_t moduleType, Int_t modulecopynr)
{
TString modulename = Form("module%02d", moduleType);
TGeoVolume* module = new TGeoVolumeAssembly(modulename);
//------------------------------------------------------------------
TGeoMedium* carbon = gGeoMan->GetMedium("TRDcarbon"); // Carbon
TGeoMedium* kapton = gGeoMan->GetMedium("MUCHkapton"); // Kapton
TGeoMedium* argon_co2 = gGeoMan->GetMedium("MUCHGEMmixture"); // active medium (Ar + CO2)
//------------------------------------------------------------------
// not used TGeoMedium* medAl = gGeoMan->GetMedium("aluminium");
// not used if (medAl == NULL) Fatal("Main", "Medium vacuum not found");
// not used
// not used TGeoMedium* medMylar = gGeoMan->GetMedium("mylar");
// not used if (medMylar == NULL) Fatal("Main", "Medium mylar not found");
// not used
// not used TGeoMedium* medIron = gGeoMan->GetMedium("iron");
// not used if (medIron == NULL) Fatal("Main", "Medium iron not found");
// not used
// not used TGeoMedium* medAir = gGeoMan->GetMedium("air");
// not used if (medAir == NULL) Fatal("Main", "Medium air not found");
// Straw tube dimensions
Double_t strawLength = 230.0; // cm
Double_t strawRadius = 0.245; // cm
Double_t wallThickness = 0.0065; // cm
// Module and straw layout parameters
Int_t nStrawsPerColumnLong = 64; // DE
Int_t nStrawsPerModuleS3 = 32; // DE
Double_t spacingY = 0.550; // cm // DE
Double_t spacingX = 0.525; // cm // DE
Double_t offsetX = spacingX / 2.0;
//Double_t size_module_long = std::ceil(spacingX * nStrawsPerColumnLong); // DE
Double_t xwidth_module_long = 34.0; // cm // DE
// (34 / 2. - 31.75 * 0.525 + 15.75 * 0.525) * 2 = 17.2
Double_t xwidth_module_S3 = 17.2; // cm // DE
Double_t moduleXSize = xwidth_module_S3;
Double_t moduleYSize = strawLength;
Double_t moduleZSize = 3.;
Double_t frameThick = 0.05;
Double_t moduleXPos = 0., moduleYPos = 0., moduleZPos = moduleZSize/2.;
// Carbon SideFrame
TGeoBBox* must_vert_frame = new TGeoBBox("must_vert_frame", frameThick/2., moduleYSize/2., moduleZSize/2.); // vertical
TGeoVolume* must_vert_frame_vol = new TGeoVolume("framevert", must_vert_frame, carbon);
must_vert_frame_vol->SetLineColor(kBlue);
TGeoTranslation* frameTransPosX = new TGeoTranslation(moduleXPos + (moduleXSize/2. - frameThick/2.), moduleYPos, moduleZPos);
module->AddNode(must_vert_frame_vol, 1, frameTransPosX);
TGeoTranslation* frameTransNegX = new TGeoTranslation(moduleXPos - (moduleXSize/2. - frameThick/2.), moduleYPos, moduleZPos);
module->AddNode(must_vert_frame_vol, 2, frameTransNegX);
TGeoVolumeAssembly* strawAssembly = new TGeoVolumeAssembly("strawAssembly");
TGeoRotation* strawRotat = new TGeoRotation("strawRotat", 0.0, 90.0, 0.0);
// Common straw geometry
TGeoTube* strawGas = new TGeoTube("StrawGas", 0, strawRadius - wallThickness, strawLength / 2.);
TGeoVolume* volStrawGas = new TGeoVolume("strawgasactive", strawGas, argon_co2);
volStrawGas->SetLineColor(kGreen);
volStrawGas->SetTransparency(40);
strawAssembly->AddNode(volStrawGas,1);
TGeoTube* strawWall = new TGeoTube("StrawWall", strawRadius - wallThickness, strawRadius, strawLength / 2.);
TGeoVolume* volStrawWall = new TGeoVolume("strawwallpassive", strawWall, kapton);
volStrawWall->SetLineColor(kRed);
//volStrawWall->SetTransparency(40);
strawAssembly->AddNode(volStrawWall,1);
// not used double strawRad = 0.25, straw_Length = moduleYSize;
// not used double stGasRad = 0.24, stGas_Length = straw_Length;
// not used double wireRad = 0.01, wire_Length = straw_Length;
// not used
// not used auto wireShape = new TGeoTube("wireShape", 0., wireRad, wire_Length/2.);
// not used TGeoVolume* wireVol = new TGeoVolume("MustWire", wireShape, medIron);
// not used wireVol->SetLineColor(kRed);
// not used strawAssembly->AddNode(wireVol,1);
// not used
// not used auto stGasShape = new TGeoTube("stGasShape", wireRad, stGasRad, stGas_Length/2.);
// not used TGeoVolume* stGasVol = new TGeoVolume("MustStGas", stGasShape, medAir);
// not used stGasVol->SetTransparency();
// not used stGasVol->SetLineColor(kYellow);
// not used strawAssembly->AddNode(stGasVol,1);
// not used
// not used auto strawShape = new TGeoTube("strawShape", stGasRad, strawRad, straw_Length/2.);
// not used TGeoVolume* strawVol = new TGeoVolume("MustStraw", strawShape, medMylar);
// not used strawVol->SetLineColor(kGreen);
// not used strawAssembly->AddNode(strawVol,1);
Int_t strawcopynr = 0;
Int_t nStraws = 2 * nStrawsPerModuleS3;
for ( int istraw = 0; istraw < nStraws; istraw++ )
{
Double_t xoffset = 15.75;
Double_t yoffset = -spacingY/2.;
if (istraw%2==1)
{
xoffset = 15.25;
yoffset = spacingY/2.;
}
TGeoTranslation* strawTrans = new TGeoTranslation((istraw/2 - xoffset) * spacingX, 0., yoffset + moduleZPos);
TGeoCombiTrans* strawCombi = new TGeoCombiTrans(*strawTrans, *strawRotat);
strawcopynr = modulecopynr * 1000 + istraw + 1;
// cout << "strawcopynr " << strawcopynr << endl;
module->AddNode(strawAssembly, strawcopynr, strawCombi);
// TGeoTranslation* strawTrans = new TGeoTranslation((istraw/2 - 15.75) * spacingX, 0., -spacingY/2.);
// TGeoTranslation* strawTrans = new TGeoTranslation((istraw/2 - 15.25) * spacingX, 0., spacingY/2.);
}
// for ( int istraw = 0 ; istraw < nStrawsPerModuleS3 ; istraw++ )
// {
// TGeoTranslation* strawTrans = new TGeoTranslation((istraw - 15.75) * spacingX, 0., -spacingY/2.);
// TGeoCombiTrans* strawCombi = new TGeoCombiTrans(*strawTrans, *strawRotat);
//
// strawcopynr = modulecopynr * 1000 + istraw + 1;
// // cout << "strawcopynr " << strawcopynr << endl;
// module->AddNode(strawAssembly, strawcopynr, strawCombi);
// }
//
// for ( int istraw = 0 ; istraw < nStrawsPerModuleS3 ; istraw++ ) {
// TGeoTranslation* strawTrans = new TGeoTranslation((istraw - 15.25) * spacingX, 0., spacingY/2.);
// TGeoCombiTrans* strawCombi = new TGeoCombiTrans(*strawTrans, *strawRotat);
//
// strawcopynr = modulecopynr * 1000 + istraw + 1 + 32;
// // cout << "strawcopynr " << strawcopynr << endl;
// module->AddNode(strawAssembly, strawcopynr, strawCombi);
// }
return module;
}
void dump_info_file()
{
TDatime datetime; // used to get timestamp
printf("writing summary information file: %s\n", FileNameInfo.Data());
FILE* ifile;
ifile = fopen(FileNameInfo.Data(), "w");
if (ifile == NULL) {
printf("error opening %s\n", FileNameInfo.Data());
exit(1);
}
fprintf(ifile, "#\n## %s information file\n#\n\n", geoVersion.Data());
fprintf(ifile, "# created %d\n\n", datetime.GetDate());
fprintf(ifile, "# MUST geometry consisting fo %d layers\n", nLayer);
for (Int_t iLayer=1; iLayer <= nLayer; iLayer++)
{
fprintf(ifile, "Layer %d: number of modules: %d module type %d StereoAngle %f.1 degrees\n", iLayer, nModule, nModuleType, StereoAngle[iLayer]);
}
fprintf(ifile, "Front module x-offset %f.1 cm\n", fTranslation[0]);
fprintf(ifile, "Front module y-offset %f.1 cm\n", fTranslation[1]);
fprintf(ifile, "Front module z-offset %f.1 cm\n", fTranslation[2]);
fprintf(ifile, "\n");
fclose(ifile);
}
/* Copyright (C) 2020-2024 Institut fuer Kernphysik, Goethe-Universitaet Frankfurt
SPDX-License-Identifier: GPL-3.0-only
Authors: Phillip Klaus [committer], Eoin Clerkin */
/*
* ROOT Macro to create the geometry of the Micro Vertex Detector
* of the CBM experiment at FAIR. It is used within the CbmRoot
* framework to simulate the detector response.
*
* The main output of this script is a .root file containing the
* the volumes of the detector. The media those volumes are
* filled with / made of are referenced in this script only by name
* and defined in a separate ASCII file named media.geo.
*
* For some components, their medium is a surrogate with equivalent
* material budget to simplify the design and speed-up simulation or
* because we depend on educated estimates regarding their material
* composition for the time being.
*/
/*
* Parameters defining the MVD
*/
static const int numStations = 2;
// all units are in cm
// Float_t quadrantBeamOffset[4] = {0.54, 0.54, 0.82, 1.04};
Float_t carrierClampOverlap = 0.0;
// Float_t heatsinkWidth[4] = {23.1, 31.1, 34.34, 37.7};
Float_t heatsinkHeight = 37.7;
// Heatsink actual thickness: 1.0cm
// The additional contributionof 0.7cm is a surrogate
// for FEBs incl. FR-4, copper, connectors:
Float_t heatsinkThickness = 1.0 + 0.7;
Float_t topPlateThickness = 1.0;
Float_t fpcWidth = 1.9;
Float_t fpcThickness = 0.0009;
Float_t glueThickness = 0.0008;
/* MIMOSIS dimensions
https://indico.gsi.de/contributionDisplay.py?contribId=8&sessionId=6&confId=4759
30.97 x 16.55 mm2 (of which the lower 3mm inactive) */
Float_t sensorDimensionsActive[3] = {3.097, 1.355, 0.005};
Float_t sensorDimensionsPassive[3] = {3.097, 0.300, 0.005};
// Formula for the carrier dimensions height ([1]):
// nrows * sensorDimensionsActive[1] + (nrows - 1) * sensorActiveOverlap +
// sensorDimensionsPassive[1] + fpcWidth + 0.1 eg. for nrows=2:
// 2*1.355-(2-1)*0.05+0.3+1.9+0.1
/* MIMOSIS-based tr (tracking) variant (general purpose tracking variant) */
/* Commented out for TwoStation Generation
Float_t stationPosition[4] = {4.0, 8.0, 12.0, 16.0};
int sensorRows[4] = {4, 4, 7, 7};
int sensorCols[4] = {2, 2, 4, 4};
Float_t heatsinkWidth[4] = {31.1, 31.1, 37.7, 37.7};
Float_t quadrantBeamOffset[4] = {0.54, 0.54, 1.04, 1.04};
Float_t carrierDimensions[4][3] = {{7.19, 7.57, 0.038},
{7.19, 7.57, 0.038},
{13.39, 11.485, 0.038},
{13.39, 11.485, 0.038}};
int carrierMaterials[4] = {1, 1, 1, 1}; // 0 = diamond, 1 = TPG
*/
Float_t stationPosition[2] = {4.0, 16.0};
int sensorRows[2] = {4, 7};
int sensorCols[2] = {2, 4};
Float_t heatsinkWidth[2] = {31.1, 37.7};
Float_t quadrantBeamOffset[2] = {0.54, 1.04};
Float_t carrierDimensions[2][3] = {{7.19, 7.57, 0.038},
{13.39, 11.485, 0.038}};
int carrierMaterials[2] = {1, 1}; // 0 = diamond, 1 = TPG
/* MIMOSIS-based vx (vertexing) variant (dedicated vertexing variant) */
/*
Float_t stationPosition[4] = {1.0, 6.0, 11.0, 16.0};
int sensorRows[4] = {2, 4, 7, 7};
int sensorCols[4] = {1, 2, 4, 4};
Float_t heatsinkWidth[4] = {23.1, 31.1, 37.7, 37.7};
Float_t quadrantBeamOffset[4] = {0.54, 0.54, 1.04, 1.04};
Float_t carrierDimensions[4][3] = {{4.10, 4.96, 0.015},
{7.19, 7.57, 0.038},
{13.39, 11.485, 0.038},
{13.39, 11.485, 0.038}};
int carrierMaterials[4] = {0, 1, 1, 1}; // 0 = diamond, 1 = TPG
*/
Float_t sensorActiveOverlap = 0.05;
Float_t sensorPitch = sensorDimensionsActive[1] - sensorActiveOverlap;
Float_t sensorSpacing = 0.0; // realistically: 0.01 (100um)
// if an artificially exploded view is desired, adjust this parameter:
Float_t explosion =
1.0; // set to 1. for no explosion, and 3. for a heavy explosion
/*
* Procedural code assemblying the MVD
*/
void Create_MVD() {
TGeoVolume *top;
TGeoVolume *stations[numStations];
TGeoVolume *quadrant;
TCanvas *c3D = new TCanvas("c3D", "MVD Layout", 1600, 1200);
TGeoManager *manager = new TGeoManager("Chamber Layout", "Chamber Layout");
TGeoMaterial *mat = new TGeoMaterial("vacuum", 0., 0., 0.);
TGeoMaterial *matAl = new TGeoMaterial("aluminium", 0., 0., 0.);
TGeoMaterial *matSilicon = new TGeoMaterial("silicon", 0, 0, 0);
TGeoMaterial *matGlue = new TGeoMaterial("MVD_glue", 0, 0, 0);
TGeoMaterial *matTPG = new TGeoMaterial("MVD_tpg", 0, 0, 0);
TGeoMaterial *matDiamond = new TGeoMaterial("MVD_cvd_diamond", 0, 0, 0);
TGeoMaterial *matFPC = new TGeoMaterial("MVD_fpc", 0, 0, 0);
TGeoMedium *vac = new TGeoMedium("vacuumMed", 0, mat);
TGeoMedium *Al = new TGeoMedium("AlMed", 2, matAl);
TGeoMedium *silicon = new TGeoMedium("siliconMed", 2, matSilicon);
TGeoMedium *glue = new TGeoMedium("glueMed", 2, matGlue);
TGeoMedium *tpg = new TGeoMedium("tpgMed", 2, matTPG);
TGeoMedium *diamond = new TGeoMedium("diamondMed", 2, matDiamond);
TGeoMedium *FPC = new TGeoMedium("FPCMed", 2, matFPC);
top = manager->MakeBox("Top", vac, 300., 300., 300.);
manager->SetTopVolume(top);
TGeoVolume *mvd = new TGeoVolumeAssembly("TwoStation");
TGeoVolume *sensorActive = manager->MakeBox(
"sensorActive", silicon, sensorDimensionsActive[0] / 2,
sensorDimensionsActive[1] / 2, sensorDimensionsActive[2] / 2);
TGeoVolume *sensorPassive = manager->MakeBox(
"sensorPassive", silicon, sensorDimensionsPassive[0] / 2,
sensorDimensionsPassive[1] / 2, sensorDimensionsPassive[2] / 2);
TGeoVolume *sensorGlue = manager->MakeBox(
"sensorGlue", glue, sensorDimensionsActive[0] / 2,
(sensorDimensionsActive[1] + sensorDimensionsPassive[1]) / 2,
glueThickness / 2);
sensorActive->SetTransparency(0);
sensorActive->SetLineColor(kAzure + 3);
sensorPassive->SetTransparency(0);
sensorPassive->SetLineColor(kCyan + 1);
sensorGlue->SetTransparency(0);
sensorGlue->SetLineColor(kCyan - 10);
Float_t fpcGlueDimensions[2] = {sensorDimensionsActive[0],
sensorPitch - sensorActiveOverlap};
TGeoVolume *fpcGlue =
manager->MakeBox("fpcGlue", glue, fpcGlueDimensions[0] / 2,
fpcGlueDimensions[1] / 2, glueThickness / 2);
fpcGlue->SetTransparency(0);
fpcGlue->SetLineColor(kCyan - 10);
TGeoTranslation T;
TGeoRotation R;
TGeoCombiTrans *M;
char station_name[30], quadrant_name[30], carrier_name[30], heatsink_name[30],
heatsinkpart_name[30], cable_name[30];
int heatsinkpartno = 0, cablepartno = 0;
// --- Sensor Assembly
TGeoVolume *sensor = new TGeoVolumeAssembly("sensor");
// Glue
Float_t x_offset = -sensorDimensionsActive[0] / 2;
Float_t y_offset =
-(sensorDimensionsActive[1] + sensorDimensionsPassive[1]) / 2;
Float_t z_offset = glueThickness / 2;
T.SetTranslation(x_offset, y_offset, -z_offset);
R.SetAngles(0., 0., 0.);
M = new TGeoCombiTrans(T, R);
sensor->AddNode(sensorGlue, 1, M);
// Active
x_offset = -sensorDimensionsActive[0] / 2;
y_offset = -sensorDimensionsActive[1] / 2;
z_offset = sensorDimensionsActive[2] / 2 + glueThickness;
T.SetTranslation(x_offset, y_offset, -z_offset);
M = new TGeoCombiTrans(T, R);
sensor->AddNode(sensorActive, 1, M);
// Passive
y_offset = -sensorDimensionsPassive[1] / 2 - sensorDimensionsActive[1];
T.SetTranslation(x_offset, y_offset, -z_offset);
M = new TGeoCombiTrans(T, R);
sensor->AddNode(sensorPassive, 1, M);
for (int i = 0; i < numStations; i++) {
// --- Station Assembly
cout << "Station " << i << endl;
sprintf(station_name, "station_S%i", i);
TGeoVolume *station = new TGeoVolumeAssembly(station_name);
// --- Quadrant Assembly
sprintf(quadrant_name, "quadrant_S%i", i);
quadrant = new TGeoVolumeAssembly(quadrant_name);
// --- Heatsink Assembly
sprintf(heatsink_name, "heatsink_S%i", i);
TGeoVolume *heatsink = new TGeoVolumeAssembly(heatsink_name);
// --- Carrier
sprintf(carrier_name, "carrier_S%i", i);
Float_t cd[3] = {carrierDimensions[i][0], carrierDimensions[i][1],
carrierDimensions[i][2]};
TGeoMedium *carrierMedium;
int carrierColor;
switch (carrierMaterials[i]) {
case 0:
carrierMedium = diamond;
carrierColor = kGray;
break;
case 1:
carrierMedium = tpg;
carrierColor = kGray + 3;
break;
default:
printf("Carrier material index not found: %i\n", carrierMaterials[i]);
exit(1);
}
TGeoVolume *carrier =
manager->MakeBox(carrier_name, carrierMedium, cd[0] / 2, cd[1] / 2, cd[2] / 2);
carrier->SetTransparency(0);
carrier->SetLineColor(carrierColor);
T.SetTranslation(-cd[0] / 2, -cd[1] / 2, 0);
R.SetAngles(0., 0., 0.);
M = new TGeoCombiTrans(T, R);
quadrant->AddNode(carrier, 1, M);
// --- Heatsink
R.SetAngles(0., 0., 0.);
// first part next to carrier
sprintf(heatsinkpart_name, "heatsinkpart_%i", heatsinkpartno++);
Float_t height_1 = heatsinkWidth[i] / 2 - cd[1] + carrierClampOverlap -
quadrantBeamOffset[i];
Float_t width_1 = heatsinkWidth[i] / 2 + quadrantBeamOffset[i];
Float_t thickness = heatsinkThickness;
TGeoVolume *hs_part1 = manager->MakeBox(heatsinkpart_name, Al, width_1 / 2.,
height_1 / 2., thickness / 2.);
hs_part1->SetTransparency(10);
hs_part1->SetLineColor(kGray);
T.SetTranslation(-width_1 / 2, -height_1 / 2 - cd[1] + carrierClampOverlap,
0);
M = new TGeoCombiTrans(T, R);
quadrant->AddNode(hs_part1, 1, M);
// second part next to carrier
sprintf(heatsinkpart_name, "heatsinkpart_%i", heatsinkpartno++);
Float_t height_2 = heatsinkWidth[i] - height_1 - width_1;
Float_t width_2 = heatsinkWidth[i] / 2 - cd[0] + carrierClampOverlap +
quadrantBeamOffset[i];
TGeoVolume *hs_part2 = manager->MakeBox(heatsinkpart_name, Al, width_2 / 2,
height_2 / 2, thickness / 2);
hs_part2->SetTransparency(10);
hs_part2->SetLineColor(kGray);
T.SetTranslation(-width_2 / 2 - cd[0] + carrierClampOverlap, -height_2 / 2,
0);
M = new TGeoCombiTrans(T, R);
quadrant->AddNode(hs_part2, 1, M);
// element to fill top and bottom if needed
sprintf(heatsinkpart_name, "heatsinkpart_%i", heatsinkpartno++);
Float_t height = (heatsinkHeight - heatsinkWidth[i]) / 2;
if (height > 0.1) {
TGeoVolume *hs_part3 =
manager->MakeBox(heatsinkpart_name, Al, heatsinkWidth[i] / 2,
height / 2, heatsinkThickness / 2);
hs_part3->SetTransparency(10);
hs_part3->SetLineColor(kGray);
T.SetTranslation(0, height / 2 + heatsinkWidth[i] / 2, 0);
M = new TGeoCombiTrans(T, R);
heatsink->AddNode(hs_part3, 1, M);
T.SetTranslation(0, -(height / 2 + heatsinkWidth[i] / 2), 0);
M = new TGeoCombiTrans(T, R);
heatsink->AddNode(hs_part3, 2, M);
T.SetTranslation(0, 0, 0);
M = new TGeoCombiTrans(T, R);
station->AddNode(heatsink, 1, M);
}
// --- Sensors
cout << " # of sensors per quadrant: " << sensorCols[i] * sensorRows[i]
<< endl;
R.SetAngles(0., 0., 0.);
TGeoVolume *cable;
Float_t cableDimensions[2] = {0.0, 0.0};
for (int k = 0; k < sensorCols[i]; k++) {
if (k % 2 == 0) {
// Make new cable with correct dimensions
sprintf(cable_name, "cable_%i", cablepartno++);
cableDimensions[0] = cd[0] - sensorDimensionsActive[0] * k;
cableDimensions[1] = fpcWidth;
cable = manager->MakeBox(cable_name, FPC, cableDimensions[0] / 2,
cableDimensions[1] / 2, fpcThickness / 2);
cable->SetTransparency(0);
cable->SetLineColor(kSpring - 1);
}
for (int l = 0; l < sensorRows[i]; l++) {
Float_t y_offset = -sensorPitch * l;
Float_t z_offset = cd[2] / 2;
R.SetAngles(0., 0., 0.);
Float_t x_offset = -sensorDimensionsActive[0] * k;
if (l % 2 == 0) // front side
z_offset = -z_offset;
if (l % 2 == 1) // back side
{
R.SetAngles(0., 180., 180.);
x_offset -= sensorDimensionsActive[0];
}
T.SetTranslation(x_offset, y_offset, z_offset);
M = new TGeoCombiTrans(T, R);
quadrant->AddNode(sensor, k * sensorRows[i] + l, M);
if (k % 2 == 0) {
// add FPC and glue for the cable
Float_t directional_z_offset = 0.0;
directional_z_offset += glueThickness; // sensor glue
directional_z_offset += sensorDimensionsActive[2]; // sensor
directional_z_offset +=
(fpcThickness + glueThickness) * (k / 2); // fpcAssembly pitch
// fpcGlue
Float_t fpcGlue_x_offset =
-fpcGlueDimensions[0] / 2 - sensorDimensionsActive[0] * k;
Float_t fpcGlue_y_offset = -fpcGlueDimensions[1] / 2 -
sensorPitch * (l + 1) -
sensorDimensionsPassive[1];
Float_t fpcGlue_z_offset = z_offset;
directional_z_offset += glueThickness / 2;
if (l % 2 == 0) // front side
fpcGlue_z_offset -= directional_z_offset;
if (l % 2 == 1) // back side
fpcGlue_z_offset += directional_z_offset;
T.SetTranslation(fpcGlue_x_offset, fpcGlue_y_offset,
fpcGlue_z_offset);
R.SetAngles(0., 0., 0.);
M = new TGeoCombiTrans(T, R);
quadrant->AddNode(fpcGlue, 1, M);
if (k != sensorCols[i] - 1) {
T.SetTranslation(fpcGlue_x_offset - fpcGlueDimensions[0],
fpcGlue_y_offset, fpcGlue_z_offset);
R.SetAngles(0., 0., 0.);
M = new TGeoCombiTrans(T, R);
quadrant->AddNode(fpcGlue, 1, M);
}
// cable
Float_t fpc_x_offset =
-cableDimensions[0] / 2 - sensorDimensionsActive[0] * k;
Float_t fpc_y_offset = -cableDimensions[1] / 2 -
sensorPitch * (l + 1) -
sensorDimensionsPassive[1];
Float_t fpc_z_offset = z_offset;
directional_z_offset += glueThickness / 2;
directional_z_offset += fpcThickness / 2;
if (l % 2 == 0) // front side
fpc_z_offset -= directional_z_offset;
if (l % 2 == 1) // back side
fpc_z_offset += directional_z_offset;
T.SetTranslation(fpc_x_offset, fpc_y_offset, fpc_z_offset);
R.SetAngles(0., 0., 0.);
M = new TGeoCombiTrans(T, R);
quadrant->AddNode(cable, l + 1, M);
}
}
}
for (int j = 0; j < 4; j++) {
cout << " Quadrant " << j << endl;
Float_t x_sign = (j == 0 || j == 3) ? 1. : -1.;
Float_t y_sign = (j == 0 || j == 1) ? -1. : 1.;
T.SetTranslation(x_sign * quadrantBeamOffset[i],
y_sign * quadrantBeamOffset[i], 0);
R.SetAngles(0., 0., -90. * j);
M = new TGeoCombiTrans(T, R);
station->AddNode(quadrant, j, M);
}
T.SetTranslation(0, 0, explosion * stationPosition[i]);
R.SetAngles(0., 0., 0.);
M = new TGeoCombiTrans(T, R);
mvd->AddNode(station, 1, M);
station->Draw("");
gPad->GetView()->RotateView(90, 180);
char filename[30];
sprintf(filename, "mvd.root.S%i.pdf", i);
c3D->SaveAs(filename);
stations[i] = station;
}
// Add top and bottom mounting plates
double depth =
stationPosition[numStations - 1] - stationPosition[0] + heatsinkThickness;
TGeoVolume *top_bottom_plate = manager->MakeBox(
"top_bottom_plate", Al, heatsinkWidth[numStations - 1] / 2,
topPlateThickness / 2, depth / 2);
top_bottom_plate->SetTransparency(10);
top_bottom_plate->SetLineColor(kGray);
T.SetTranslation(0, +heatsinkHeight / 2 + topPlateThickness / 2,
depth / 2 + stationPosition[0] - heatsinkThickness / 2);
M = new TGeoCombiTrans(T, R);
mvd->AddNode(top_bottom_plate, 1, M);
T.SetTranslation(0, -heatsinkHeight / 2 - topPlateThickness / 2,
depth / 2 + stationPosition[0] - heatsinkThickness / 2);
M = new TGeoCombiTrans(T, R);
mvd->AddNode(top_bottom_plate, 2, M);
// Demonstration target:
// TGeoVolume *target = manager->MakeBox("target", silicon, 0.5, 0.5, 0.05);
// mvd->AddNode(target, 1);
top->AddNode(mvd, 2, new TGeoTranslation(0,0,-40));
// Standard checks, to be executed at least before submitting a new geo
manager->CloseGeometry();
manager->CheckOverlaps(0.001, "s");
top->CheckOverlaps(0.001, "s");
top->FindOverlaps();
quadrant->CheckOverlaps(0.001, "s");
manager->CheckGeometryFull();
// done with standard checks
// Open a file for writing a reporoducible format
TFile *outfile = new TFile("mvd_v25a.geo.root?reproducible", "RECREATE");
top->Write(); // Write top volume
// Also add transformation matrix to place in space:
TGeoTranslation *mvd_trans = new TGeoTranslation("", 0., 0., 0.0);
TGeoRotation *mvd_rot = new TGeoRotation();
TGeoCombiTrans *mvd_combi_trans = new TGeoCombiTrans(*mvd_trans, *mvd_rot);
//mvd_combi_trans->Write("trans");
outfile->Close();
mvd->Draw("ogl");
// station->Draw("ogl");
// quadrant->Draw("ogl");
// quadrant->Draw("");
// quadrant->Raytrace();
// top->Draw("");
// gPad->GetView()->ShowAxis();
// top->Raytrace();
}
## MVD Simulation Geometry
This repository contains files necessary to (re-) create the
CbmRoot simulation geometry of the Micro Vertex Detector (MVD).
Imported files from https://git.cbm.gsi.de/mvd/simulation-geometry
Branches in this repo contain other versions of the MVD simulation geometry
/* Copyright (C) 2013-2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Volker Friese, David Emschermann [committer] */
/******************************************************************************
** Creation of beam pipe geometry in ROOT format (TGeo).
**
** @file create_pipegeo_v16.C
** @author Volker Friese <v.friese@gsi.de>
** @date 11.10.2013
**
** The beam pipe is composed of carbon with a thickness of 0.5 mm. It is
** placed directly into the cave as mother volume.
** The pipe consists of a number of parts. Each part has a PCON
** shape. The beam pipe inside the RICH is part of the RICH geometry;
** the beam pipe geometry thus excludes the z range of the RICH in case
** the latter is present in the setup.
*****************************************************************************/
// 2025.02.07 - DE - add NCAL mockup to v20a
// 2020.05.05 - DE - update table dimensions and position measured by Christian Sturm
// 2018.08.23 - DE - shorten the table length from 400 cm to 250 cm
#include "TGeoManager.h"
#include "TGeoPcon.h"
#include "TGeoTube.h"
#include <iomanip>
#include <iostream>
using namespace std;
// ------------- Other global variables -----------------------------------
// ---> TGeoManager (too lazy to write out 'Manager' all the time
TGeoManager* gGeoMan = NULL; // will be set later
// ----------------------------------------------------------------------------
// ============================================================================
// ====== Main function =====
// ============================================================================
void create_platform_v24a()
{
// ----- Define platform parts ----------------------------------------------
/** For v24a (mCBM) **/
TString geoTag = "v24a_mcbm";
// Double_t platform_angle = 25.; // rotation angle around y-axis
// Double_t platform_angle = 19.; // rotation angle around y-axis
Double_t platform_angle = 0.; // rotation angle around y-axis
// Double_t platX_offset = -230.; // offset to the right side along x-axis
Double_t platX_offset = -25.1; // offset along x-axis
Double_t platY_offset = 0.0; // offset along y-axis
Double_t platZ_offset = 13.7; // offset along z-axis
Double_t sizeX = 100.0; // table width // until 15.05.2020: 80.0;
Double_t sizeY = 98.5; // table height // until 15.05.2020: 80.0;
Double_t sizeZ = 215.5; // table length // until 15.05.2020: 250.0;
// Double_t endZ = 450.0; // ends at z = 450.0
// /** For v16b (SIS 300) **/
// TString geoTag = "v16b";
// Double_t sizeX = 725.0; // symmetric in x
// Double_t sizeY = 234.0; // without rails
// Double_t sizeZ = 455.0; // long version
// Double_t endZ = 540.0; // ends at z = 450.0
// Double_t beamY = 570.0; // nominal beam height
Double_t beamY = 200.0; // nominal beam height
Double_t posX = 0;
Double_t posY = -beamY + sizeY / 2.; // rest on the floor at -beamY
Double_t posZ = +sizeZ / 2.;
// --------------------------------------------------------------------------
// ------- Geometry file name (output) ----------------------------------
TString geoFileName = "platform_";
geoFileName = geoFileName + geoTag + ".geo.root";
// --------------------------------------------------------------------------
// ------- Open info file -----------------------------------------------
TString infoFileName = geoFileName;
infoFileName.ReplaceAll("root", "info");
fstream infoFile;
infoFile.open(infoFileName.Data(), fstream::out);
infoFile << "Platform geometry created with create_platform_v24a.C" << std::endl << std::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();
// // ---> 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");
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");
// --------------------------------------------------------------------------
// -------------- Create geometry and top volume -------------------------
gGeoMan = (TGeoManager*) gROOT->FindObject("FAIRGeom");
gGeoMan->SetName("PLATFORMgeom");
TGeoVolume* top = new TGeoVolumeAssembly("top");
gGeoMan->SetTopVolume(top);
TString platformName = "platform_";
platformName += geoTag;
TGeoVolume* platform = new TGeoVolumeAssembly(platformName.Data());
// --------------------------------------------------------------------------
// ----- Create ---------------------------------------------------------
TGeoBBox* platform_base = new TGeoBBox("", sizeX / 2., sizeY / 2., sizeZ / 2.);
TGeoVolume* platform_vol = new TGeoVolume("platform", platform_base, air);
platform_vol->SetLineColor(kBlue);
platform_vol->SetTransparency(70);
TGeoTranslation* platform_trans = new TGeoTranslation("", posX, posY, posZ);
platform->AddNode(platform_vol, 1, platform_trans);
infoFile << "sizeX : " << setprecision(2) << sizeX << " cm " << endl
<< "sizeY : " << setprecision(2) << sizeY << " cm " << endl
<< "sizeZ : " << setprecision(2) << sizeZ << " cm " << endl
<< endl;
infoFile << "posX : " << setprecision(2) << posX << " cm " << endl
<< "posY : " << setprecision(2) << posY << " cm " << endl
<< "posZ : " << setprecision(2) << posZ << " cm " << endl
<< endl;
infoFile << "offsetX : " << setprecision(2) << platX_offset << " cm " << endl
<< "offsetY : " << setprecision(2) << platY_offset << " cm " << endl
<< "offsetZ : " << setprecision(2) << platZ_offset << " cm " << endl
<< endl;
// --------------- Finish -----------------------------------------------
top->AddNode(platform, 1);
// ----- Create ncal -------------------------------------------------
//=======================================================================================
// -------------- Create geometry and top volume -------------------------
TString ncalName = "ncal_v24a";
// gGeoMan->SetTopVolume(top);
// TGeoVolume* ncal = new TGeoVolumeAssembly(ncalName.Data());
// --------------------------------------------------------------------------
// Laenge 50.0 cm
// Durchmesser 14.0 cm
const Bool_t IncludeOuterRing = true; // false; // true, plot out 6 detectors
const Bool_t IncludeInnerCore = true; // false; // true, plot inner detectors
// start and stop angles
Double_t angle1 = 0; // closed
Double_t angle2 = 360; // closed
Double_t gxoff = 0; // global offset in x
Double_t gyoff = 0; // global offset in y
Double_t gzoff = 380; // global offset in z
gxoff -= platX_offset; // global offset in x
gyoff -= platY_offset; // global offset in y
gzoff -= platZ_offset; // global offset in z
// 7 ncal array
Double_t rmax50 = 14.0 / 2.;
Double_t rmin50 = 0.;
Double_t length50 = 50.0;
Double_t nscale = 1.01;
// TGeoVolume* vncal00 = gGeoManager->MakePgon("ncal00", air, 0, 360, 6, 2); // 1 section
TGeoVolume* vncal00 = gGeoManager->MakePgon("ncal00", air, angle1, angle2, 6, 4); // 2 sections
TGeoPgon *pgon = (TGeoPgon*)(vncal00->GetShape());
pgon->DefineSection(0,-length50 /2., rmin50, rmax50); // detector
pgon->DefineSection(1, length50 /2., rmin50, rmax50); // detector
pgon->DefineSection(2, length50 /2. , rmin50, rmax50/2.); // light guide
pgon->DefineSection(3, length50 /2.+10, rmin50, rmax50/2.); // light guide
vncal00->SetLineColor(kGreen);
TGeoTranslation* tra1 = new TGeoTranslation("tra1", gxoff + cos( 30 * acos(-1)/180) * 2 * rmax50 * nscale, gyoff + sin( 30 * acos(-1)/180) * 2 * rmax50 * nscale, gzoff + length50 / 2.);
if (IncludeOuterRing) platform->AddNode(vncal00, 1, tra1);
TGeoTranslation* tra2 = new TGeoTranslation("tra2", gxoff + cos( 90 * acos(-1)/180) * 2 * rmax50 * nscale, gyoff + sin( 90 * acos(-1)/180) * 2 * rmax50 * nscale, gzoff + length50 / 2.);
if (IncludeOuterRing) platform->AddNode(vncal00, 2, tra2);
TGeoTranslation* tra3 = new TGeoTranslation("tra3", gxoff + cos(150 * acos(-1)/180) * 2 * rmax50 * nscale, gyoff + sin(150 * acos(-1)/180) * 2 * rmax50 * nscale, gzoff + length50 / 2.);
if (IncludeOuterRing) platform->AddNode(vncal00, 3, tra3);
TGeoTranslation* tra4 = new TGeoTranslation("tra4", gxoff + cos(210 * acos(-1)/180) * 2 * rmax50 * nscale, gyoff + sin(210 * acos(-1)/180) * 2 * rmax50 * nscale, gzoff + length50 / 2.);
if (IncludeOuterRing) platform->AddNode(vncal00, 4, tra4);
TGeoTranslation* tra5 = new TGeoTranslation("tra5", gxoff + cos(270 * acos(-1)/180) * 2 * rmax50 * nscale, gyoff + sin(270 * acos(-1)/180) * 2 * rmax50 * nscale, gzoff + length50 / 2.);
if (IncludeOuterRing) platform->AddNode(vncal00, 5, tra5);
TGeoTranslation* tra6 = new TGeoTranslation("tra6", gxoff + cos(330 * acos(-1)/180) * 2 * rmax50 * nscale, gyoff + sin(330 * acos(-1)/180) * 2 * rmax50 * nscale, gzoff + length50 / 2.);
if (IncludeOuterRing) platform->AddNode(vncal00, 6, tra6);
TGeoTranslation* tra7 = new TGeoTranslation("tra7", gxoff + 0., gyoff + 0., gzoff + length50 / 2.);
if (IncludeInnerCore) platform->AddNode(vncal00, 7, tra7);
// --------------- Finish -----------------------------------------------
// TGeoTranslation* tra_ncal = new TGeoTranslation("tra_ncal", gxoff, gyoff, gzoff);
// platform->AddNode(ncal, 1, tra_ncal);
cout << endl << endl;
gGeoMan->CloseGeometry();
gGeoMan->CheckOverlaps(0.001);
gGeoMan->PrintOverlaps();
gGeoMan->Test();
platform->Export(geoFileName); // an alternative way of writing the platform volume
TFile* geoFile = new TFile(geoFileName, "UPDATE");
// rotate the platform around y
TGeoRotation* platform_rotation = new TGeoRotation();
platform_rotation->RotateY(platform_angle);
// TGeoCombiTrans* platform_placement = new TGeoCombiTrans( sin( platform_angle/180.*acos(-1) ) * z1[1]/2., 0., 0., platform_rotation);
TGeoCombiTrans* platform_placement =
new TGeoCombiTrans("platform_rot", platX_offset, platY_offset, platZ_offset, platform_rotation);
// TGeoTranslation* platform_placement = new TGeoTranslation("platform_trans", 0., 0., 0.);
platform_placement->Write();
geoFile->Close();
cout << endl;
cout << "Geometry " << top->GetName() << " written to " << geoFileName << endl;
top->Draw("ogl");
infoFile.close();
}
// ============================================================================
// ====== End of main function =====
// ============================================================================
/* Copyright (C) 2022 Czech Technical University in Prague,
Faculty of Nuclear Sciences and Physical Engineering
SPDX-License-Identifier: GPL-3.0-only
Authors: Petr Chudoba [committer]*/
#include "TGeoArb8.h"
#include "TGeoCompositeShape.h"
#include "TGeoCone.h"
#include "TGeoManager.h"
#include "TGeoMatrix.h"
#include "TGeoSystemOfUnits.h"
#include "TGeoTube.h"
#include "TPad.h"
#include "TROOT.h"
#include "TSystem.h"
#include "TFile.h"
#include "TVector3.h"
#include "iostream"
#include "stdio.h"
#include "cmath"
using namespace std;
using namespace TGeoUnit;
void create_bpipe_geometry_gen(const char* geoTag = "v24f", double beam_deflection_angle=0)
{
//--- Definition of a simple geometry
gSystem->Load("libGeom");
TString geomMngr = "beampipe_";
geomMngr = geomMngr+geoTag;
TGeoManager* geom = new TGeoManager(geomMngr, "CBM beampipe geometry generator for user adjustable angles");
//--- define some materials
TGeoMixture* matCarbonFiber = new TGeoMixture("BP_carbonfiber", 4, 1.5);
matCarbonFiber->AddElement(12.001, 6.0, 0.8926);
matCarbonFiber->AddElement(1.0079, 1.0, 0.0192);
matCarbonFiber->AddElement(35.453, 17.0, 0.0271);
matCarbonFiber->AddElement(15.999, 8.0, 0.0611);
// TGeoMixture* matStainless = new TGeoMixture("BP_stainless", 10, 8.0);
// matStainless->AddElement(12.0, 6.0, 0.00035);
// matStainless->AddElement(51.94, 24.0, 0.175);
// matStainless->AddElement(54.94, 25.0, 0.01);
// matStainless->AddElement(95.94, 42.0, 0.025);
// matStainless->AddElement(14.0, 7.0, 0.0005);
// matStainless->AddElement(58.6934, 28.0, 0.115);
// matStainless->AddElement(30.97, 15.0, 0.000225);
// matStainless->AddElement(31.97, 16.0, 0.000075);
// matStainless->AddElement(27.98, 14.0, 0.005);
// matStainless->AddElement(55.93, 26.0, 0.67135);
TGeoMaterial* matVacuum = new TGeoMaterial("BP_vacuum", 1.e-16, 1.e-16, 1.e-16);
// TGeoMaterial* matAl = new TGeoMaterial("BP_aluminium", 26.9815386, 13, 2.7, 24.01);
// //--- define some media
TGeoMedium* Vacuum = new TGeoMedium("BP_vacuum", 1, matVacuum);
// TGeoMedium* Al = new TGeoMedium("BP_aluminium", 2, matAl);
TGeoMedium* CF = new TGeoMedium("BP_carbonfiber", 3, matCarbonFiber);
// TGeoMedium* Stainless = new TGeoMedium("BP_stainless", 4, matStainless);
// Conus part dimensions
const Double_t conus_lenght = 1585 * mm;
const Double_t conus_rmin1 = 55 * mm;
const Double_t conus_rmax1 = 56 * mm;
const Double_t conus_rmin2 = 125 * mm;
const Double_t conus_rmax2 = 126 * mm;
const Double_t beam_pipe_length = 14460 * mm;
const Double_t beam_pipe_rmin = 90 * mm;
const Double_t beam_pipe_rmax = 92 * mm;
const Double_t dist_to_bellow = 4418 * mm; // center of mass of upstream flange
const Double_t bending_radius = 4737 * mm; // center of mass of downstream flange
const Double_t flange_thickness = 30 * mm;
const Double_t short_segment = 45 * mm;
const Double_t long_segment = 65 * mm;
const Double_t bellow_rmin = 137.5 * mm;
const Double_t bellow_rmax = 142.5 * mm;
const Double_t cone_deflection_angle = 1.277/radian; // from deg to rad
beam_deflection_angle = beam_deflection_angle/radian; // from deg to rad
Double_t pipe_deflection_radius = bending_radius+(flange_thickness/2)+(beam_pipe_length/2);
Double_t bellow_deflection_angle = beam_deflection_angle-cone_deflection_angle; // in radians
Double_t alpha = atan((bending_radius*sin(bellow_deflection_angle))/(bending_radius*cos(bellow_deflection_angle)-dist_to_bellow)); // in radians
Double_t direction=1.0;
if (alpha!=0){
direction=alpha/abs(alpha);
}
// Center of mass points of bellow flanges
TVector3 p_b0(0,0,flange_thickness/2);
TVector3 p_b6(bending_radius*sin(bellow_deflection_angle),0,bending_radius*cos(bellow_deflection_angle)-dist_to_bellow);
// Vectors defining axis of each part of bellow
TVector3 b0(0,0,flange_thickness); // axis vector of the upstream flange
TVector3 b1(short_segment*sin(alpha/4),0,short_segment*cos(alpha/4)); // axis vector of the first bellow segment
TVector3 b2(long_segment*sin(alpha),0,long_segment*cos(alpha)); // axis vector of the second bellow segment
TVector3 b3; // axis vector of the third (middle) bellow segment - init only
TVector3 b4(long_segment*sin(alpha+bellow_deflection_angle),0,long_segment*cos(alpha+bellow_deflection_angle)); // axis vector of the fourth bellow segment
TVector3 b5(short_segment*sin((alpha/4)+bellow_deflection_angle),0,short_segment*cos((alpha/4)+bellow_deflection_angle)); // axis vector of the fifth bellow segment
TVector3 b6(flange_thickness*sin(bellow_deflection_angle),0,flange_thickness*cos(bellow_deflection_angle)); // axis vector of the downstream flange
b3 = (p_b6-(1./2)*b6-b5-b4)-(p_b0+(1./2)*b0+b1+b2); // axis vector of the third (middle) bellow segment
TVector3 pipe_vec(beam_pipe_length*sin(bellow_deflection_angle),0,beam_pipe_length*cos(bellow_deflection_angle));
Double_t middle_segment = b3.Mag();
// Angles of separate part of bellow
Double_t beta0 = direction*b0.Theta();
Double_t beta1 = direction*b1.Theta();
Double_t beta2 = direction*b2.Theta();
Double_t beta3 = direction*b3.Theta();
Double_t beta4 = direction*b4.Theta();
Double_t beta5 = direction*b5.Theta();
Double_t beta6 = direction*b6.Theta();
// Normal vectors for CTub cut planes for bellow segments
TVector3 n01(-sin((beta0-beta1)),0,-cos((beta0-beta1)));
TVector3 n12(-sin((beta1-beta2)/2),0,cos((beta1-beta2)/2));
TVector3 n21(sin((beta2-beta1)/2),0,-cos((beta2-beta1)/2));
TVector3 n23(-sin((beta2-beta3)/2),0,cos((beta2-beta3)/2));
TVector3 n32(sin((beta3-beta2)/2),0,-cos((beta3-beta2)/2));
TVector3 n34(-sin((beta3-beta4)/2),0,cos((beta3-beta4)/2));
TVector3 n43(sin((beta4-beta3)/2),0,-cos((beta4-beta3)/2));
TVector3 n45(-sin((beta4-beta5)/2),0,cos((beta4-beta5)/2));
TVector3 n54(sin((beta5-beta4)/2),0,-cos((beta5-beta4)/2));
TVector3 n56(-sin((beta5-beta6)),0,cos((beta5-beta6)));
//-----------------------DEFINITION OF TRANSFORMATIONS--------------------------------------------------------------------------------------
TGeoTranslation orig_translation("orig_translation", -0.15707676 * mm, 0, 3230 * mm);
TGeoTranslation orig_translation_cone("orig_translation_cone", -0.15707676 * mm, 0, 1645 * mm);
TGeoRotation orig_rotation("orig_rotation");
orig_rotation.RotateY(cone_deflection_angle*radian);
TGeoHMatrix orig_combi = orig_rotation * orig_translation;
TGeoHMatrix orig_combi_cone = orig_rotation * orig_translation_cone;
TGeoHMatrix* origin_combi = new TGeoHMatrix(orig_combi);
TGeoHMatrix* origin_combi_cone = new TGeoHMatrix(orig_combi_cone);
TGeoRotation* rot_sts_conus_connection = new TGeoRotation("rot_sts_conus_connection");
rot_sts_conus_connection->RotateZ(180);
TGeoCombiTrans* ctr_sts_conus_connection = new TGeoCombiTrans(0, 0, -1600 * mm, rot_sts_conus_connection);
TGeoRotation* rotation_of_sts_tube = new TGeoRotation("rotation_of_sts_tube");
rotation_of_sts_tube->RotateZ(180);
rotation_of_sts_tube->RotateY(-cone_deflection_angle*radian);
TGeoCombiTrans* ctr_sts_tube = new TGeoCombiTrans(0.3707676 * mm, 0, -1631.001 * mm, rotation_of_sts_tube);
TVector3 aux_vec;
aux_vec=(1./2)*b0;
TGeoRotation* rot_b0 = new TGeoRotation("rot_b0");
rot_b0->RotateY(beta0*radian);
TGeoCombiTrans* ctr_b0 = new TGeoCombiTrans(aux_vec.X(),aux_vec.Y(),aux_vec.Z(),rot_b0);
aux_vec=aux_vec+(1./2)*(b0+b1);
TGeoRotation* rot_b1 = new TGeoRotation("rot_b1");
rot_b1->RotateY(beta1*radian);
TGeoCombiTrans* ctr_b1 = new TGeoCombiTrans(aux_vec.X(),aux_vec.Y(),aux_vec.Z(),rot_b1);
aux_vec=aux_vec+(1./2)*(b1+b2);
TGeoRotation* rot_b2 = new TGeoRotation("rot_b2");
rot_b2->RotateY(beta2*radian);
TGeoCombiTrans* ctr_b2 = new TGeoCombiTrans(aux_vec.X(),aux_vec.Y(),aux_vec.Z(),rot_b2);
aux_vec=aux_vec+(1./2)*(b2+b3);
TGeoRotation* rot_b3 = new TGeoRotation("rot_b3");
rot_b3->RotateY(beta3*radian);
TGeoCombiTrans* ctr_b3 = new TGeoCombiTrans(aux_vec.X(),aux_vec.Y(),aux_vec.Z(),rot_b3);
aux_vec=aux_vec+(1./2)*(b3+b4);
TGeoRotation* rot_b4 = new TGeoRotation("rot_b4");
rot_b4->RotateY(beta4*radian);
TGeoCombiTrans* ctr_b4 = new TGeoCombiTrans(aux_vec.X(),aux_vec.Y(),aux_vec.Z(),rot_b4);
aux_vec=aux_vec+(1./2)*(b4+b5);
TGeoRotation* rot_b5 = new TGeoRotation("rot_b5");
rot_b5->RotateY(beta5*radian);
TGeoCombiTrans* ctr_b5 = new TGeoCombiTrans(aux_vec.X(),aux_vec.Y(),aux_vec.Z(),rot_b5);
aux_vec=aux_vec+(1./2)*(b5+b6);
TGeoRotation* rot_b6 = new TGeoRotation("rot_b6");
rot_b6->RotateY(beta6*radian);
TGeoCombiTrans* ctr_b6 = new TGeoCombiTrans(aux_vec.X(),aux_vec.Y(),aux_vec.Z(),rot_b6);
aux_vec=aux_vec+(1./2)*(b6+pipe_vec);
TGeoRotation rot_psd_tube_loc("rot_psd_tube_loc");
rot_psd_tube_loc.RotateY(beta6*radian);
TGeoTranslation tr_psd_tube_loc("tr_psd_tube", aux_vec.X(),aux_vec.Y(),aux_vec.Z());
TGeoHMatrix ctr_psd_tube_aux = orig_combi*tr_psd_tube_loc*rot_psd_tube_loc;
TGeoHMatrix* ctr_psd_tube = new TGeoHMatrix(ctr_psd_tube_aux);
//------------------------------------DEFINITIONS OF VOLUMES----------------------------------------
//--- make the top container volume
Double_t worldx = 800 * mm;
Double_t worldy = 220 * mm;
Double_t worldz = 18100 * mm;
TString assemblyName = "pipe_";
assemblyName=assemblyName+geoTag;
TGeoVolumeAssembly* full_assembly = new TGeoVolumeAssembly(assemblyName);
geom->SetTopVolume(full_assembly);
full_assembly->SetVisibility(kTRUE);
TGeoVolume* conical_beam_pipe = new TGeoVolumeAssembly("conical_beam_pipe");
conical_beam_pipe->SetVisibility(kFALSE);
TGeoVolume* vacuum_conical_beam_pipe = new TGeoVolumeAssembly("vacuum_conical_beam_pipe");
vacuum_conical_beam_pipe->SetVisibility(kFALSE);
TGeoVolume* bellow_ass = new TGeoVolumeAssembly("Bellow assembly");
bellow_ass->SetVisibility(kFALSE);
TGeoVolume* vacuum_bellow_ass = new TGeoVolumeAssembly("Vacuum_bellow assembly");
vacuum_bellow_ass->SetVisibility(kFALSE);
// DOWNSTREAM_CARBON-FIBRE_RICH_MUCH_FLANGE_TO_BELLOW_ASS------------------------------------------------------------------------------------
TGeoBBox* rich_much_flange_box = new TGeoBBox("rich_much_flange_box", 15.2, 15.2, 1.5);
TGeoTube* rich_much_flange_hole = new TGeoTube("rich_much_flange_hole", 0., 12.6, 1.6);
TGeoCompositeShape* rich_much_flange_composite =
new TGeoCompositeShape("flange_composite_rich", "rich_much_flange_box-rich_much_flange_hole");
TGeoVolume* rich_much_downstream_flange =
new TGeoVolume("rich_much_downstream_flange", rich_much_flange_composite, CF);
rich_much_downstream_flange->SetLineColor(kGray);
// VACUUM IN THE FLANGE----------------------------------------------------------------------------------------------
TGeoTube* vacuum_flange_hole = new TGeoTube("vacuum_flange_hole", 0., 12.5, 1.5);
TGeoVolume* vacuum_downstream_flange =
new TGeoVolume("vacuum_downstream_flange", vacuum_flange_hole, Vacuum);
vacuum_downstream_flange->SetLineColor(kRed);
// CONICAL_BEAM_PIPE----------------------------------------------------------------------------------------------------------
TGeoCone* conus = new TGeoCone("conus", conus_lenght, conus_rmin1, conus_rmax1, conus_rmin2, conus_rmax2);
TGeoVolume* conus_volume = new TGeoVolume("conus_volume", conus, CF);
conus_volume->SetLineColor(kGray);
//-------------------------------VACUUM IN CONE-------------------------------------------------------------------
TGeoCone* vacuum_conus = new TGeoCone("vacuum_conus", conus_lenght, 0, conus_rmin1, 0, conus_rmin2);
TGeoVolume* vacuum_conus_volume = new TGeoVolume("vacuum_conus_volume", vacuum_conus, Vacuum);
vacuum_conus_volume->SetLineColor(kGreen);
// CONNECTING TUBE--------------------------------------------------------------------------------------------------------------------------------------------------------
TGeoCtub* tube_connection = new TGeoCtub("tube_connection", 55. * mm, 56. * mm, 15. * mm, 0., 360., -0.022286009, 0., -0.999751636, 0., 0., 1.);
TGeoVolume* tube_connection_volume = new TGeoVolume("tube_connection_volume", tube_connection, CF);
tube_connection_volume->SetLineColor(kGray);
//------------------------VACUUM IN THE CONNECTING TUBE--------------------------------------------------------------
TGeoCtub* vacuum_tube_connection = new TGeoCtub("vacuum_tube_connection", 0. * mm, 55. * mm, 15. * mm, 0., 360., -0.022286009, 0., -0.999751636, 0., 0., 1.);
TGeoVolume* vacuum_tube_connection_volume = new TGeoVolume("vacuum_tube_connection_volume", vacuum_tube_connection, Vacuum);
vacuum_tube_connection_volume->SetLineColor(kGreen);
// STS tube-----------------------------------------------------------------------------------------------------
TGeoCtub* tube_connection_sts = new TGeoCtub("tube_connection_sts", 55. * mm, 56. * mm, 15. * mm, 0., 360., 0., 0., -1., 0.011143697, 0., 0.999937907);
TGeoVolume* tube_connection_sts_volume = new TGeoVolume("tube_connection_sts_volume", tube_connection_sts, CF);
tube_connection_sts_volume->SetLineColor(kGray);
//-------------------------------BELLOW DEFINITION----------------------------------------------------------------
//UPSTREAM FLANGE
TGeoBBox* flange_box = new TGeoBBox("flange_box", 15.2, 15.2, 1.5);
TGeoTube* flange_hole = new TGeoTube("flange_hole", 0., 12.5, 1.6);
TGeoCompositeShape* flange_composite = new TGeoCompositeShape("flange_composite", "flange_box-flange_hole");
TGeoVolume* bellow_flange_0 = new TGeoVolume("bellow_flange_0", flange_composite, CF);
bellow_flange_0->SetLineColor(kRed);
//BELLOW SEGMENT 1
TGeoCtub* bellow_s1 = new TGeoCtub("bellow_s1", bellow_rmin, bellow_rmax, short_segment/2-0.001, 0., 360.,
n01.X(), n01.Y(), n01.Z(), n12.X(), n12.Y(), n12.Z());
TGeoVolume* bellow_1 = new TGeoVolume("bellow_s1", bellow_s1, CF);
bellow_1->SetLineColor(kRed);
//BELLOW SEGMENT 2
TGeoCtub* bellow_s2 = new TGeoCtub("bellow_s2", bellow_rmin, bellow_rmax, long_segment/2-0.001, 0., 360.,
n21.X(), n21.Y(), n21.Z(), n23.X(), n23.Y(), n23.Z());
TGeoVolume* bellow_2 = new TGeoVolume("bellow_s2", bellow_s2, CF);
bellow_2->SetLineColor(kRed);
//BELLOW SEGMENT 3
TGeoCtub* bellow_s3 = new TGeoCtub("bellow_s3", bellow_rmin, bellow_rmax, middle_segment/2-0.001, 0., 360.,
n32.X(), n32.Y(), n32.Z(), n34.X(), n34.Y(), n34.Z());
TGeoVolume* bellow_3 = new TGeoVolume("bellow_s3", bellow_s3, CF);
bellow_3->SetLineColor(kRed);
//BELLOW SEGMENT 4
TGeoCtub* bellow_s4 = new TGeoCtub("bellow_s4", bellow_rmin, bellow_rmax, long_segment/2-0.001, 0., 360.,
n43.X(), n43.Y(), n43.Z(), n45.X(), n45.Y(), n45.Z());
TGeoVolume* bellow_4 = new TGeoVolume("bellow_s4", bellow_s4, CF);
bellow_4->SetLineColor(kRed);
//BELLOW SEGMENT 5
TGeoCtub* bellow_s5 = new TGeoCtub("bellow_s5", bellow_rmin, bellow_rmax, short_segment/2-0.001, 0., 360.,
n54.X(), n54.Y(), n54.Z(), n56.X(), n56.Y(), n56.Z());
TGeoVolume* bellow_5 = new TGeoVolume("bellow_s5", bellow_s5, CF);
bellow_5->SetLineColor(kRed);
//DOWNSTREAM FLANGE
TGeoTube* flange_cyl = new TGeoTube("flange_cyl", 8.9, 15., 1.5);
TGeoVolume* bellow_flange_1 = new TGeoVolume("bellow_flange_1", flange_cyl, CF);
bellow_flange_1->SetLineColor(kRed);
//-------------------------------BELLOW VACUUM DEFINITION----------------------------------------------------------------
//VACUUM UPSTREAM FLANGE
TGeoVolume* vacuum_bellow_flange_0 = new TGeoVolume("vacuum_bellow_flange_0", vacuum_flange_hole, Vacuum);
vacuum_bellow_flange_0->SetLineColor(kGreen);
//VACUUM BELLOW SEGMENT 1
TGeoCtub* vacuum_bellow_s1 = new TGeoCtub("vacuum_bellow_s1", 0, bellow_rmin, short_segment/2, 0., 360.,
n01.X(), n01.Y(), n01.Z(), n12.X(), n12.Y(), n12.Z());
TGeoVolume* vacuum_bellow_1 = new TGeoVolume("vacuum_bellow_s1", vacuum_bellow_s1, Vacuum);
vacuum_bellow_1->SetLineColor(kGreen);
//VACUUM BELLOW SEGMENT 2
TGeoCtub* vacuum_bellow_s2 = new TGeoCtub("vacuum_bellow_s2", 0, bellow_rmin, long_segment/2, 0., 360.,
n21.X(), n21.Y(), n21.Z(), n23.X(), n23.Y(), n23.Z());
TGeoVolume* vacuum_bellow_2 = new TGeoVolume("vacuum_bellow_s2", vacuum_bellow_s2, Vacuum);
vacuum_bellow_2->SetLineColor(kGreen);
//VACUUM BELLOW SEGMENT 3
TGeoCtub* vacuum_bellow_s3 = new TGeoCtub("vacuum_bellow_s3", 0, bellow_rmin, middle_segment/2, 0., 360.,
n32.X(), n32.Y(), n32.Z(), n34.X(), n34.Y(), n34.Z());
TGeoVolume* vacuum_bellow_3 = new TGeoVolume("vacuum_bellow_s3", vacuum_bellow_s3, Vacuum);
vacuum_bellow_3->SetLineColor(kGreen);
//VACUUM BELLOW SEGMENT 4
TGeoCtub* vacuum_bellow_s4 = new TGeoCtub("vacuum_bellow_s4", 0, bellow_rmin, long_segment/2, 0., 360.,
n43.X(), n43.Y(), n43.Z(), n45.X(), n45.Y(), n45.Z());
TGeoVolume* vacuum_bellow_4 = new TGeoVolume("vacuum_bellow_s4", vacuum_bellow_s4, Vacuum);
vacuum_bellow_4->SetLineColor(kGreen);
//VACUUM BELLOW SEGMENT 5
TGeoCtub* vacuum_bellow_s5 = new TGeoCtub("vacuum_bellow_s5", 0, bellow_rmin, short_segment/2, 0., 360.,
n54.X(), n54.Y(), n54.Z(), n56.X(), n56.Y(), n56.Z());
TGeoVolume* vacuum_bellow_5 = new TGeoVolume("vacuum_bellow_s5", vacuum_bellow_s5, Vacuum);
vacuum_bellow_5->SetLineColor(kGreen);
//VACUUM DOWNSTREAM FLANGE
TGeoTube* vacuum_flange_cyl_hole = new TGeoTube("vacuum_flange_cyl_hole", 0., 8.9, 1.5);
TGeoVolume* vacuum_bellow_flange_1 = new TGeoVolume("vacuum_bellow_flange_1", vacuum_flange_cyl_hole, Vacuum);
vacuum_bellow_flange_1->SetLineColor(kGreen);
//------------------------------PSD TUBE-------------------------------------------------------------------------
TGeoTube* psd_tube_s = new TGeoTube("psd_tube_s", beam_pipe_rmin, beam_pipe_rmax, beam_pipe_length/2);
TGeoVolume* psd_tube = new TGeoVolume("psd_tube", psd_tube_s, CF);
psd_tube->SetLineColor(kGray);
//------------------------------VACUUM PSD TUBE-------------------------------------------------------------------------
TGeoTube* vacuum_psd_tube_s = new TGeoTube("vacuum_psd_tube_s", 0. * mm, beam_pipe_rmin, beam_pipe_length/2);
TGeoVolume* vacuum_psd_tube = new TGeoVolume("vacuum_psd_tube", vacuum_psd_tube_s, Vacuum);
vacuum_psd_tube->SetLineColor(kGreen);
//----------------Bellow with flanges-----------------------------
bellow_ass->AddNode(bellow_flange_0, 1, ctr_b0);
bellow_ass->AddNode(bellow_1, 1, ctr_b1);
bellow_ass->AddNode(bellow_2, 1, ctr_b2);
bellow_ass->AddNode(bellow_3, 1, ctr_b3);
bellow_ass->AddNode(bellow_4, 1, ctr_b4);
bellow_ass->AddNode(bellow_5, 1, ctr_b5);
bellow_ass->AddNode(bellow_flange_1, 1, ctr_b6);
//----------------Vacuum in bellow and flanges-----------------------------
vacuum_bellow_ass->AddNode(vacuum_bellow_flange_0, 1, ctr_b0);
vacuum_bellow_ass->AddNode(vacuum_bellow_1, 1, ctr_b1);
vacuum_bellow_ass->AddNode(vacuum_bellow_2, 1, ctr_b2);
vacuum_bellow_ass->AddNode(vacuum_bellow_3, 1, ctr_b3);
vacuum_bellow_ass->AddNode(vacuum_bellow_4, 1, ctr_b4);
vacuum_bellow_ass->AddNode(vacuum_bellow_5, 1, ctr_b5);
vacuum_bellow_ass->AddNode(vacuum_bellow_flange_1, 1, ctr_b6);
//-------------------CONICAL section--------------------------------------------------
conical_beam_pipe->AddNode(rich_much_downstream_flange, 1, new TGeoTranslation(0, 0, 1570 * mm));
conical_beam_pipe->AddNode(conus_volume, 1, new TGeoTranslation(0, 0, 0));
conical_beam_pipe->AddNode(tube_connection_volume, 1, ctr_sts_conus_connection);
// conical_beam_pipe->AddNode(tube_connection_sts_volume, 1, ctr_sts_tube); //inset in STS box - omitted; if used, needs some fine tunning
//-------------------VACUUM in CONICAL section--------------------------------------------------
vacuum_conical_beam_pipe->AddNode(vacuum_conus_volume, 1, new TGeoTranslation(0, 0, 0));
vacuum_conical_beam_pipe->AddNode(vacuum_tube_connection_volume, 1, ctr_sts_conus_connection);
//------------------INSERT into top volume
full_assembly->AddNode(conical_beam_pipe, 1, origin_combi_cone);
full_assembly->AddNode(vacuum_conical_beam_pipe, 1, origin_combi_cone);
full_assembly->AddNode(bellow_ass, 1, origin_combi);
full_assembly->AddNode(vacuum_bellow_ass, 1, origin_combi);
full_assembly->AddNode(psd_tube, 1, ctr_psd_tube);
full_assembly->AddNode(vacuum_psd_tube, 1, ctr_psd_tube);
//beampipe->AddNode(full_assembly,1, new TGeoTranslation(0, 0, 0*mm));
// --- close the geometry
geom->CloseGeometry();
//--- draw the ROOT box
geom->SetVisLevel(4);
full_assembly->Draw();
if (gPad && !gROOT->IsBatch()) gPad->GetViewer3D();
// --------------- Finish -----------------------------------------------
TString geo_bin_filename = "pipe_";
TString geo_name = geo_bin_filename + geoTag;
geo_bin_filename = geo_bin_filename + geoTag + ".geo.root";
TFile* binfile = TFile::Open(geo_bin_filename, "RECREATE");
geom->GetTopVolume()->Write(geo_name); // outputting on the top volume
TGeoTranslation* trans = new TGeoTranslation(0.0, 0.0, 79.0003); // pushing the beampipe to touch the STS
trans->Write("trans");
cout << endl;
cout << "Geometry " << geom->GetTopVolume()->GetName() << " written to " << geo_bin_filename << endl;
binfile->Close();
//--- close the geometry
geom->CloseGeometry();
// gGeoManager->CheckOverlaps(0.000000001);
// gGeoManager->GetListOfOverlaps()->Print();
}
/* Copyright (C) 2020-2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Florian Uhlig, David Emschermann [committer] */
// clang-format off
#include <iostream>
//#include "FairGeoMedium.h"
//#include "FairGeoBuilder.h"
//#include "FairGeoMedia.h"
#include "TGeoManager.h"
#include "TGeoVolume.h"
using namespace std;
// Changelog
// 2024-05-07 - v24a - DE - Based on v21c, shift to new z-position
// 2022-05-23 - v21c - DE - Based on v21b, rotate RICH orthogonal to the z-axis
// 2022-03-08 - v21b - DE - Based on v21a, relocate RICH along the rail onto the 25 degree line by -20 cm
// 2021-09-28 - v21a - SR - Based on v20d, moved RICH according to the TOF v21d
// 2020-05-25 - v20d - AW - Move mRICH by +7.2cm in Z accordingly to the mTOF movement from rev 16441
// 2020-05-20 - v20d - AW - changed positioning to +2.5cm to 25°line (nearer to beam axis) (from Analysis)
// 2020-05-06 - v20b - AW - changed positioning to center on 25° line (without Window)
// 2020-04-02 - v19a - FU - same as v19c but with exported geometry in output file
// 2019-11-28 - v19c - DE - move mRICH +12+7 cm in x direction (same as mTOF v19b) for the Nov 2019 run
// 2017-11-17 - v18d - DE - add aerogel as radiator to the mRICH module
// 2017-11-12 - v18c - DE - push mRICH downstream to z=355 cm for long setup
// 2017-07-19 - v18b - DE - add one level to the geometry hierarchy
// 2017-07-15 - v18b - DE - arrange 4x mRICH detectors in the setup and tilt towards target
void create_rich_v24a_mcbm()
{
gSystem->Load("libGeom");
// Load FairRunSim to ensure the correct unit system
FairRunSim* sim = new FairRunSim();
TString geoFileName = "rich_v24a_mcbm.geo.root?reproducible"; // Reproducible flag removes changing timestamps etc...
TString topNodeName = "rich_v24a_mcbm";
// displace RICH module along the rails on the TOF frame
Double_t XOffset = 0;
Double_t ZOffset = -9-12; // 2024 z-position
Double_t displacement_along_rails = -23.5; // cm for Nickel-58 run
Double_t support_frame_rotation_angle = 0; // 12.5; // degrees
XOffset += +displacement_along_rails *cos( support_frame_rotation_angle * acos(-1)/180 );
ZOffset += -displacement_along_rails *sin( support_frame_rotation_angle * acos(-1)/180 );
// end of displacement along the rails
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();
TGeoManager* gGeoMan = gGeoManager;
FairGeoMedia* geoMedia = geoFace->getMedia();
FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder();
//Media
FairGeoMedium* mAluminium = geoMedia->getMedium("aluminium");
if (mAluminium == NULL) Fatal("Main", "FairMedium aluminium not found");
geoBuild->createMedium(mAluminium);
TGeoMedium* medAl = gGeoMan->GetMedium("aluminium");
if (medAl == NULL) Fatal("Main", "Medium vacuum not found");
FairGeoMedium* mKapton = geoMedia->getMedium("kapton");
if (mKapton == NULL) Fatal("Main", "FairMedium kapton not found");
geoBuild->createMedium(mKapton);
TGeoMedium* medKapton = gGeoMan->GetMedium("kapton");
if (medKapton == NULL) Fatal("Main", "Medium kapton not found");
FairGeoMedium* mAir = geoMedia->getMedium("air");
if (mAir == NULL) Fatal("Main", "FairMedium air not found");
geoBuild->createMedium(mAir);
TGeoMedium* medAir = gGeoMan->GetMedium("air");
if (medAir == NULL) Fatal("Main", "Medium air not found");
FairGeoMedium* mPmtGlas = geoMedia->getMedium("PMTglass");
if (mPmtGlas == NULL) Fatal("Main", "FairMedium vacuum not found");
geoBuild->createMedium(mPmtGlas);
TGeoMedium* medPmtGlas = gGeoMan->GetMedium("PMTglass");
if (medPmtGlas == NULL) Fatal("Main", "Medium vacuum not found");
FairGeoMedium* mNitrogen = geoMedia->getMedium("RICHgas_N2_dis");
if (mNitrogen == NULL) Fatal("Main", "FairMedium RICHgas_N2_dis not found");
geoBuild->createMedium(mNitrogen);
TGeoMedium* medNitrogen = gGeoMan->GetMedium("RICHgas_N2_dis");
if (medNitrogen == NULL) Fatal("Main", "Medium RICHgas_N2_dis not found");
FairGeoMedium* mPMT = geoMedia->getMedium("CsI");
if (mPMT == NULL) Fatal("Main", "FairMedium CsI not found");
geoBuild->createMedium(mPMT);
TGeoMedium* medCsI = gGeoMan->GetMedium("CsI");
if (medCsI == NULL) Fatal("Main", "Medium CsI not found");
FairGeoMedium* mElectronic = geoMedia->getMedium("air");
if (mElectronic == NULL) Fatal("Main", "FairMedium air not found");
geoBuild->createMedium(mElectronic);
TGeoMedium* medElectronic = gGeoMan->GetMedium("air");
if (medElectronic == NULL) Fatal("Main", "Medium air not found");
FairGeoMedium* mAerogel = geoMedia->getMedium("aerogel");
if (mAerogel == NULL) Fatal("Main", "FairMedium aerogel not found");
geoBuild->createMedium(mAerogel);
TGeoMedium* medAerogel = gGeoMan->GetMedium("aerogel");
if (medAerogel == NULL) Fatal("Main", "Medium aerogel not found");
//Dimensions of the RICH prototype [cm]
const Double_t ItemToKapton = 1.85;
// Box
const Double_t boxThickness = 0.3;
const Double_t boxBackThickness = 1.;
const Double_t boxFrontThickness = 0.3;
const Double_t boxXLen = 38.2;
const Double_t boxYLen = 59.7;
const Double_t boxZLen = 25. + boxBackThickness - ItemToKapton;
const Bool_t isRotate90DegZ = false;
// PMT
// PMT specs https://www.hamamatsu.com/resources/pdf/etd/H12700_TPMH1348E.pdf
const Double_t pmtNofPixels = 8;
const Double_t pmtSize = 5.2;
const Double_t pmtSizeHalf = pmtSize / 2.;
const Double_t pmtSensitiveSize = 4.85;
const Double_t pmtPixelSize = 0.6; //pmtSensitiveSize / pmtNofPixels;
const Double_t pmtPixelSizeHalf = pmtPixelSize / 2.;
const Double_t pmtOuterPixelSize = 0.625; //pmtSensitiveSize / pmtNofPixels;
const Double_t pmtOuterPixelSizeHalf = pmtOuterPixelSize / 2.;
const Double_t pmtGap = 0.1;
const Double_t pmtGapHalf = pmtGap / 2.;
const Double_t pmtMatrixGap = 0.1;
const Double_t pmtPixelThickness = 0.1;
const Double_t pmtWindowThickness = 0.00; //0.15
Double_t pmtWindowPixelDistance = 0.0;
if (pmtWindowThickness > 0.0) pmtWindowPixelDistance = 0.0;
const Double_t pmtThickness = pmtPixelThickness + pmtWindowThickness + pmtWindowPixelDistance;
const Double_t pmtZPadding = 3.871;
const Double_t pmtXShift = 2.5;
// Electronics
const Double_t elecLength = 10.;
const Double_t elecWidth = 3. * pmtSize;
const Double_t elecHeight = 2. * pmtSize;
// Aerogel Box
const Double_t aerogelXLen = 20.;
const Double_t aerogelYLen = 20.;
const Double_t aerogelZLen = 3.;
const Double_t aerogelPmtDistance = 10.;
const Double_t aerogelGap = 0.1;
// Imaginary sensitive plane
Bool_t isIncludeSensPlane = false;
const Double_t sensPlaneSize = 200.;
const Double_t sensPlaneBoxDistance = 1.;
//Global positioning
const Double_t boxFrontToTarget = 334.2 + ItemToKapton + boxZLen / 2;
// Create the top volume
TGeoVolume* top = new TGeoVolumeAssembly("top");
gGeoMan->SetTopVolume(top);
// Rich assembly
TGeoVolume* rich = new TGeoVolumeAssembly(topNodeName);
top->AddNode(rich, 1);
// Al box
TGeoRotation* rotBox = new TGeoRotation("rotBox", 0., 0., 0.);
TGeoCombiTrans* trBox = NULL;
if (isRotate90DegZ) {
rotBox->RotateZ(90.);
rotBox->RotateY(0.955); //Tilting of Rich
trBox = new TGeoCombiTrans(0, -pmtXShift - (pmtSize + pmtGap + 1), boxFrontToTarget, rotBox);
}
else {
rotBox->RotateX(0.955); //Tilting of Rich
// Nov 2019 run
rotBox->RotateY(support_frame_rotation_angle);
//trBox = new TGeoCombiTrans(-pmtXShift-(pmtSize + pmtGap + 1)+12.+7., 0, boxFrontToTarget, rotBox);
// Mar2020
trBox = new TGeoCombiTrans(-pmtXShift - (pmtSize + pmtGap + 1) + 6.3 + XOffset + 16. + 5. + 2.5, 0,
boxFrontToTarget + 27. + ZOffset, rotBox);
}
TGeoVolume* boxVol = gGeoMan->MakeBox("box", medAl, boxXLen / 2., boxYLen / 2., boxZLen / 2.);
// rich->AddNode(boxVol, 1, trBox);
rich->AddNode(boxVol, 1);
// Gas
TGeoVolume* gasVol = gGeoMan->MakeBox("Gas", medNitrogen, boxXLen / 2. - boxThickness, boxYLen / 2. - boxThickness,
((boxZLen - boxBackThickness - boxFrontThickness) / 2.));
TGeoTranslation* trGas = new TGeoTranslation(0., 0., (-(boxBackThickness - boxFrontThickness) / 2.));
boxVol->AddNode(gasVol, 1, trGas);
// Front plane from kapton
TGeoVolume* kaptonVol = gGeoMan->MakeBox("kapton", medKapton, boxXLen / 2. - boxThickness,
boxYLen / 2. - boxThickness, boxFrontThickness / 2.);
TGeoTranslation* trKapton = new TGeoTranslation(0., 0., -(boxZLen - boxFrontThickness) / 2.);
boxVol->AddNode(kaptonVol, 1, trKapton);
// Aerogel
TGeoVolume* aerogelVol =
gGeoMan->MakeBox("aerogel", medAerogel, aerogelXLen / 2., aerogelYLen / 2., aerogelZLen / 2.);
Double_t aerogelZ = boxZLen / 2. - boxBackThickness - pmtZPadding - aerogelPmtDistance - aerogelZLen / 2.;
TGeoTranslation* trAerogel1 = new TGeoTranslation(pmtXShift, (aerogelYLen + aerogelGap) / 2., aerogelZ);
TGeoTranslation* trAerogel2 = new TGeoTranslation(pmtXShift, -(aerogelYLen + aerogelGap) / 2., aerogelZ);
gasVol->AddNode(aerogelVol, 1, trAerogel1);
gasVol->AddNode(aerogelVol, 2, trAerogel2);
// PMT
TGeoTranslation* trPmt1 = new TGeoTranslation(pmtSizeHalf + pmtGapHalf, -pmtSize - pmtGap, 0.); // Bottom Right
TGeoTranslation* trPmt2 = new TGeoTranslation(pmtSizeHalf + pmtGapHalf, 0., 0.); // Middle Right
TGeoTranslation* trPmt3 = new TGeoTranslation(pmtSizeHalf + pmtGapHalf, pmtSize + pmtGap, 0.); // Top Right
TGeoTranslation* trPmt4 = new TGeoTranslation(-pmtSizeHalf - pmtGapHalf, -pmtSize - pmtGap, 0.); // Bottom Left
TGeoTranslation* trPmt5 = new TGeoTranslation(-pmtSizeHalf - pmtGapHalf, 0., 0.); // Middle Left
TGeoTranslation* trPmt6 = new TGeoTranslation(-pmtSizeHalf - pmtGapHalf, pmtSize + pmtGap, 0.); // Top Left
TGeoVolume* pmtContVol = new TGeoVolumeAssembly("pmt_cont_vol");
TGeoVolume* pmtVol = new TGeoVolumeAssembly("pmt_vol_0");
TGeoVolume* pmtVol_180 = new TGeoVolumeAssembly("pmt_vol_1");
TGeoVolume* pmtPixelVol =
gGeoMan->MakeBox("pmt_pixel", medCsI, pmtPixelSize / 2., pmtPixelSize / 2., pmtPixelThickness / 2.);
TGeoVolume* pmtPixelVol_outer_outer =
gGeoMan->MakeBox("pmt_pixel", medCsI, pmtOuterPixelSize / 2., pmtOuterPixelSize / 2., pmtPixelThickness / 2.);
TGeoVolume* pmtPixelVol_inner_outer =
gGeoMan->MakeBox("pmt_pixel", medCsI, pmtPixelSize / 2., pmtOuterPixelSize / 2., pmtPixelThickness / 2.);
TGeoVolume* pmtPixelVol_outer_inner =
gGeoMan->MakeBox("pmt_pixel", medCsI, pmtOuterPixelSize / 2., pmtPixelSize / 2., pmtPixelThickness / 2.);
TGeoVolume* pmtWindow = gGeoMan->MakeBox("pmt_Window", medPmtGlas, pmtSizeHalf, pmtSizeHalf, pmtWindowThickness / 2.);
pmtContVol->AddNode(pmtVol_180, 1, trPmt1); // To Power Module // Bottom Right
pmtContVol->AddNode(pmtVol, 2, trPmt2); // Middle // Middle Right
pmtContVol->AddNode(pmtVol, 3, trPmt3); // To Combiner // Top Right
pmtContVol->AddNode(pmtVol_180, 4, trPmt4); // To Power Module // Bottom Left
pmtContVol->AddNode(pmtVol, 5, trPmt5); // Middle // Middle Left
pmtContVol->AddNode(pmtVol, 6, trPmt6); // To Combiner // Top Left
Int_t halfPmtNofPixels = pmtNofPixels / 2;
for (Int_t i = 0; i < pmtNofPixels; i++) {
for (Int_t j = 0; j < pmtNofPixels; j++) {
//check outer Pixels
Double_t x = 0.;
Double_t y = 0.;
bool x_outer = false;
bool y_outer = false;
if (i == 0) {
x = -(halfPmtNofPixels - 1) * pmtPixelSize - pmtOuterPixelSizeHalf;
x_outer = true;
}
else if (i == (pmtNofPixels - 1)) {
x = (halfPmtNofPixels - 1) * pmtPixelSize + pmtOuterPixelSizeHalf;
x_outer = true;
}
else if (i < halfPmtNofPixels) {
x = -((halfPmtNofPixels - 1) - i) * pmtPixelSize - pmtPixelSizeHalf;
x_outer = false;
}
else {
x = (i - halfPmtNofPixels) * pmtPixelSize + pmtPixelSizeHalf;
x_outer = false;
}
if (j == 0) {
y = -(halfPmtNofPixels - 1) * pmtPixelSize - pmtOuterPixelSizeHalf;
y_outer = true;
}
else if (j == (pmtNofPixels - 1)) {
y = (halfPmtNofPixels - 1) * pmtPixelSize + pmtOuterPixelSizeHalf;
y_outer = true;
}
else if (j < halfPmtNofPixels) {
y = -((halfPmtNofPixels - 1) - j) * pmtPixelSize - pmtPixelSizeHalf;
y_outer = false;
}
else {
y = (j - halfPmtNofPixels) * pmtPixelSize + pmtPixelSizeHalf;
y_outer = false;
}
//Double_t x = (i - (halfPmtNofPixels - 1)) * pmtPixelSize - pmtPixelSizeHalf;
//Double_t y = (j - (halfPmtNofPixels - 1)) * pmtPixelSize - pmtPixelSizeHalf;
TGeoTranslation* trij = new TGeoTranslation(x, y, -pmtPixelThickness / 2. + pmtThickness / 2.);
//normal rotated PMT (HV connector at lower side)
uint uid = 18 - ((j % 4) / 2) * 16 - (j % 2) + 2 * i + (1 - (j / 4)) * 100;
//180?? rotated PMT
uint uid_180 = 15 + ((j % 4) / 2) * 16 + (j % 2) - 2 * i + (1 - (j / 4)) * 100;
if (x_outer == true && y_outer == true) {
pmtVol->AddNode(pmtPixelVol_outer_outer, uid, trij);
pmtVol_180->AddNode(pmtPixelVol_outer_outer, uid_180, trij);
}
else if (x_outer == true && y_outer == false) {
pmtVol->AddNode(pmtPixelVol_outer_inner, uid, trij);
pmtVol_180->AddNode(pmtPixelVol_outer_inner, uid_180, trij);
}
else if (x_outer == false && y_outer == true) {
pmtVol->AddNode(pmtPixelVol_inner_outer, uid, trij);
pmtVol_180->AddNode(pmtPixelVol_inner_outer, uid_180, trij);
}
else {
pmtVol->AddNode(pmtPixelVol, uid, trij);
pmtVol_180->AddNode(pmtPixelVol, uid_180, trij);
}
}
}
TGeoTranslation* trWndw = new TGeoTranslation(0., 0., +pmtWindowThickness / 2. - pmtThickness / 2.);
if (pmtWindowThickness > 0.0) {
pmtVol->AddNode(pmtWindow, 1, trWndw);
pmtVol_180->AddNode(pmtWindow, 1, trWndw);
}
//
Double_t pmtContXLen = 2 * (pmtSize + pmtGap);
Double_t pmtContYLen = 3 * (pmtSize + pmtGap);
TGeoTranslation* trPmtCont1 = new TGeoTranslation(-pmtContXLen / 2., pmtContYLen, 0.); //Top Left
TGeoTranslation* trPmtCont2 = new TGeoTranslation(-pmtContXLen / 2., 0., 0.); //Middle Left
TGeoTranslation* trPmtCont3 = new TGeoTranslation(-pmtContXLen / 2., -pmtContYLen, 0.); //Bottom Left
TGeoTranslation* trPmtCont4 = new TGeoTranslation(pmtContXLen / 2., pmtContYLen, 0.); //
TGeoTranslation* trPmtCont5 = new TGeoTranslation(pmtContXLen / 2., 0., 0.); //
TGeoTranslation* trPmtCont6 = new TGeoTranslation(pmtContXLen / 2., -pmtContYLen, 0.); //
TGeoVolume* pmtPlaneVol = new TGeoVolumeAssembly("pmt_plane");
pmtPlaneVol->AddNode(pmtContVol, 00,
trPmtCont1); // Id gives the Address 0x7**0 of the top left DiRICH in a BP (X|Y)
pmtPlaneVol->AddNode(pmtContVol, 03, trPmtCont2);
pmtPlaneVol->AddNode(pmtContVol, 06, trPmtCont3);
pmtPlaneVol->AddNode(pmtContVol, 20, trPmtCont4);
pmtPlaneVol->AddNode(pmtContVol, 23, trPmtCont5);
pmtPlaneVol->AddNode(pmtContVol, 26, trPmtCont6);
TGeoTranslation* trPmtPlane =
new TGeoTranslation(pmtXShift, 0., boxZLen / 2. - boxBackThickness - pmtZPadding + (pmtThickness / 2.));
gasVol->AddNode(pmtPlaneVol, 1, trPmtPlane);
gGeoMan->CheckOverlaps();
gGeoMan->PrintOverlaps();
//Draw
pmtPixelVol->SetLineColor(kYellow + 4);
aerogelVol->SetLineColor(kCyan);
aerogelVol->SetTransparency(70);
gasVol->SetLineColor(kGreen);
gasVol->SetTransparency(60);
kaptonVol->SetLineColor(kBlue);
kaptonVol->SetTransparency(70);
//gGeoMan->SetTopVisible();
//boxVol->SetVisibility(true);
// boxVol->Draw("ogl");
//top->Draw("ogl");
gGeoMan->SetVisLevel(7); //7
rich->Export(geoFileName); // an alternative way of writing the trd volume
TFile* geoFile = new TFile(geoFileName, "UPDATE");
trBox->Write();
cout << endl << "Geometry exported to " << geoFileName << endl;
geoFile->Close();
}
/* Copyright (C) 2012-2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: David Emschermann [committer] */
/******************************************************************************
** Creation of STS geometry in ROOT format (TGeo).
**
** @file create_stsgeo_v24b.C
** @author David Emschermann <d.emschermann@gsi.de>
** @author Volker Friese <v.friese@gsi.de>
** @since 15 June 2012
** @date 09.05.2014
** @author Tomas Balog <T.Balog@gsi.de>
**
** 2024-04-29 - MS - v24c: based on v24b, shift STS in Z to position measured in the cave
** as it was seen that the station 0 module position was not correct
** and the measurement was done again in the CAVE. The position of
** the Back-side of the STS box was expected to be at 57.8 cm.
** We opened the side wall of the sts-box and did the measurement
** inside the box for the placement of the C-Frames.
** The thickness of the back-side wall is 0.5 cm which means from
** inside the box (57.8-0.5=57.3) the last C-Frame edge is at 7 cm
** away (50.3). The edge of the front wall from out-side is at 22.8 cm
** (35 cm away from the backside wall). And the first module box wall
** from the wall is 1.6 cm away.
** 2024-03-27 - DE - v24b: based on v24a, shift STS in z to position measured in the cave
** 2024-03-26 - DE - v24a: add preliminary version of mSTS v24a for the 2024_03_22 gold setup
** 2024-02-06 - DE - v24a: position the STS sensors as measured in the cave
** 2023-06-29 - DE - v23b: add a 6x6 cm2 module at z=16.5 cm, keep STS box around 2x2 and 3x3 (from v22e)
** 2023-06-27 - DE - v23a: add a 6x6 cm2 module at z=14.0 cm (nominal), keep STS box around 2x2 and 3x3 (from v22e)
** 2023-02-09 - DE - v22f: decrease distance between statios 0 and 1 from 140 mm to 135 mm, to reflect CAD
** 2023-02-09 - DE - v22f: increase gap between units of a station gkLadderGapZ from 10 mm to 12 mm, to reflect CAD
** 2023-02-09 - DE - v22f: shift ladder U2 downwards in y by 2.2 mm
** 2023-02-08 - DE - v22f: introduce ladder type 12 (based on 10) for U2, but with original gkSectorOverlapY of 4.6 mm
** 2022-09-13 - DE - v22e: correct gkSectorOverlapY to 9.0 mm for the ladder type 10 (with 12 cm sensors)
** 2022-03-18 - DE - v22d: add position offset for mSTS 2022_03_22_iron as surveyed in the cave
** 2022-02-01 - DE - v22b: add position offset for mSTS 07_2021 as surveyed in the cave
** 2022-01-25 - DE - v22a: add a aluminium box around v20e
** 2020-05-16 - DE - v20e: swap ladders in unit 3 - 3x 6x6 on beam side
** 2020-03-21 - DE - v20d: build mSTS for March 2020 - 1 ladder - shift -3 cm in x
** 2020-03-11 - DE - v20c: build mSTS for March 2021 - 5 ladders
** 2020-03-11 - DE - v20b: build mSTS for May 2020 - 2 ladders
** 2020-03-11 - DE - v20a: build mSTS for March 2020 - 1 ladder
**
** 2019-12-04 - DE - v19d: build 2nd mSTS v19d station from one 6x6 and one 6x12 cm x cm sensors
** 2019-12-04 - DE - v19c: build 1st mSTS v19c station at nominal position
** 2019-08-12 - DE - v19a: mSTS as built in March 2019 - the mSTS FEBs are in the bottom
** 2019-03-15 - DE - v18n: mSTS as built in March 2019 - downstream ladder of station 0 at position of station 1
** 2018-01-18 - DE - v18g: set overlaps in X and Y according to mSTS CAD model
**
** v18f: flip orientation of carbon ladders for primary beam left of mSTS, change z-positions to 30 and 45 cm
** v18e: 2 stations, derived from v15b, 1st 2x2, 2nd of 3x3 sensor array, sensor size 6x6 cm2 with carbon ladder supports
** v18d: 2 stations of 3x3 sensor array, sensor size 6x6 cm2 with carbon ladder supports
** v18c: (causes segfault due to divide) 2 stations of 3x3 sensor array, sensor size 6x6 cm2 with carbon ladder supports
** v18b: 2 stations of 4x4 sensor array, sensor size 6x6 cm2
** v18a: 2 stations of 3x3 sensor array, sensor size 6x6 cm2
**
** 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 "TGeoCompositeShape.h"
#include "TGeoCone.h"
#include "TGeoManager.h"
#include "TGeoPara.h"
#include "TGeoTube.h"
#include <iomanip>
#include <iostream>
// ------------- Installation offset -----------------------------------
// position in x and y agrees within 2 mm to CbmRoot geometry (01.02.2022)
const Double_t gOffX = 0.0; // Offset from nominal position
const Double_t gOffY = 0.0; // Offset from nominal position
// 2023
// const Double_t gOffZ = 5.0; // Offset from nominal position
// 2024
const Double_t gOffZ = 4.55; // Offset from nominal position
const Bool_t IncludeBox = true; // false; // true, if STS box is plotted
// ------------- Steering variables -----------------------------------
// ---> Horizontal width of sensors [cm]
const Double_t gkSensorSizeX = 6.2092;
// ---> 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
const Double_t gkSectorOverlapYL10 = 0.90; // for ladders with 124 mm sensors - Oleg CAD 13/09/2022
// ---> 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 = 1.20; // DEJH -> 0.90 / 0.50
// v22e const Double_t gkLadderGapZ = 1.00; // DEJH -> 0.90 / 0.50
// ---> Gap in z between lowest sector to carbon support structure [cm]
const Double_t gkSectorGapZFrame = 0.10;
// ---> 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; // kFALSE; // switch this false for v15a
const Bool_t gkConstructFrames = kTRUE; // kFALSE; // switch this false for v15a
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)
// ----------------------------------------------------------------------------
// -------------- 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;
// ----------------------------------------------------------------------------
// ------------- 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
// ----------------------------------------------------------------------------
Int_t CreateSubplates();
Int_t CreatePlates();
Int_t CreateSensors();
Int_t CreateSectors();
Int_t CreateLadders();
void CheckVolume(TGeoVolume* volume);
void CheckVolume(TGeoVolume* volume, fstream& file);
TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x);
TGeoVolume* ConstructSmallCone(Double_t coneDz);
TGeoVolume* ConstructBigCone(Double_t coneDz);
TGeoVolume* ConstructHalfLadder(Int_t ladderid, const TString& name, Int_t nSectors, Int_t* sectorTypes, char align);
TGeoVolume* ConstructLadder(Int_t LadderIndex, TGeoVolume* halfLadderU, TGeoVolume* halfLadderD, Double_t shiftZ);
TGeoVolume* ConstructLadderWithGap(Int_t LadderIndex, TGeoVolume* halfLadderU, TGeoVolume* halfLadderD, Double_t gapY);
TGeoVolume* ConstructStation(Int_t iStation, Int_t nLadders, Int_t* ladderTypes, Double_t rHole);
// ============================================================================
// ====== Main function =====
// ============================================================================
void create_stsgeo_v24c(const char* geoTag = "v24c_mcbm")
{
// ------- Geometry file name (output) ----------------------------------
TString geoFileName = "sts_";
geoFileName = geoFileName + geoTag + ".geo.root?reproducible";
// --------------------------------------------------------------------------
// ------- 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_v24c.C" << endl << 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 FairRunSim to ensure the correct unit system
FairRunSim* sim = new FairRunSim();
// ------- 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");
// ---> 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");
// ---> 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");
// ---
gStsMedium = air;
// --------------------------------------------------------------------------
// -------------- Create geometry and top volume -------------------------
gGeoMan = (TGeoManager*) gROOT->FindObject("FAIRGeom");
gGeoMan->SetName("STSgeom");
TGeoVolume* top = new TGeoVolumeAssembly("TOP");
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(kYellow);
if (iSensor == 2) sensor->SetLineColor(kRed);
if (iSensor == 3) sensor->SetLineColor(kBlue);
if (iSensor == 4) sensor->SetLineColor(kAzure + 7);
if (iSensor == 5) sensor->SetLineColor(kGreen);
if (iSensor == 6) 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 --------------------------------------
TString name = "";
cout << endl << endl;
cout << "===> Creating ladders...." << endl;
infoFile << endl << "Ladders:" << endl;
Int_t nLadders = CreateLadders();
for (Int_t iLadder = 1; iLadder <= nLadders; iLadder++) {
cout << endl;
name = Form("Ladder%02d", iLadder);
TGeoVolume* ladder = gGeoMan->GetVolume(name);
CheckVolume(ladder);
CheckVolume(ladder, infoFile);
CheckVolume(ladder->GetNode(0)->GetVolume(), infoFile);
}
// --------------------------------------------------------------------------
// ---------------- Create cone -----------------------------------------
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 -------------------------------------
// Float_t statPos[8] = {30., 40., 50., 60., 70., 80., 90., 100.};
//DE23 Float_t statPos[8] = {13.75, 28.25, 41.75, 50., 60., 70., 80., 90.};
// Float_t statPos[8] = {14., 28., 42., 50., 60., 70., 80., 90.};
// 2023
// Float_t statPos[8] = {11.5, 28., 42., 50., 60., 70., 80., 90.};
// 2024
//
// from cave (Jens)
// hier die Sensorpositionen in Z-Richtung für das mSTS Upgrade.
// Target to Station 0: dZ=170 165
// Station 0 to 1: dZ=125 290
// Station 1 to 2: dZ=135 425
//
// 2024
//Float_t statPos[8] = {16.5, 29.0, 42.5, 50., 60., 70., 80., 90.};
Float_t statPos[8] = {12.065, 26.50, 40.0, 50., 60., 70., 80., 90.};
//
// Float_t statPos[8] = {30., 45., 50., 60., 70., 80., 90., 100.};
cout << endl << endl;
cout << "===> Creating stations...." << endl;
infoFile << endl << "Stations: ";
nLadders = 0;
Int_t ladderTypes[20];
Double_t statZ = 0.;
Double_t rHole = 0.;
TGeoBBox* statShape = NULL;
TGeoTranslation* statTrans = NULL;
// --- Station 01: 8 ladders, type 3 2 2 1 1 2 2 3
cout << endl;
statZ = 30.;
rHole = 2.0;
nLadders = 1;
ladderTypes[0] = 13;
TGeoVolume* station01 = ConstructStation(0, nLadders, ladderTypes, rHole);
CheckVolume(station01);
CheckVolume(station01, infoFile);
infoFile << "Position z = " << statPos[0] << endl;
// --- Station 02: 12 ladders, type 4 3 3 2 2 1 1 2 2 3 3 4
cout << endl;
statZ = 40.;
rHole = 2.0;
nLadders = 3;
nLadders = 2;
ladderTypes[0] = 9;
ladderTypes[1] = 9;
// v22e ladderTypes[0] = 10;
// v22e ladderTypes[1] = 10;
// v22e ladderTypes[2] = 11; // triple ladder
TGeoVolume* station02 = ConstructStation(1, nLadders, ladderTypes, rHole);
CheckVolume(station02);
CheckVolume(station02, infoFile);
infoFile << "Position z = " << statPos[1] << endl;
// --- Station 03: 12 ladders, type 8 7 6 6 6 5 5 6 6 6 7 8
cout << endl;
statZ = 50.;
rHole = 2.9;
nLadders = 3;
ladderTypes[0] = 10;
ladderTypes[1] = 12;
ladderTypes[2] = 11; // triple ladder
TGeoVolume* station03 = ConstructStation(2, nLadders, ladderTypes, rHole);
CheckVolume(station03);
CheckVolume(station03, infoFile);
infoFile << "Position z = " << statPos[2] << endl;
// // --- Station 04: 14 ladders, type 9 8 7 6 6 6 5 5 6 6 7 8 9
// cout << endl;
// statZ = 60.;
// rHole = 2.9;
// nLadders = 14;
// ladderTypes[0] = 15; // 42; // 9;
// ladderTypes[1] = 14; // 34; // 8;
// ladderTypes[2] = 13; // 33; // 7;
// ladderTypes[3] = 12; // 32; // 6;
// ladderTypes[4] = 12; // 32; // 6;
// ladderTypes[5] = 12; // 32; // 6;
// ladderTypes[6] = 4; // 41; // 5;
// ladderTypes[7] = 4; // 41; // 5;
// ladderTypes[8] = 12; // 32; // 6;
// ladderTypes[9] = 12; // 32; // 6;
// ladderTypes[10] = 12; // 32; // 6;
// ladderTypes[11] = 13; // 33; // 7;
// ladderTypes[12] = 14; // 34; // 8;
// ladderTypes[13] = 15; // 42; // 9;
// TGeoVolume* station04 = ConstructStation(3, nLadders, ladderTypes, rHole);
//
// if (gkConstructCones) {
// // upstream
// TGeoRotation* coneRot41 = new TGeoRotation;
// coneRot41->RotateZ(-90);
// coneRot41->RotateY(180);
// // TGeoCombiTrans* conePosRot41 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-0.3-gkLadderGapZ/2., coneRot41);
// TGeoCombiTrans* conePosRot41 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-0.285-gkLadderGapZ/2., coneRot41);
// station04->AddNode(coneBigVolum, 1, conePosRot41);
//
// // downstream
// TGeoRotation* coneRot42 = new TGeoRotation;
// coneRot42->RotateZ(-90);
// // TGeoCombiTrans* conePosRot42 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+0.3+gkLadderGapZ/2., coneRot42);
// TGeoCombiTrans* conePosRot42 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+0.285+gkLadderGapZ/2., coneRot42);
// station04->AddNode(coneBigVolum, 2, conePosRot42);
//
// station04->GetShape()->ComputeBBox();
// }
//
// CheckVolume(station04);
// CheckVolume(station04, infoFile);
// infoFile << "Position z = " << statPos[3] << endl;
//
//
// // --- Station 05: 14 ladders, type 14 13 12 12 11 11 10 10 11 11 12 12 13 14
// cout << endl;
// statZ = 70.;
// rHole = 3.7;
// nLadders = 14;
// ladderTypes[0] = 19; // 55; // 14;
// ladderTypes[1] = 18; // 54; // 13;
// ladderTypes[2] = 17; // 53; // 12;
// ladderTypes[3] = 17; // 53; // 12;
// ladderTypes[4] = 16; // 52; // 11;
// ladderTypes[5] = 16; // 52; // 11;
// ladderTypes[6] = 5; // 51; // 23; // 10;
// ladderTypes[7] = 5; // 51; // 23; // 10;
// ladderTypes[8] = 16; // 52; // 11;
// ladderTypes[9] = 16; // 52; // 11;
// ladderTypes[10] = 17; // 53; // 12;
// ladderTypes[11] = 17; // 53; // 12;
// ladderTypes[12] = 18; // 54; // 13;
// ladderTypes[13] = 19; // 55; // 14;
// TGeoVolume* station05 = ConstructStation(4, nLadders, ladderTypes, rHole);
//
// if (gkConstructCones) {
// // upstream
// TGeoRotation* coneRot51 = new TGeoRotation;
// coneRot51->RotateZ(90);
// coneRot51->RotateY(180);
// // TGeoCombiTrans* conePosRot51 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-0.3-gkLadderGapZ/2., coneRot51);
// TGeoCombiTrans* conePosRot51 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-0.285-gkLadderGapZ/2., coneRot51);
// station05->AddNode(coneBigVolum, 1, conePosRot51);
//
// // downstream
// TGeoRotation* coneRot52 = new TGeoRotation;
// coneRot52->RotateZ(90);
// // TGeoCombiTrans* conePosRot52 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+0.3+gkLadderGapZ/2., coneRot52);
// TGeoCombiTrans* conePosRot52 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+0.285+gkLadderGapZ/2., coneRot52);
// station05->AddNode(coneBigVolum, 2, conePosRot52);
//
// station05->GetShape()->ComputeBBox();
// }
//
// CheckVolume(station05);
// CheckVolume(station05, infoFile);
// infoFile << "Position z = " << statPos[4] << endl;
//
//
// // --- Station 06: 14 ladders, type 14 13 12 12 11 11 10 10 11 11 12 12 13 14
// cout << endl;
// statZ = 80.;
// rHole = 3.7;
// nLadders = 14;
// ladderTypes[0] = 19; // 55; // 14;
// ladderTypes[1] = 18; // 54; // 13;
// ladderTypes[2] = 17; // 53; // 12;
// ladderTypes[3] = 17; // 53; // 12;
// ladderTypes[4] = 16; // 52; // 11;
// ladderTypes[5] = 16; // 52; // 11;
// ladderTypes[6] = 6; // 61; // 10;
// ladderTypes[7] = 6; // 61; // 10;
// ladderTypes[8] = 16; // 52; // 11;
// ladderTypes[9] = 16; // 52; // 11;
// ladderTypes[10] = 17; // 53; // 12;
// ladderTypes[11] = 17; // 53; // 12;
// ladderTypes[12] = 18; // 54; // 13;
// ladderTypes[13] = 19; // 55; // 14;
// TGeoVolume* station06 = ConstructStation(5, nLadders, ladderTypes, rHole);
//
// if (gkConstructCones) {
// // upstream
// TGeoRotation* coneRot61 = new TGeoRotation;
// coneRot61->RotateZ(-90);
// coneRot61->RotateY(180);
// // TGeoCombiTrans* conePosRot61 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-0.3-gkLadderGapZ/2., coneRot61);
// TGeoCombiTrans* conePosRot61 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-0.285-gkLadderGapZ/2., coneRot61);
// station06->AddNode(coneBigVolum, 1, conePosRot61);
//
// // downstream
// TGeoRotation* coneRot62 = new TGeoRotation;
// coneRot62->RotateZ(-90);
// // TGeoCombiTrans* conePosRot62 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+0.3+gkLadderGapZ/2., coneRot62);
// TGeoCombiTrans* conePosRot62 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+0.285+gkLadderGapZ/2., coneRot62);
// station06->AddNode(coneBigVolum, 2, conePosRot62);
//
// station06->GetShape()->ComputeBBox();
// }
//
// CheckVolume(station06);
// CheckVolume(station06, infoFile);
// infoFile << "Position z = " << statPos[5] << endl;
//
//
// // --- Station 07: 16 ladders, type 14 13 17 17 16 16 16 15 15 16 16 16 17 17 13 14
// cout << endl;
// statZ = 90.;
// rHole = 4.2;
// nLadders = 16;
// ladderTypes[0] = 21; // 73; // 17;
// ladderTypes[1] = 19; // 55; // 14;
// ladderTypes[2] = 18; // 54; // 13;
// ladderTypes[3] = 20; // 72; // 16;
// ladderTypes[4] = 20; // 72; // 16;
// ladderTypes[5] = 20; // 72; // 16;
// ladderTypes[6] = 20; // 72; // 16;
// ladderTypes[7] = 7; // 71; // 15;
// ladderTypes[8] = 7; // 71; // 15;
// ladderTypes[9] = 20; // 72; // 16;
// ladderTypes[10] = 20; // 72; // 16;
// ladderTypes[11] = 20; // 72; // 16;
// ladderTypes[12] = 20; // 72; // 16;
// ladderTypes[13] = 18; // 54; // 13;
// ladderTypes[14] = 19; // 55; // 14;
// ladderTypes[15] = 21; // 73; // 17;
// TGeoVolume* station07 = ConstructStation(6, nLadders, ladderTypes, rHole);
//
// if (gkConstructCones) {
// // upstream
// TGeoRotation* coneRot71 = new TGeoRotation;
// coneRot71->RotateZ(90);
// coneRot71->RotateY(180);
// // TGeoCombiTrans* conePosRot71 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-0.3-gkLadderGapZ/2., coneRot71);
// TGeoCombiTrans* conePosRot71 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-0.285-gkLadderGapZ/2., coneRot71);
// station07->AddNode(coneBigVolum, 1, conePosRot71);
//
// // downstream
// TGeoRotation* coneRot72 = new TGeoRotation;
// coneRot72->RotateZ(90);
// // TGeoCombiTrans* conePosRot72 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+0.3+gkLadderGapZ/2., coneRot72);
// TGeoCombiTrans* conePosRot72 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+0.285+gkLadderGapZ/2., coneRot72);
// station07->AddNode(coneBigVolum, 2, conePosRot72);
//
// station07->GetShape()->ComputeBBox();
// }
//
// CheckVolume(station07);
// CheckVolume(station07, infoFile);
// infoFile << "Position z = " << statPos[6] << endl;
//
//
// // --- Station 08: 16 ladders, type 14 13 17 17 16 16 16 15 15 16 16 16 17 17 13 14
// cout << endl;
// statZ = 100.;
// rHole = 4.2;
// nLadders = 16;
// ladderTypes[0] = 19; // 55; // 14;
// ladderTypes[1] = 17; // 53; // 12;
// ladderTypes[2] = 23; // 83; // 20;
// ladderTypes[3] = 22; // 82; // 19;
// ladderTypes[4] = 22; // 82; // 19;
// ladderTypes[5] = 22; // 82; // 19;
// ladderTypes[6] = 22; // 82; // 19;
// ladderTypes[7] = 8; // 81; // 18;
// ladderTypes[8] = 8; // 81; // 18;
// ladderTypes[9] = 22; // 82; // 19;
// ladderTypes[10] = 22; // 82; // 19;
// ladderTypes[11] = 22; // 82; // 19;
// ladderTypes[12] = 22; // 82; // 19;
// ladderTypes[13] = 23; // 83; // 20;
// ladderTypes[14] = 17; // 53; // 12;
// ladderTypes[15] = 19; // 55; // 14;
// TGeoVolume* station08 = ConstructStation(7, nLadders, ladderTypes, rHole);
//
// if (gkConstructCones) {
// // upstream
// TGeoRotation* coneRot81 = new TGeoRotation;
// coneRot81->RotateZ(-90);
// coneRot81->RotateY(180);
// // TGeoCombiTrans* conePosRot81 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-0.3-gkLadderGapZ/2., coneRot81);
// TGeoCombiTrans* conePosRot81 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-0.285-gkLadderGapZ/2., coneRot81);
// station08->AddNode(coneBigVolum, 1, conePosRot81);
//
// // downstream
// TGeoRotation* coneRot82 = new TGeoRotation;
// coneRot82->RotateZ(-90);
// // TGeoCombiTrans* conePosRot82 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+0.3+gkLadderGapZ/2., coneRot82);
// TGeoCombiTrans* conePosRot82 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+0.285+gkLadderGapZ/2., coneRot82);
// station08->AddNode(coneBigVolum, 2, conePosRot82);
//
// station08->GetShape()->ComputeBBox();
// }
//
// CheckVolume(station08);
// CheckVolume(station08, infoFile);
// infoFile << "Position z = " << statPos[7] << endl;
// --------------------------------------------------------------------------
// --------------- Create subplates ---------------------------------------
cout << endl << endl;
cout << "===> Creating subplates...." << endl << endl;
infoFile << endl << "Subplates: " << endl;
Int_t nSubplates = CreateSubplates();
for (Int_t iSubplate = 1; iSubplate <= nSubplates; iSubplate++) {
TString name = Form("Subplate%02d", iSubplate);
TGeoVolume* subplate = gGeoMan->GetVolume(name);
// add color to plates
subplate->SetTransparency(60);
if (iSubplate == 1) subplate->SetLineColor(kOrange); // kOrange);
if (iSubplate == 2) subplate->SetLineColor(kOrange); // kRed);
if (iSubplate == 3) subplate->SetLineColor(kOrange); // kGreen);
if (iSubplate == 4) subplate->SetLineColor(kOrange); // kRed);
if (iSubplate == 5) subplate->SetLineColor(kOrange); // kOrange);
if (iSubplate == 6) subplate->SetLineColor(kOrange); // kCyan);
if (iSubplate == 7) subplate->SetLineColor(kOrange); // kRed);
if (iSubplate == 8) subplate->SetLineColor(kOrange); // kGreen);
if (iSubplate == 9) subplate->SetLineColor(kOrange); // kGreen);
if (iSubplate == 10) subplate->SetLineColor(kOrange); // kGreen);
// CheckVolume(plate);
// CheckVolume(plate, infoFile);
}
// --------------------------------------------------------------------------
// --------------- Create plates ---------------------------------------
cout << endl << endl;
cout << "===> Creating plates...." << endl << endl;
infoFile << endl << "Plates: " << endl;
Int_t nPlates = CreatePlates();
for (Int_t iPlate = 1; iPlate <= nPlates; iPlate++) {
TString name = Form("Plate%02d", iPlate);
TGeoVolume* plate = gGeoMan->GetVolume(name);
// CheckVolume(plate);
// CheckVolume(plate, infoFile);
}
// --------------------------------------------------------------------------
// --------------- Create STS volume ------------------------------------
cout << endl << endl;
cout << "===> Creating STS...." << endl;
TString stsName = "sts_";
stsName += geoTag;
// --- 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
Int_t nStation = 3; // set number of stations
for (Int_t iStation = 1; iStation <= nStation; 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[2] - statPos[1]) + stsBorder;
Double_t stsPosZ = 0.5 * (statPos[2] + statPos[1]);
// stsZ = (statPos[1] - statPos[0]) + stsBorder;
// Double_t stsPosZ = 0.5 * (statPos[1] + statPos[0]);
// --- Create box around the stations
TGeoBBox* stsBox = 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[1] + 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 STS volume
// TGeoShape* stsShape = new TGeoCompositeShape("stsShape",
// "stsBox-stsCone1:trans1-stsCone2:trans2");
// TGeoVolume* sts = new TGeoVolume(stsName.Data(), stsShape, gStsMedium);
// TGeoVolume* sts = new TGeoVolume(stsName.Data(), stsBox, gStsMedium);
TGeoVolumeAssembly* sts = new TGeoVolumeAssembly(stsName.Data()); // do not produce keeping volumes
// --- Place stations in the STS
for (Int_t iStation = 1; iStation <= nStation; iStation++) {
TString statName = Form("Station%02d", iStation);
TGeoVolume* station = gGeoMan->GetVolume(statName);
Double_t posZ = statPos[iStation - 1] - stsPosZ;
TGeoTranslation* trans = new TGeoTranslation(0., 0., posZ); // standard
sts->AddNode(station, iStation, trans);
sts->GetShape()->ComputeBBox();
}
// plates
if (IncludeBox)
for (Int_t iPlate = 1; iPlate <= nPlates; iPlate++) {
TString platName = Form("Plate%02d", iPlate);
TGeoVolume* plate = gGeoMan->GetVolume(platName);
TGeoTranslation* boxdz01 = new TGeoTranslation("ty01", 0, 0, 2.50); // v23a - shift to 2x2 and 3x3 stations
sts->AddNode(plate, iPlate, boxdz01);
// sts->AddNode(plate, iPlate);
sts->GetShape()->ComputeBBox();
}
cout << endl;
CheckVolume(sts);
// --------------------------------------------------------------------------
// --------------- Finish -----------------------------------------------
TGeoTranslation* stsTrans = new TGeoTranslation(gOffX, gOffY, stsPosZ + gOffZ);
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->Test();
TFile* geoFile = new TFile(geoFileName, "RECREATE");
sts->Export(geoFileName);
cout << endl;
cout << "Geometry " << sts->GetName() << " exported to " << geoFileName << endl;
geoFile->Close();
geoFile = new TFile(geoFileName, "UPDATE");
stsTrans->Write();
geoFile->Close();
TString geoFileName_ = "sts_";
geoFileName_ = geoFileName_ + geoTag + "_geo.root?reproducible";
geoFile = new TFile(geoFileName_, "RECREATE");
gGeoMan->Write(); // use this is you want GeoManager format in the output
geoFile->Close();
top->Draw("ogl");
gGeoManager->SetVisLevel(6);
infoFile.close();
// create medialist for this geometry
TString createmedialist = gSystem->Getenv("VMCWORKDIR");
createmedialist += "/macro/geometry/create_medialist.C";
std::cout << "Loading macro " << createmedialist << std::endl;
gROOT->LoadMacro(createmedialist);
gROOT->ProcessLine("create_medialist(\"\", false)");
}
// ============================================================================
// ====== 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;
}
/** ======================================================================= **/
/** ======================================================================= **/
Int_t CreateSubplates()
{
Int_t nSubplates = 0;
Double_t xSize = 0.;
Double_t ySize = 0.;
Double_t zSize = 0.5; // cm // gkSubplateThickness;
TGeoMedium* aluminium = gGeoMan->GetMedium("aluminium");
// xsize 830 / (830 - 115+137-12) = 590
// ysize 518 / 222 / 125 = 865
// ysize 530 / 198 / 137 // corrected for 12 mm rim
// center z-axis in front cutout
// ysize 518 + 222/2. = 629
// ysize 530 + 198/2. = 629
// center z-axis in front cutout
// xsize 830/2. - (115 + 137)/2. = 415 - 126 = 289
// --- Subplate type 01: front plate (83.0 cm x 86.5 cm)
xSize = 83.0; // cm
ySize = 53.0; // cm
TGeoBBox* shape_subplate01 = new TGeoBBox("subplate01", xSize / 2., ySize / 2., zSize / 2.);
new TGeoVolume("Subplate01", shape_subplate01, aluminium);
nSubplates++;
// --- Subplate type 02: front plate (83.0 cm x 86.5 cm)
xSize = 59.0; // cm
ySize = 19.8; // cm
TGeoBBox* shape_subplate02 = new TGeoBBox("subplate02", xSize / 2., ySize / 2., zSize / 2.);
new TGeoVolume("Subplate02", shape_subplate02, aluminium);
nSubplates++;
// --- Subplate type 03: front plate (83.0 cm x 86.5 cm)
xSize = 83.0; // cm
ySize = 13.7; // cm
TGeoBBox* shape_subplate03 = new TGeoBBox("subplate03", xSize / 2., ySize / 2., zSize / 2.);
new TGeoVolume("Subplate03", shape_subplate03, aluminium);
nSubplates++;
// xsize 830 / (830 - 340 - 25) = 465
// ysize 483 / 293 / 89 = 865
// center z-axis in back cutout
// ysize 483 + 293/2. = 629.5
// center z-axis in backside cutout
// xsize 830/2. - ( 340/2. + 25 ) = 415 - 220 = 195
// --- Subplate type 04: front plate (83.0 cm x 86.5 cm)
xSize = 83.0; // cm
ySize = 48.3; // cm
TGeoBBox* shape_subplate04 = new TGeoBBox("subplate04", xSize / 2., ySize / 2., zSize / 2.);
new TGeoVolume("Subplate04", shape_subplate04, aluminium);
nSubplates++;
// --- Subplate type 05: front plate (83.0 cm x 86.5 cm)
xSize = 46.5; // cm
ySize = 29.3; // cm
TGeoBBox* shape_subplate05 = new TGeoBBox("subplate05", xSize / 2., ySize / 2., zSize / 2.);
new TGeoVolume("Subplate05", shape_subplate05, aluminium);
nSubplates++;
// --- Subplate type 06: front plate (83.0 cm x 86.5 cm)
xSize = 83.0; // cm
ySize = 8.9; // cm
TGeoBBox* shape_subplate06 = new TGeoBBox("subplate06", xSize / 2., ySize / 2., zSize / 2.);
new TGeoVolume("Subplate06", shape_subplate06, aluminium);
nSubplates++;
// bottom / top
// --- Subplate type 07: bottom/top plate (83.0 cm x 34.0 cm)
xSize = 83.0; // cm
ySize = 34.0; // cm
TGeoBBox* shape_subplate07 = new TGeoBBox("subplate07", xSize / 2., zSize / 2., ySize / 2.);
new TGeoVolume("Subplate07", shape_subplate07, aluminium);
nSubplates++;
// right
// --- Subplate type 08: right plate
xSize = 85.5; // cm
ySize = 34.0; // cm
TGeoBBox* shape_subplate08 = new TGeoBBox("subplate08", zSize / 2., xSize / 2., ySize / 2.);
new TGeoVolume("Subplate08", shape_subplate08, aluminium);
nSubplates++;
// left bottom
// --- Subplate type 09: left plate
xSize = 52.5; // cm
ySize = 34.0; // cm
TGeoBBox* shape_subplate09 = new TGeoBBox("subplate09", zSize / 2., xSize / 2., ySize / 2.);
new TGeoVolume("Subplate09", shape_subplate09, aluminium);
nSubplates++;
// left top
// --- Subplate type 10: left plate
xSize = 13.2; // cm
ySize = 34.0; // cm
TGeoBBox* shape_subplate10 = new TGeoBBox("subplate10", zSize / 2., xSize / 2., ySize / 2.);
new TGeoVolume("Subplate10", shape_subplate10, aluminium);
nSubplates++;
/*
xSize = 82.0; // cm
ySize = 50.0; // cm
TGeoBBox* shape_subplate01 = new TGeoBBox("subplate01", xSize / 2., ySize / 2., 1.5 / 2.);
new TGeoVolume("Subplate11", shape_subplate01, aluminium);
nSubplates++;
*/
return nSubplates;
}
/** ======================================================================= **/
/** ======================================================================= **/
Int_t CreatePlates()
{
Int_t nPlates = 0;
Double_t box_dx = 83.0; // cm
Double_t box_dy = 86.5; // cm
// Double_t dx = 0; // cm
// Double_t dx = -(box_dx/2 - 19.5); // cm - backside center
// Double_t dx = -(box_dx/2 - 12.6); // cm - frontside center
Double_t dx = -box_dx / 2 + 15.7; // cm - from CAD drawing
Double_t dy = box_dy / 2 - 62.9; // cm - from CAD drawing 23,6 cm
// Double_t box_dz_inner = 0; // cm
Double_t box_dz_inner = 34.0; // cm
TGeoVolume* subplate01 = gGeoMan->GetVolume("Subplate01");
TGeoVolume* subplate02 = gGeoMan->GetVolume("Subplate02");
TGeoVolume* subplate03 = gGeoMan->GetVolume("Subplate03");
TGeoBBox* box01 = (TGeoBBox*) subplate01->GetShape();
TGeoBBox* box02 = (TGeoBBox*) subplate02->GetShape();
TGeoBBox* box03 = (TGeoBBox*) subplate03->GetShape();
TGeoVolume* subplate04 = gGeoMan->GetVolume("Subplate04");
TGeoVolume* subplate05 = gGeoMan->GetVolume("Subplate05");
TGeoVolume* subplate06 = gGeoMan->GetVolume("Subplate06");
TGeoBBox* box04 = (TGeoBBox*) subplate04->GetShape();
TGeoBBox* box05 = (TGeoBBox*) subplate05->GetShape();
TGeoBBox* box06 = (TGeoBBox*) subplate06->GetShape();
TGeoVolume* subplate07 = gGeoMan->GetVolume("Subplate07");
TGeoBBox* box07 = (TGeoBBox*) subplate07->GetShape();
TGeoVolume* subplate08 = gGeoMan->GetVolume("Subplate08");
TGeoBBox* box08 = (TGeoBBox*) subplate08->GetShape();
TGeoVolume* subplate09 = gGeoMan->GetVolume("Subplate09");
TGeoBBox* box09 = (TGeoBBox*) subplate09->GetShape();
TGeoVolume* subplate10 = gGeoMan->GetVolume("Subplate10");
TGeoBBox* box10 = (TGeoBBox*) subplate10->GetShape();
// --- Plate type 1: front plate made of 3 subplates
TGeoVolumeAssembly* plate01 = new TGeoVolumeAssembly("Plate01");
Double_t sy01 = -box_dy / 2. + box01->GetDY();
Double_t sz01 = -(box01->GetDZ() + box_dz_inner / 2.);
TGeoTranslation* ty01 = new TGeoTranslation("ty01", dx, sy01 + dy, sz01);
plate01->AddNode(subplate01, 1, ty01);
Double_t sx02 = -box_dx / 2. + box02->GetDX();
Double_t sy02 = -box_dy / 2. + box01->GetDY() * 2 + box02->GetDY();
TGeoTranslation* ty02 = new TGeoTranslation("ty02", sx02 + dx, sy02 + dy, sz01);
plate01->AddNode(subplate02, 2, ty02);
Double_t sy03 = -box_dy / 2. + box01->GetDY() * 2 + box02->GetDY() * 2 + box03->GetDY();
TGeoTranslation* ty03 = new TGeoTranslation("ty03", dx, sy03 + dy, sz01);
plate01->AddNode(subplate03, 3, ty03);
plate01->GetShape()->ComputeBBox();
nPlates++;
// --- Plate type 2: back plate made of 3 subplates
TGeoVolumeAssembly* plate02 = new TGeoVolumeAssembly("Plate02");
Double_t sy04 = -box_dy / 2. + box04->GetDY();
Double_t sz04 = box04->GetDZ() + box_dz_inner / 2.;
TGeoTranslation* ty04 = new TGeoTranslation("ty04", dx, sy04 + dy, sz04);
plate02->AddNode(subplate04, 1, ty04);
Double_t sx05 = -box_dx / 2. + box05->GetDX();
Double_t sy05 = -box_dy / 2. + box04->GetDY() * 2 + box05->GetDY();
TGeoTranslation* ty05 = new TGeoTranslation("ty05", sx05 + dx, sy05 + dy, sz04);
plate02->AddNode(subplate05, 2, ty05);
Double_t sy06 = -box_dy / 2. + box04->GetDY() * 2 + box05->GetDY() * 2 + box06->GetDY();
TGeoTranslation* ty06 = new TGeoTranslation("ty06", dx, sy06 + dy, sz04);
plate02->AddNode(subplate06, 3, ty06);
plate02->GetShape()->ComputeBBox();
nPlates++;
// --- Plate type 3: bottom plate
TGeoVolumeAssembly* plate03 = new TGeoVolumeAssembly("Plate03");
Double_t sy07 = box_dy / 2. - box07->GetDY();
TGeoTranslation* ty07 = new TGeoTranslation("ty07", dx, -sy07 + dy, 0.);
plate03->AddNode(subplate07, 1, ty07);
plate03->GetShape()->ComputeBBox();
nPlates++;
// --- Plate type 4: top plate
TGeoVolumeAssembly* plate04 = new TGeoVolumeAssembly("Plate04");
TGeoTranslation* ty17 = new TGeoTranslation("ty17", dx, sy07 + dy, 0.);
plate04->AddNode(subplate07, 1, ty17);
plate04->GetShape()->ComputeBBox();
nPlates++;
// --- Plate type 5: -x plate
TGeoVolumeAssembly* plate05 = new TGeoVolumeAssembly("Plate05");
Double_t sx08 = box_dx / 2. - box08->GetDX();
TGeoTranslation* ty08 = new TGeoTranslation("ty08", -sx08 + dx, dy, 0.);
plate05->AddNode(subplate08, 1, ty08);
plate05->GetShape()->ComputeBBox();
nPlates++;
// --- Plate type 6: +x plate (shorted due to beampipe)
TGeoVolumeAssembly* plate06 = new TGeoVolumeAssembly("Plate06");
Double_t sy09 = -box_dy / 2. + box09->GetDY() + 2 * box09->GetDX();
TGeoTranslation* ty09 = new TGeoTranslation("ty09", sx08 + dx, sy09 + dy, 0.);
plate06->AddNode(subplate09, 1, ty09);
plate06->GetShape()->ComputeBBox();
nPlates++;
// --- Plate type 7: +x plate (shorted due to beampipe)
TGeoVolumeAssembly* plate07 = new TGeoVolumeAssembly("Plate07");
Double_t sy10 = -box_dy / 2. + box10->GetDY() + 2 * box10->GetDX();
TGeoTranslation* ty10 = new TGeoTranslation("ty10", sx08 + dx, -sy10 + dy, 0.);
plate07->AddNode(subplate10, 1, ty10);
plate07->GetShape()->ComputeBBox();
nPlates++;
return nPlates;
}
/** ======================================================================= **/
/** ===========================================================================
** 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;
TGeoVolume* s0vol = NULL;
TGeoVolume* halfLadderU = NULL;
TGeoVolume* halfLadderD = NULL;
Double_t shiftZ = 0.;
Double_t ladderY = 0.;
Double_t gapY = 0.;
// --- Ladder 01 x-mirror of 02: 10 sectors, type 4 4 3 2 1 1 2 3 4 4
nSectors = 5;
sectorTypes[0] = 1;
sectorTypes[1] = 2;
sectorTypes[2] = 3;
sectorTypes[3] = 4;
sectorTypes[4] = 4;
s0name = Form("Sector%02d", sectorTypes[0]);
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
shiftZ = 2. * shape->GetDZ() + gkSectorGapZ;
halfLadderU = ConstructHalfLadder(1, "HalfLadder01u", nSectors, sectorTypes, 'r'); // mirrored
halfLadderD = ConstructHalfLadder(1, "HalfLadder01d", nSectors, sectorTypes, 'l'); // mirrored
ConstructLadder(1, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 02: 10 sectors, type 4 4 3 2 1 1 2 3 4 4
nSectors = 5;
sectorTypes[0] = 1;
sectorTypes[1] = 2;
sectorTypes[2] = 3;
sectorTypes[3] = 4;
sectorTypes[4] = 4;
s0name = Form("Sector%02d", sectorTypes[0]);
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
shiftZ = 2. * shape->GetDZ() + gkSectorGapZ;
halfLadderU = ConstructHalfLadder(2, "HalfLadder02u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(2, "HalfLadder02d", nSectors, sectorTypes, 'r');
ConstructLadder(2, halfLadderU, halfLadderD, shiftZ);
nLadders++;
//=====================================================================================
// --- Ladder 13: 1 sector, type 3
nSectors = 1;
sectorTypes[0] = 3;
s0name = Form("Sector%02d", sectorTypes[0]);
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
shiftZ = 2. * shape->GetDZ() + gkSectorGapZ;
//
// top half ladder only (FEBs in the top)
//
halfLadderU = ConstructHalfLadder(13, "HalfLadder13u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(13, "HalfLadder13d", 0, sectorTypes, 'r');
// halfLadderD = ConstructHalfLadder(13, "HalfLadder13d", nSectors, sectorTypes, 'r');
ConstructLadder(13, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 09: 2 sectors, type 3 3 - mSTS
nSectors = 2;
sectorTypes[0] = 3;
sectorTypes[1] = 3;
s0name = Form("Sector%02d", sectorTypes[0]);
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
shiftZ = 2. * shape->GetDZ() + gkSectorGapZ;
//
// bottom half ladder only
//
// halfLadderU = ConstructHalfLadder(9, "HalfLadder09u", nSectors, sectorTypes, 'l');
halfLadderU = ConstructHalfLadder(9, "HalfLadder09u", 0, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(9, "HalfLadder09d", nSectors, sectorTypes, 'r');
//
ConstructLadder(9, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 10: 2 sectors, type 3 4 - mSTS
nSectors = 2;
sectorTypes[0] = 3;
sectorTypes[1] = 4;
s0name = Form("Sector%02d", sectorTypes[0]);
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
shiftZ = 2. * shape->GetDZ() + gkSectorGapZ;
//
// bottom half ladder only
//
// halfLadderU = ConstructHalfLadder(10, "HalfLadder10u", nSectors, sectorTypes, 'l');
halfLadderU = ConstructHalfLadder(10, "HalfLadder10u", 0, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(10, "HalfLadder10d", nSectors, sectorTypes, 'r');
//
ConstructLadder(10, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 11: 3 sectors, type 3 3 3 - mSTS
nSectors = 3;
sectorTypes[0] = 3;
sectorTypes[1] = 3;
sectorTypes[2] = 3;
s0name = Form("Sector%02d", sectorTypes[0]);
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
shiftZ = 2. * shape->GetDZ() + gkSectorGapZ;
//
// bottom half ladder only
//
// halfLadderU = ConstructHalfLadder(11, "HalfLadder11u", nSectors, sectorTypes, 'l');
halfLadderU = ConstructHalfLadder(11, "HalfLadder11u", 0, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(11, "HalfLadder11d", nSectors, sectorTypes, 'r');
//
ConstructLadder(11, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 12: 2 sectors, type 3 4 - mSTS - y-overlap different from 10
nSectors = 2;
sectorTypes[0] = 3;
sectorTypes[1] = 4;
s0name = Form("Sector%02d", sectorTypes[0]);
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
shiftZ = 2. * shape->GetDZ() + gkSectorGapZ;
//
// bottom half ladder only
//
// halfLadderU = ConstructHalfLadder(12, "HalfLadder12u", nSectors, sectorTypes, 'l');
halfLadderU = ConstructHalfLadder(12, "HalfLadder12u", 0, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(12, "HalfLadder12d", nSectors, sectorTypes, 'r');
//
ConstructLadder(12, halfLadderU, halfLadderD, shiftZ);
nLadders++;
//=====================================================================================
// --- Ladder 03 x-mirror of 04: 10 sectors, type 5 4 3 3 6 6 3 3 4 5
nSectors = 5;
sectorTypes[0] = 6;
sectorTypes[1] = 3;
sectorTypes[2] = 3;
sectorTypes[3] = 4;
sectorTypes[4] = 5;
s0name = Form("Sector%02d", sectorTypes[0]);
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
shiftZ = 2. * shape->GetDZ() + gkSectorGapZ;
halfLadderU = ConstructHalfLadder(3, "HalfLadder03u", nSectors, sectorTypes, 'r'); // mirrored
halfLadderD = ConstructHalfLadder(3, "HalfLadder03d", nSectors, sectorTypes, 'l'); // mirrored
ConstructLadder(3, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 04: 10 sectors, type 5 4 3 3 6 6 3 3 4 5
nSectors = 5;
sectorTypes[0] = 6;
sectorTypes[1] = 3;
sectorTypes[2] = 3;
sectorTypes[3] = 4;
sectorTypes[4] = 5;
s0name = Form("Sector%02d", sectorTypes[0]);
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
shiftZ = 2. * shape->GetDZ() + gkSectorGapZ;
halfLadderU = ConstructHalfLadder(4, "HalfLadder04u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(4, "HalfLadder04d", nSectors, sectorTypes, 'r');
ConstructLadder(4, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 14: 6 sensors, type 5 4 3 3 4 5
nSectors = 3;
sectorTypes[0] = 3;
sectorTypes[1] = 4;
sectorTypes[2] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(14, "HalfLadder14u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(14, "HalfLadder14d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(14, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 15: 4 sectors, type 4 4 4 4
nSectors = 2;
sectorTypes[0] = 4;
sectorTypes[1] = 4;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(15, "HalfLadder15u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(15, "HalfLadder15d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(15, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 05 x-mirror of 06: 10 sectors, type 5 5 4 3 7 7 3 4 5 5
nSectors = 5;
sectorTypes[0] = 7;
sectorTypes[1] = 3;
sectorTypes[2] = 4;
sectorTypes[3] = 5;
sectorTypes[4] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(5, "HalfLadder05u", nSectors, sectorTypes, 'r'); // mirrored
halfLadderD = ConstructHalfLadder(5, "HalfLadder05d", nSectors, sectorTypes, 'l'); // mirrored
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(5, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 06: 10 sectors, type 5 5 4 3 7 7 3 4 5 5
nSectors = 5;
sectorTypes[0] = 7;
sectorTypes[1] = 3;
sectorTypes[2] = 4;
sectorTypes[3] = 5;
sectorTypes[4] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(6, "HalfLadder06u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(6, "HalfLadder06d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(6, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 16: 10 sectors, type 5 5 4 3 3 3 3 4 5 5
nSectors = 5;
sectorTypes[0] = 3;
sectorTypes[1] = 3;
sectorTypes[2] = 4;
sectorTypes[3] = 5;
sectorTypes[4] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(16, "HalfLadder16u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(16, "HalfLadder16d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(16, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 17: 8 sectors, type 5 5 4 3 3 4 5 5
nSectors = 4;
sectorTypes[0] = 3;
sectorTypes[1] = 4;
sectorTypes[2] = 5;
sectorTypes[3] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(17, "HalfLadder17u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(17, "HalfLadder17d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(17, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 18: 6 sectors, type 5 5 4 4 5 5
nSectors = 3;
sectorTypes[0] = 4;
sectorTypes[1] = 5;
sectorTypes[2] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(18, "HalfLadder18u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(18, "HalfLadder18d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(18, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 19: 4 sectors, type 5 5 5 5
nSectors = 2;
sectorTypes[0] = 5;
sectorTypes[1] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(19, "HalfLadder19u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(19, "HalfLadder19d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(19, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 07: 10 sectors, type 5 5 4 3 3 gap 3 3 4 5 5, with gap
nSectors = 5;
sectorTypes[0] = 3;
sectorTypes[1] = 3;
sectorTypes[2] = 4;
sectorTypes[3] = 5;
sectorTypes[4] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(7, "HalfLadder07u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(7, "HalfLadder07d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
gapY = 4.4;
ConstructLadderWithGap(7, halfLadderU, halfLadderD, 2 * gapY);
nLadders++;
// --- Ladder 20: 10 sectors, type 5 5 5 3 2 2 3 5 5 5
nSectors = 5;
sectorTypes[0] = 2;
sectorTypes[1] = 3;
sectorTypes[2] = 5;
sectorTypes[3] = 5;
sectorTypes[4] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(20, "HalfLadder20u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(20, "HalfLadder20d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(20, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 21: 2 sectors, type 5 5
nSectors = 1;
sectorTypes[0] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(21, "HalfLadder21u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(21, "HalfLadder21d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(21, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 08: 8 sectors, type 5 5 5 4 gap 4 5 5 5, with gap
nSectors = 4;
sectorTypes[0] = 4;
sectorTypes[1] = 5;
sectorTypes[2] = 5;
sectorTypes[3] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(8, "HalfLadder08u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(8, "HalfLadder08d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
gapY = 4.57;
ConstructLadderWithGap(8, halfLadderU, halfLadderD, 2 * gapY);
nLadders++;
// --- Ladder 22: 10 sectors, type 5 5 5 4 3 3 4 5 5 5
nSectors = 5;
sectorTypes[0] = 3;
sectorTypes[1] = 4;
sectorTypes[2] = 5;
sectorTypes[3] = 5;
sectorTypes[4] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(22, "HalfLadder22u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(22, "HalfLadder22d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(22, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 23: 10 sectors, type 5 5 4 4 3 3 4 4 5 5
nSectors = 5;
sectorTypes[0] = 3;
sectorTypes[1] = 4;
sectorTypes[2] = 4;
sectorTypes[3] = 5;
sectorTypes[4] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(23, "HalfLadder23u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(23, "HalfLadder23d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(23, halfLadderU, halfLadderD, shiftZ);
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
**/
TGeoVolume* ConstructHalfLadder(Int_t ladderid, const TString& name, Int_t nSectors, Int_t* sectorTypes, char align)
{
// --- 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", (char*) 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
if (ladderid != 10)
ladderY -= Double_t(nSectors - 1) * gkSectorOverlapY;
else
ladderY -= Double_t(nSectors - 1) * gkSectorOverlapYL10;
// --- Add gaps in z direction
ladderZ += Double_t(nSectors - 1) * gkSectorGapZ;
// --- Create and place modules
Bool_t L12firstpass = true; // false, if ladder was shifted already once
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
if (L12firstpass == true)
if (ladderid == 12)
{
L12firstpass = false; // false, if ladder was shifted already once
yPosSect += (gkSectorOverlapYL10 - gkSectorOverlapY) / 2.; // shift ladder type 12 downwards by 2.2 mm
// cout << "DE20230209 " << (gkSectorOverlapYL10 - gkSectorOverlapY) / 2. << endl;
}
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);
// // DEDE
// // drop 2nd module on this halfladder for mSTS Nov 2019
// // halfLadder->AddNode(module, iSector+1, trans);
// if (ladderid == 9) cout << "DE333 " << iSector << endl;
// if (ladderid == 9)
// if (iSector == 0)
// halfLadder->AddNode(module, iSector+1, trans);
halfLadder->AddNode(module, iSector + 1, trans);
halfLadder->GetShape()->ComputeBBox();
if (ladderid != 10)
yPosSect += 0.5 * sectorY - gkSectorOverlapY;
else
yPosSect += 0.5 * sectorY - gkSectorOverlapYL10;
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("Ladder%02d", LadderIndex);
Int_t i;
Double_t j;
Int_t YnumOfFrameBoxes = (Int_t)(ladderY / gkFrameStep) + 1; // calculate number of elements
if (LadderIndex == 1 || LadderIndex == 2) // set even number of ladder elements for these ladders in station 1 and 2
YnumOfFrameBoxes--;
// if (LadderIndex == 3 || LadderIndex == 4) // set even number of ladder elements for these ladders in station 3 and 4
// YnumOfFrameBoxes++;
YnumOfFrameBoxes += YnumOfFrameBoxes % 2; // use even number of frame elements for all ladders
// cout << "DE: lad " << LadderIndex << " inum " << YnumOfFrameBoxes << endl;
// DEDE
TGeoBBox* fullFrameShp = new TGeoBBox(name + "_FullFrameBox_shp", xu / 2., gkFrameStep / 2.,
(xu / 2. + sqrt(2.) * gkFrameThickness / 2.) / 2.);
// TGeoBBox* fullFrameShp = new TGeoBBox (name+"_FullFrameBox_shp", xu/2., gkFrameStep/2., (gkSectorGapZFrame+xu/2.+sqrt(2.)*gkFrameThickness/2.)/2.);
TGeoVolume* fullFrameBoxVol = new TGeoVolume(name + "_FullFrameBox", fullFrameShp, gStsMedium);
// cout << "DE: frame Z size " << (xu/2.+sqrt(2.)*gkFrameThickness/2.) << " cm" << endl;
ConstructFrameElement("FrameBox", 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);
// cout << "DE: i " << i << " j " << j << endl;
if (LadderIndex <= 2) // central ladders in stations 1 to 8
{
if ((j >= -1) && (j <= 1)) // keep the inner 4 elements free for the cone
continue;
}
else if (LadderIndex <= 8) // central ladders in stations 1 to 8
{
if ((j >= -2) && (j <= 2)) // keep the inner 4 elements free for the cone
continue;
}
// DEDE
ladder->AddNode(fullFrameBoxVol, i,
new TGeoCombiTrans(name + "_FullFrameBox_posrot", 0., j * gkFrameStep,
-ladderZ / 2. - (xu / 2. + sqrt(2.) * gkFrameThickness / 2.) / 2.,
fullFrameRot));
// ladder->AddNode(fullFrameBoxVol, i, new TGeoCombiTrans(name+"_FullFrameBox_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
**
** 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 overlap and displaced in z bz shiftZ.
**
** Arguments:
** name volume name
** halfLadderU pointer to upper half ladder
** halfLadderD pointer to lower half ladder
** shiftZ relative displacement along the z axis
**/
TGeoVolume* ConstructLadder(Int_t LadderIndex, TGeoVolume* halfLadderU, TGeoVolume* halfLadderD, 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("Ladder%02d", LadderIndex);
TGeoVolumeAssembly* ladder = new TGeoVolumeAssembly(name);
Double_t ladderX = TMath::Max(xu, xd);
// Double_t ladderY = yu + yd - gkSectorOverlapY;
Double_t ladderY = TMath::Max(yu, yd);
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
// cout << "DEEEE: li " << LadderIndex
// << " || xu " << xu << " yu " << yu << " zu " << zu
// << " || xd " << xd << " yd " << yd << " zd " << zd
// << " || ypu " << yPosU << " ypd " << yPosD
// << endl;
if (yu == 0) // if no top (= only bottom) half ladder
{
yPosD = 0.5 * (ladderY - yd); // top aligned
zPosD = 0.5 * (ladderZ - zd); // 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); // take width of top HL
AddCarbonLadder(LadderIndex, ladder, ladderX, ladderY, ladderZ); // take width of any HL
// --------------------------------------------------------------------------
return ladder;
}
/** ======================================================================= **/
/** ===========================================================================
** 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
**/
TGeoVolume* ConstructLadderWithGap(Int_t LadderIndex, TGeoVolume* halfLadderU, TGeoVolume* halfLadderD, Double_t gapY)
{
// --- Some variables
TGeoBBox* shape = NULL;
Int_t i;
Double_t j;
// --- 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("Ladder%02d", 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);
// --- 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 station
**
** The station 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
** rHole radius of inner hole
**/
// TGeoVolume* ConstructStation(const char* name,
// Int_t iStation,
TGeoVolume* ConstructStation(Int_t iStation, Int_t nLadders, Int_t* ladderTypes, Double_t rHole)
{
TString name;
name = Form("Station%02d", iStation + 1); // 1,2,3,4,5,6,7,8
// name = Form("Station%02d", iStation); // 0,1,2,3,4,5,6,7 - Station00 missing in output
// --- Some local variables
TGeoShape* statShape = NULL;
TGeoBBox* ladderShape = NULL;
TGeoBBox* shape = NULL;
TGeoVolume* ladder = NULL;
TString ladderName;
// --- Determine size of station from ladders
Double_t statX = 0.;
Double_t statY = 0.;
Double_t statZeven = 0.;
Double_t statZodd = 0.;
Double_t statZ = 0.;
for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) {
Int_t ladderType = ladderTypes[iLadder];
ladderName = Form("Ladder%02d", ladderType);
ladder = gGeoManager->GetVolume(ladderName);
if (!ladder) Fatal("ConstructStation", Form("Volume %s not found", ladderName.Data()));
shape = (TGeoBBox*) ladder->GetShape();
statX += 2. * shape->GetDX();
statY = TMath::Max(statY, 2. * shape->GetDY());
if (iLadder % 2) statZeven = TMath::Max(statZeven, 2. * shape->GetDZ());
else
statZodd = TMath::Max(statZodd, 2. * shape->GetDZ());
}
statX -= Double_t(nLadders - 1) * gkLadderOverlapX;
statZ = statZeven + gkLadderGapZ + statZodd;
// --- Create station volume
TString boxName(name);
boxName += "_box";
cout << "before statZ/2.: " << statZ / 2. << endl;
statZ = 2 * 4.5; // changed Z size of the station for cone and gkLadderGapZ
cout << "fixed to statZ/2.: " << statZ / 2. << endl;
TGeoBBox* statBox = new TGeoBBox(boxName, statX / 2., statY / 2., statZ / 2.);
// TString tubName(name);
// tubName += "_tub";
// TString expression = boxName + "-" + tubName;
// // TGeoTube* statTub = new TGeoTube(tubName, 0., rHole, statZ/2.);
// // TGeoBBox* statTub = new TGeoBBox(tubName, rHole, rHole, statZ/2.);
// TGeoBBox* statTub = new TGeoBBox(tubName, rHole, rHole, statZ/2.+.1); // .1 opens the hole in z direction
//
// statShape = new TGeoCompositeShape(name, expression.Data());
// TGeoVolume* station = new TGeoVolume(name, statShape, gStsMedium);
// TGeoVolume* station = new TGeoVolume(name, statBox, gStsMedium);
TGeoVolumeAssembly* station = new TGeoVolumeAssembly(name); // do not produce keeping volumes
Double_t subtractedVal;
// --- Place ladders in station
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++) {
Int_t ladderType = ladderTypes[iLadder];
ladderName = Form("Ladder%02d", ladderType);
ladder = gGeoManager->GetVolume(ladderName);
shape = (TGeoBBox*) ladder->GetShape();
if (maxdz < shape->GetDZ()) maxdz = shape->GetDZ();
}
for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) {
Int_t ladderType = ladderTypes[iLadder];
ladderName = Form("Ladder%02d", ladderType);
ladder = gGeoManager->GetVolume(ladderName);
shape = (TGeoBBox*) ladder->GetShape();
xPos += shape->GetDX();
cout << "xPos2: " << xPos << endl;
yPos = 0.; // vertically centred
TGeoRotation* rot = new TGeoRotation();
if (gkConstructFrames)
// DEDE
subtractedVal = sqrt(2.) * gkFrameThickness / 2. + shape->GetDX();
// subtractedVal = 2*gkSectorGapZFrame + sqrt(2.)*gkFrameThickness/2. + shape->GetDX();
else
subtractedVal = 0.;
// zPos = 0.5 * gkLadderGapZ + (shape->GetDZ()-subtractedVal/2.); // non z-aligned ladders
zPos = 0.5 * gkLadderGapZ + (2 * maxdz - shape->GetDZ() - subtractedVal / 2.); // z-aligned ladders
cout << "DE ladder" << ladderTypes[iLadder] << " dx: " << shape->GetDX() << " dy: " << shape->GetDY()
<< " dz: " << shape->GetDZ() << " max dz: " << maxdz << endl;
cout << "DE ladder" << ladderTypes[iLadder] << " fra: " << gkFrameThickness / 2. << " sub: " << subtractedVal
<< " zpo: " << zPos << endl
<< endl;
// mCBM
if ((iStation % 2 == 0) && (iStation >= 1)) // flip ladders to reproduce CAD layout
// if (iStation % 2 == 0) // flip ladders for even stations to reproduce CAD layout
// even station 0,2,4,6
// if (iStation % 2 == 1) // flip ladders for odd stations to reproduce CAD layout
// odd station 1,3,5,7
{
// --- Unrotated ladders --- downstream
if ((nLadders / 2 + iLadder) % 2) {
// zPos = 0.5 * gkLadderGapZ + (shape->GetDZ()-subtractedVal/2.);
rot->RotateY(180.);
}
// --- Rotated ladders --- upstream
else {
// zPos = -0.5 * gkLadderGapZ - (shape->GetDZ()-subtractedVal/2.);
zPos = -zPos;
}
}
else
// odd station 1,3,5,7
{
// --- Unrotated ladders --- upstream
if ((nLadders / 2 + iLadder) % 2) {
// zPos = -0.5 * gkLadderGapZ - (shape->GetDZ()-subtractedVal/2.);
zPos = -zPos;
}
// --- Rotated ladders --- downstream
else {
// zPos = 0.5 * gkLadderGapZ + (shape->GetDZ()-subtractedVal/2.);
rot->RotateY(180.);
// zPos += 14.; // move STS ladder from position of C-frame #1 to C-frame #3 - March 2019 version
}
}
TGeoCombiTrans* trans = new TGeoCombiTrans(xPos, yPos, zPos, rot);
// enable or disable units
// Unit -1
if ((ladderType == 13) && (iLadder + 1 == 1)) {
cout << "including " << ladderName << " " << ladderType << " " << iLadder + 1 << endl;
station->AddNode(ladder, iLadder + 1, trans);
}
// Unit 0
if ((ladderType == 9) && (iLadder + 1 == 1)) {
cout << "including " << ladderName << " " << ladderType << " " << iLadder + 1 << endl;
station->AddNode(ladder, iLadder + 1, trans);
}
// Unit 1
if ((ladderType == 9) && (iLadder + 1 == 2)) {
cout << "including " << ladderName << " " << ladderType << " " << iLadder + 1 << endl;
station->AddNode(ladder, iLadder + 1, trans);
}
// Unit 2
if ((ladderType == 12) && (iLadder + 1 == 2)) {
cout << "including " << ladderName << " " << ladderType << " " << iLadder + 1 << endl;
station->AddNode(ladder, iLadder + 1, trans);
}
// Unit 3 right (far from beam)
if ((ladderType == 10) && (iLadder + 1 == 1)) {
cout << "including " << ladderName << " " << ladderType << " " << iLadder + 1 << endl;
station->AddNode(ladder, iLadder + 1, trans);
}
// Unit 3 left (close to beam)
if ((ladderType == 11) && (iLadder + 1 == 3)) {
cout << "including " << ladderName << " " << ladderType << " " << iLadder + 1 << endl;
station->AddNode(ladder, iLadder + 1, trans);
}
// include all ladders
// station->AddNode(ladder, iLadder+1, trans);
// // drop upstream ladder for mSTS Nov 2019
// // station->AddNode(ladder, iLadder+1, trans);
// cout << "DE222 " << iLadder << endl;
// if (iLadder == 1) station->AddNode(ladder, iLadder+1, trans);
station->GetShape()->ComputeBBox();
xPos += shape->GetDX() - gkLadderOverlapX;
cout << "xPos3: " << xPos << endl;
}
return station;
}
/** ======================================================================= **/
/** ===========================================================================
** 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)
{
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()) {
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");
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.));
TGeoBBox* frameVertPillarShp;
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 pillar
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);
TGeoCombiTrans* slopeTrRot =
new TGeoCombiTrans(name + "_slopepillar_posrot_1", 0., 0., -(x + sqrt(2.) * t - 2. * t) / 2., slopeRot);
frameBoxVol->AddNode(frameSlopePillarVol, 1, slopeTrRot);
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;
}
/** ======================================================================= **/
/* Copyright (C) 2012-2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: David Emschermann [committer] */
/******************************************************************************
** Creation of STS geometry in ROOT format (TGeo).
**
** @file create_stsgeo_v24b.C
** @author David Emschermann <d.emschermann@gsi.de>
** @author Volker Friese <v.friese@gsi.de>
** @since 15 June 2012
** @date 09.05.2014
** @author Tomas Balog <T.Balog@gsi.de>
*
** 2024-07-08 - MS - v24d: Based on the v24c (similar to v24c). In this version of the geometry we introduce passive volumes for e.g. C-frames,
** mSTS upgrade module box, box on the top of the main msts-box, beam-pipe screen and also the bug fix done for the ladder winding;
** The bug of the ladder height (when we put it horizontally) was present in the geometry since the year 2018-2019 (roughly).
** ( https://indico.gsi.de/event/8579/contributions/37306/attachments/27063/33854/CBM-TN-19006-v1.1.pdf )
** 2024-04-29 - MS - v24c: based on v24b, shift STS in Z to position measured in the cave
** as it was seen that the station 0 module position was not correct
** and the measurement was done again in the CAVE. The position of
** the Back-side of the STS box was expected to be at 57.8 cm.
** We opened the side wall of the sts-box and did the measurement
** inside the box for the placement of the C-Frames.
** The thickness of the back-side wall is 0.5 cm which means from
** inside the box (57.8-0.5=57.3) the last C-Frame edge is at 7 cm
** away (50.3). The edge of the front wall from out-side is at 22.8 cm
** (35 cm away from the backside wall). And the first module box wall
** from the wall is 1.6 cm away.
** 2024-03-27 - DE - v24b: based on v24a, shift STS in z to position measured in the cave
** 2024-03-26 - DE - v24a: add preliminary version of mSTS v24a for the 2024_03_22 gold setup
** 2024-02-06 - DE - v24a: position the STS sensors as measured in the cave
** 2023-06-29 - DE - v23b: add a 6x6 cm2 module at z=16.5 cm, keep STS box around 2x2 and 3x3 (from v22e)
** 2023-06-27 - DE - v23a: add a 6x6 cm2 module at z=14.0 cm (nominal), keep STS box around 2x2 and 3x3 (from v22e)
** 2023-02-09 - DE - v22f: decrease distance between statios 0 and 1 from 140 mm to 135 mm, to reflect CAD
** 2023-02-09 - DE - v22f: increase gap between units of a station gkLadderGapZ from 10 mm to 12 mm, to reflect CAD
** 2023-02-09 - DE - v22f: shift ladder U2 downwards in y by 2.2 mm
** 2023-02-08 - DE - v22f: introduce ladder type 12 (based on 10) for U2, but with original gkSectorOverlapY of 4.6 mm
** 2022-09-13 - DE - v22e: correct gkSectorOverlapY to 9.0 mm for the ladder type 10 (with 12 cm sensors)
** 2022-03-18 - DE - v22d: add position offset for mSTS 2022_03_22_iron as surveyed in the cave
** 2022-02-01 - DE - v22b: add position offset for mSTS 07_2021 as surveyed in the cave
** 2022-01-25 - DE - v22a: add a aluminium box around v20e
** 2020-05-16 - DE - v20e: swap ladders in unit 3 - 3x 6x6 on beam side
** 2020-03-21 - DE - v20d: build mSTS for March 2020 - 1 ladder - shift -3 cm in x
** 2020-03-11 - DE - v20c: build mSTS for March 2021 - 5 ladders
** 2020-03-11 - DE - v20b: build mSTS for May 2020 - 2 ladders
** 2020-03-11 - DE - v20a: build mSTS for March 2020 - 1 ladder
**
** 2019-12-04 - DE - v19d: build 2nd mSTS v19d station from one 6x6 and one 6x12 cm x cm sensors
** 2019-12-04 - DE - v19c: build 1st mSTS v19c station at nominal position
** 2019-08-12 - DE - v19a: mSTS as built in March 2019 - the mSTS FEBs are in the bottom
** 2019-03-15 - DE - v18n: mSTS as built in March 2019 - downstream ladder of station 0 at position of station 1
** 2018-01-18 - DE - v18g: set overlaps in X and Y according to mSTS CAD model
**
** v18f: flip orientation of carbon ladders for primary beam left of mSTS, change z-positions to 30 and 45 cm
** v18e: 2 stations, derived from v15b, 1st 2x2, 2nd of 3x3 sensor array, sensor size 6x6 cm2 with carbon ladder supports
** v18d: 2 stations of 3x3 sensor array, sensor size 6x6 cm2 with carbon ladder supports
** v18c: (causes segfault due to divide) 2 stations of 3x3 sensor array, sensor size 6x6 cm2 with carbon ladder supports
** v18b: 2 stations of 4x4 sensor array, sensor size 6x6 cm2
** v18a: 2 stations of 3x3 sensor array, sensor size 6x6 cm2
**
** 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 "TGeoCompositeShape.h"
#include "TGeoCone.h"
#include "TGeoManager.h"
#include "TGeoPara.h"
#include "TGeoTube.h"
#include <iomanip>
#include <iostream>
// ------------- Installation offset -----------------------------------
// position in x and y agrees within 2 mm to CbmRoot geometry (01.02.2022)
const Double_t gOffX = 0.0; // Offset from nominal position
const Double_t gOffY = 0.0; // Offset from nominal position
// 2023
// const Double_t gOffZ = 5.0; // Offset from nominal position
// 2024
const Double_t gOffZ = 4.55; // Offset from nominal position
const Bool_t IncludeBox = true; // false; // true, if STS box is plotted
// ------------- Steering variables -----------------------------------
// ---> Horizontal width of sensors [cm]
const Double_t gkSensorSizeX = 6.2092;
// ---> 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
const Double_t gkSectorOverlapYL10 = 0.90; // for ladders with 124 mm sensors - Oleg CAD 13/09/2022
// ---> 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 = 1.20; // DEJH -> 0.90 / 0.50
// v22e const Double_t gkLadderGapZ = 1.00; // DEJH -> 0.90 / 0.50
// ---> Gap in z between lowest sector to carbon support structure [cm]
const Double_t gkSectorGapZFrame = 0.10;
// ---> 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; // kFALSE; // switch this false for v15a
const Bool_t gkConstructFrames = kTRUE; // kFALSE; // switch this false for v15a
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;
// ----------------------------------------------------------------------------
// ------------- 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
// ----------------------------------------------------------------------------
Int_t CreateSubplates();
Int_t CreatePlates();
Int_t CreateSensors();
Int_t CreateSectors();
Int_t CreateLadders();
void CheckVolume(TGeoVolume* volume);
void CheckVolume(TGeoVolume* volume, fstream& file);
TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x);
TGeoVolume* ConstructSmallCone(Double_t coneDz);
TGeoVolume* ConstructBigCone(Double_t coneDz);
TGeoVolume* ConstructHalfLadder(Int_t ladderid, const TString& name, Int_t nSectors, Int_t* sectorTypes, char align);
TGeoVolume* ConstructLadder(Int_t LadderIndex, TGeoVolume* halfLadderU, TGeoVolume* halfLadderD, Double_t shiftZ);
TGeoVolume* ConstructLadderWithGap(Int_t LadderIndex, TGeoVolume* halfLadderU, TGeoVolume* halfLadderD, Double_t gapY);
TGeoVolume* ConstructStation(Int_t iStation, Int_t nLadders, Int_t* ladderTypes, Double_t rHole);
void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile);
void PostProcessGdml(TGeoVolume* gdmlTop);
void CheckVolumes(TGeoVolume* volume, fstream& file, Bool_t listChildren = kTRUE);
// ============================================================================
// ====== Main function =====
// ============================================================================
void create_stsgeo_v24d(const char* geoTag = "v24d_mcbm")
{
// ------- Geometry file name (output) ----------------------------------
TString geoFileName = "sts_";
geoFileName = geoFileName + geoTag + ".geo.root?reproducible";
// --------------------------------------------------------------------------
// ------- 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_v24d.C" << endl << 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 FairRunSim to ensure the correct unit system
FairRunSim* sim = new FairRunSim();
// ------- 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");
// ---> 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");
// ---> 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");
// ---> STS Beam_Pipe_Screen_Cut
FairGeoMedium* mSTS_PLA = geoMedia->getMedium("STS_PLA");
if (!mSTS_PLA) Fatal("Main", "FairMedium STS_PLA not found");
geoBuild->createMedium(mSTS_PLA);
TGeoMedium* STS_PLA = gGeoMan->GetMedium("STS_PLA");
if (!STS_PLA) Fatal("Main", "Medium STS_PLA not found");
// ---> STS FEB Material
FairGeoMedium* mSTSFEBMaterial = geoMedia->getMedium("STSFEBMaterial");
if (!mSTSFEBMaterial) Fatal("Main", "FairMedium STSFEBMaterial not found");
geoBuild->createMedium(mSTSFEBMaterial);
TGeoMedium* STSFEBMaterial = gGeoMan->GetMedium("STSFEBMaterial");
if (!STSFEBMaterial) Fatal("Main", "Medium STSFEBMaterial not found");
// ---
gStsMedium = air;
// --------------------------------------------------------------------------
// -------------- Create geometry and top volume -------------------------
gGeoMan = (TGeoManager*) gROOT->FindObject("FAIRGeom");
gGeoMan->SetName("STSgeom");
TGeoVolume* top = new TGeoVolumeAssembly("TOP");
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(kYellow);
if (iSensor == 2) sensor->SetLineColor(kRed);
if (iSensor == 3) sensor->SetLineColor(kBlue);
if (iSensor == 4) sensor->SetLineColor(kAzure + 7);
if (iSensor == 5) sensor->SetLineColor(kGreen);
if (iSensor == 6) 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 --------------------------------------
TString name = "";
cout << endl << endl;
cout << "===> Creating ladders...." << endl;
infoFile << endl << "Ladders:" << endl;
Int_t nLadders = CreateLadders();
for (Int_t iLadder = 1; iLadder <= nLadders; iLadder++) {
cout << endl;
name = Form("Ladder%02d", iLadder);
TGeoVolume* ladder = gGeoMan->GetVolume(name);
CheckVolume(ladder);
CheckVolume(ladder, infoFile);
CheckVolume(ladder->GetNode(0)->GetVolume(), infoFile);
}
// --------------------------------------------------------------------------
// ---------------- Create cone -----------------------------------------
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 -------------------------------------
// Float_t statPos[8] = {30., 40., 50., 60., 70., 80., 90., 100.};
//DE23 Float_t statPos[8] = {13.75, 28.25, 41.75, 50., 60., 70., 80., 90.};
// Float_t statPos[8] = {14., 28., 42., 50., 60., 70., 80., 90.};
// 2023
// Float_t statPos[8] = {11.5, 28., 42., 50., 60., 70., 80., 90.};
// 2024
//
// from cave (Jens)
// hier die Sensorpositionen in Z-Richtung für das mSTS Upgrade.
// Target to Station 0: dZ=170 165
// Station 0 to 1: dZ=125 290
// Station 1 to 2: dZ=135 425
//
// 2024
//Float_t statPos[8] = {16.5, 29.0, 42.5, 50., 60., 70., 80., 90.};
Float_t statPos[8] = {12.065, 26.50, 40.0, 50., 60., 70., 80., 90.};
//
// Float_t statPos[8] = {30., 45., 50., 60., 70., 80., 90., 100.};
cout << endl << endl;
cout << "===> Creating stations...." << endl;
infoFile << endl << "Stations: ";
nLadders = 0;
Int_t ladderTypes[20];
Double_t statZ = 0.;
Double_t rHole = 0.;
TGeoBBox* statShape = NULL;
TGeoTranslation* statTrans = NULL;
// --- Station 01: 8 ladders, type 3 2 2 1 1 2 2 3
cout << endl;
statZ = 30.;
rHole = 2.0;
nLadders = 1;
ladderTypes[0] = 13;
TGeoVolume* station01 = ConstructStation(0, nLadders, ladderTypes, rHole);
CheckVolume(station01);
CheckVolume(station01, infoFile);
infoFile << "Position z = " << statPos[0] << endl;
// --- Station 02: 12 ladders, type 4 3 3 2 2 1 1 2 2 3 3 4
cout << endl;
statZ = 40.;
rHole = 2.0;
nLadders = 3;
nLadders = 2;
ladderTypes[0] = 9;
ladderTypes[1] = 9;
// v22e ladderTypes[0] = 10;
// v22e ladderTypes[1] = 10;
// v22e ladderTypes[2] = 11; // triple ladder
TGeoVolume* station02 = ConstructStation(1, nLadders, ladderTypes, rHole);
CheckVolume(station02);
CheckVolume(station02, infoFile);
infoFile << "Position z = " << statPos[1] << endl;
// --- Station 03: 12 ladders, type 8 7 6 6 6 5 5 6 6 6 7 8
cout << endl;
statZ = 50.;
rHole = 2.9;
nLadders = 3;
ladderTypes[0] = 10;
ladderTypes[1] = 12;
ladderTypes[2] = 11; // triple ladder
TGeoVolume* station03 = ConstructStation(2, nLadders, ladderTypes, rHole);
CheckVolume(station03);
CheckVolume(station03, infoFile);
infoFile << "Position z = " << statPos[2] << endl;
// // --- Station 04: 14 ladders, type 9 8 7 6 6 6 5 5 6 6 7 8 9
// cout << endl;
// statZ = 60.;
// rHole = 2.9;
// nLadders = 14;
// ladderTypes[0] = 15; // 42; // 9;
// ladderTypes[1] = 14; // 34; // 8;
// ladderTypes[2] = 13; // 33; // 7;
// ladderTypes[3] = 12; // 32; // 6;
// ladderTypes[4] = 12; // 32; // 6;
// ladderTypes[5] = 12; // 32; // 6;
// ladderTypes[6] = 4; // 41; // 5;
// ladderTypes[7] = 4; // 41; // 5;
// ladderTypes[8] = 12; // 32; // 6;
// ladderTypes[9] = 12; // 32; // 6;
// ladderTypes[10] = 12; // 32; // 6;
// ladderTypes[11] = 13; // 33; // 7;
// ladderTypes[12] = 14; // 34; // 8;
// ladderTypes[13] = 15; // 42; // 9;
// TGeoVolume* station04 = ConstructStation(3, nLadders, ladderTypes, rHole);
//
// if (gkConstructCones) {
// // upstream
// TGeoRotation* coneRot41 = new TGeoRotation;
// coneRot41->RotateZ(-90);
// coneRot41->RotateY(180);
// // TGeoCombiTrans* conePosRot41 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-0.3-gkLadderGapZ/2., coneRot41);
// TGeoCombiTrans* conePosRot41 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-0.285-gkLadderGapZ/2., coneRot41);
// station04->AddNode(coneBigVolum, 1, conePosRot41);
//
// // downstream
// TGeoRotation* coneRot42 = new TGeoRotation;
// coneRot42->RotateZ(-90);
// // TGeoCombiTrans* conePosRot42 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+0.3+gkLadderGapZ/2., coneRot42);
// TGeoCombiTrans* conePosRot42 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+0.285+gkLadderGapZ/2., coneRot42);
// station04->AddNode(coneBigVolum, 2, conePosRot42);
//
// station04->GetShape()->ComputeBBox();
// }
//
// CheckVolume(station04);
// CheckVolume(station04, infoFile);
// infoFile << "Position z = " << statPos[3] << endl;
//
//
// // --- Station 05: 14 ladders, type 14 13 12 12 11 11 10 10 11 11 12 12 13 14
// cout << endl;
// statZ = 70.;
// rHole = 3.7;
// nLadders = 14;
// ladderTypes[0] = 19; // 55; // 14;
// ladderTypes[1] = 18; // 54; // 13;
// ladderTypes[2] = 17; // 53; // 12;
// ladderTypes[3] = 17; // 53; // 12;
// ladderTypes[4] = 16; // 52; // 11;
// ladderTypes[5] = 16; // 52; // 11;
// ladderTypes[6] = 5; // 51; // 23; // 10;
// ladderTypes[7] = 5; // 51; // 23; // 10;
// ladderTypes[8] = 16; // 52; // 11;
// ladderTypes[9] = 16; // 52; // 11;
// ladderTypes[10] = 17; // 53; // 12;
// ladderTypes[11] = 17; // 53; // 12;
// ladderTypes[12] = 18; // 54; // 13;
// ladderTypes[13] = 19; // 55; // 14;
// TGeoVolume* station05 = ConstructStation(4, nLadders, ladderTypes, rHole);
//
// if (gkConstructCones) {
// // upstream
// TGeoRotation* coneRot51 = new TGeoRotation;
// coneRot51->RotateZ(90);
// coneRot51->RotateY(180);
// // TGeoCombiTrans* conePosRot51 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-0.3-gkLadderGapZ/2., coneRot51);
// TGeoCombiTrans* conePosRot51 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-0.285-gkLadderGapZ/2., coneRot51);
// station05->AddNode(coneBigVolum, 1, conePosRot51);
//
// // downstream
// TGeoRotation* coneRot52 = new TGeoRotation;
// coneRot52->RotateZ(90);
// // TGeoCombiTrans* conePosRot52 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+0.3+gkLadderGapZ/2., coneRot52);
// TGeoCombiTrans* conePosRot52 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+0.285+gkLadderGapZ/2., coneRot52);
// station05->AddNode(coneBigVolum, 2, conePosRot52);
//
// station05->GetShape()->ComputeBBox();
// }
//
// CheckVolume(station05);
// CheckVolume(station05, infoFile);
// infoFile << "Position z = " << statPos[4] << endl;
//
//
// // --- Station 06: 14 ladders, type 14 13 12 12 11 11 10 10 11 11 12 12 13 14
// cout << endl;
// statZ = 80.;
// rHole = 3.7;
// nLadders = 14;
// ladderTypes[0] = 19; // 55; // 14;
// ladderTypes[1] = 18; // 54; // 13;
// ladderTypes[2] = 17; // 53; // 12;
// ladderTypes[3] = 17; // 53; // 12;
// ladderTypes[4] = 16; // 52; // 11;
// ladderTypes[5] = 16; // 52; // 11;
// ladderTypes[6] = 6; // 61; // 10;
// ladderTypes[7] = 6; // 61; // 10;
// ladderTypes[8] = 16; // 52; // 11;
// ladderTypes[9] = 16; // 52; // 11;
// ladderTypes[10] = 17; // 53; // 12;
// ladderTypes[11] = 17; // 53; // 12;
// ladderTypes[12] = 18; // 54; // 13;
// ladderTypes[13] = 19; // 55; // 14;
// TGeoVolume* station06 = ConstructStation(5, nLadders, ladderTypes, rHole);
//
// if (gkConstructCones) {
// // upstream
// TGeoRotation* coneRot61 = new TGeoRotation;
// coneRot61->RotateZ(-90);
// coneRot61->RotateY(180);
// // TGeoCombiTrans* conePosRot61 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-0.3-gkLadderGapZ/2., coneRot61);
// TGeoCombiTrans* conePosRot61 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-0.285-gkLadderGapZ/2., coneRot61);
// station06->AddNode(coneBigVolum, 1, conePosRot61);
//
// // downstream
// TGeoRotation* coneRot62 = new TGeoRotation;
// coneRot62->RotateZ(-90);
// // TGeoCombiTrans* conePosRot62 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+0.3+gkLadderGapZ/2., coneRot62);
// TGeoCombiTrans* conePosRot62 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+0.285+gkLadderGapZ/2., coneRot62);
// station06->AddNode(coneBigVolum, 2, conePosRot62);
//
// station06->GetShape()->ComputeBBox();
// }
//
// CheckVolume(station06);
// CheckVolume(station06, infoFile);
// infoFile << "Position z = " << statPos[5] << endl;
//
//
// // --- Station 07: 16 ladders, type 14 13 17 17 16 16 16 15 15 16 16 16 17 17 13 14
// cout << endl;
// statZ = 90.;
// rHole = 4.2;
// nLadders = 16;
// ladderTypes[0] = 21; // 73; // 17;
// ladderTypes[1] = 19; // 55; // 14;
// ladderTypes[2] = 18; // 54; // 13;
// ladderTypes[3] = 20; // 72; // 16;
// ladderTypes[4] = 20; // 72; // 16;
// ladderTypes[5] = 20; // 72; // 16;
// ladderTypes[6] = 20; // 72; // 16;
// ladderTypes[7] = 7; // 71; // 15;
// ladderTypes[8] = 7; // 71; // 15;
// ladderTypes[9] = 20; // 72; // 16;
// ladderTypes[10] = 20; // 72; // 16;
// ladderTypes[11] = 20; // 72; // 16;
// ladderTypes[12] = 20; // 72; // 16;
// ladderTypes[13] = 18; // 54; // 13;
// ladderTypes[14] = 19; // 55; // 14;
// ladderTypes[15] = 21; // 73; // 17;
// TGeoVolume* station07 = ConstructStation(6, nLadders, ladderTypes, rHole);
//
// if (gkConstructCones) {
// // upstream
// TGeoRotation* coneRot71 = new TGeoRotation;
// coneRot71->RotateZ(90);
// coneRot71->RotateY(180);
// // TGeoCombiTrans* conePosRot71 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-0.3-gkLadderGapZ/2., coneRot71);
// TGeoCombiTrans* conePosRot71 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-0.285-gkLadderGapZ/2., coneRot71);
// station07->AddNode(coneBigVolum, 1, conePosRot71);
//
// // downstream
// TGeoRotation* coneRot72 = new TGeoRotation;
// coneRot72->RotateZ(90);
// // TGeoCombiTrans* conePosRot72 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+0.3+gkLadderGapZ/2., coneRot72);
// TGeoCombiTrans* conePosRot72 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+0.285+gkLadderGapZ/2., coneRot72);
// station07->AddNode(coneBigVolum, 2, conePosRot72);
//
// station07->GetShape()->ComputeBBox();
// }
//
// CheckVolume(station07);
// CheckVolume(station07, infoFile);
// infoFile << "Position z = " << statPos[6] << endl;
//
//
// // --- Station 08: 16 ladders, type 14 13 17 17 16 16 16 15 15 16 16 16 17 17 13 14
// cout << endl;
// statZ = 100.;
// rHole = 4.2;
// nLadders = 16;
// ladderTypes[0] = 19; // 55; // 14;
// ladderTypes[1] = 17; // 53; // 12;
// ladderTypes[2] = 23; // 83; // 20;
// ladderTypes[3] = 22; // 82; // 19;
// ladderTypes[4] = 22; // 82; // 19;
// ladderTypes[5] = 22; // 82; // 19;
// ladderTypes[6] = 22; // 82; // 19;
// ladderTypes[7] = 8; // 81; // 18;
// ladderTypes[8] = 8; // 81; // 18;
// ladderTypes[9] = 22; // 82; // 19;
// ladderTypes[10] = 22; // 82; // 19;
// ladderTypes[11] = 22; // 82; // 19;
// ladderTypes[12] = 22; // 82; // 19;
// ladderTypes[13] = 23; // 83; // 20;
// ladderTypes[14] = 17; // 53; // 12;
// ladderTypes[15] = 19; // 55; // 14;
// TGeoVolume* station08 = ConstructStation(7, nLadders, ladderTypes, rHole);
//
// if (gkConstructCones) {
// // upstream
// TGeoRotation* coneRot81 = new TGeoRotation;
// coneRot81->RotateZ(-90);
// coneRot81->RotateY(180);
// // TGeoCombiTrans* conePosRot81 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-0.3-gkLadderGapZ/2., coneRot81);
// TGeoCombiTrans* conePosRot81 = new TGeoCombiTrans(name+"conePosRot2", 0., 0., -coneDz-0.285-gkLadderGapZ/2., coneRot81);
// station08->AddNode(coneBigVolum, 1, conePosRot81);
//
// // downstream
// TGeoRotation* coneRot82 = new TGeoRotation;
// coneRot82->RotateZ(-90);
// // TGeoCombiTrans* conePosRot82 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+0.3+gkLadderGapZ/2., coneRot82);
// TGeoCombiTrans* conePosRot82 = new TGeoCombiTrans(name+"conePosRot1", 0., 0., coneDz+0.285+gkLadderGapZ/2., coneRot82);
// station08->AddNode(coneBigVolum, 2, conePosRot82);
//
// station08->GetShape()->ComputeBBox();
// }
//
// CheckVolume(station08);
// CheckVolume(station08, infoFile);
// infoFile << "Position z = " << statPos[7] << endl;
// --------------------------------------------------------------------------
// --------------- Create subplates ---------------------------------------
cout << endl << endl;
cout << "===> Creating subplates...." << endl << endl;
infoFile << endl << "Subplates: " << endl;
Int_t nSubplates = CreateSubplates();
for (Int_t iSubplate = 1; iSubplate <= nSubplates; iSubplate++) {
TString name = Form("Subplate%02d", iSubplate);
TGeoVolume* subplate = gGeoMan->GetVolume(name);
// add color to plates
subplate->SetTransparency(60);
if (iSubplate == 1) subplate->SetLineColor(kOrange); // kOrange);
if (iSubplate == 2) subplate->SetLineColor(kOrange); // kRed);
if (iSubplate == 3) subplate->SetLineColor(kOrange); // kGreen);
if (iSubplate == 4) subplate->SetLineColor(kOrange); // kRed);
if (iSubplate == 5) subplate->SetLineColor(kOrange); // kOrange);
if (iSubplate == 6) subplate->SetLineColor(kOrange); // kCyan);
if (iSubplate == 7) subplate->SetLineColor(kOrange); // kRed);
if (iSubplate == 8) subplate->SetLineColor(kOrange); // kGreen);
if (iSubplate == 9) subplate->SetLineColor(kOrange); // kGreen);
if (iSubplate == 10) subplate->SetLineColor(kOrange); // kGreen);
// CheckVolume(plate);
// CheckVolume(plate, infoFile);
}
// --------------------------------------------------------------------------
// --------------- Create plates ---------------------------------------
cout << endl << endl;
cout << "===> Creating plates...." << endl << endl;
infoFile << endl << "Plates: " << endl;
Int_t nPlates = CreatePlates();
for (Int_t iPlate = 1; iPlate <= nPlates; iPlate++) {
TString name = Form("Plate%02d", iPlate);
TGeoVolume* plate = gGeoMan->GetVolume(name);
// CheckVolume(plate);
// CheckVolume(plate, infoFile);
}
// --------------------------------------------------------------------------
// --------------- Create STS volume ------------------------------------
cout << endl << endl;
cout << "===> Creating STS...." << endl;
TString stsName = "sts_";
stsName += geoTag;
// --- 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
Int_t nStation = 3; // set number of stations
for (Int_t iStation = 1; iStation <= nStation; 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[2] - statPos[1]) + stsBorder;
Double_t stsPosZ = 0.5 * (statPos[2] + statPos[1]);
// stsZ = (statPos[1] - statPos[0]) + stsBorder;
// Double_t stsPosZ = 0.5 * (statPos[1] + statPos[0]);
// --- Create box around the stations
TGeoBBox* stsBox = 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[1] + 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 STS volume
// TGeoShape* stsShape = new TGeoCompositeShape("stsShape",
// "stsBox-stsCone1:trans1-stsCone2:trans2");
// TGeoVolume* sts = new TGeoVolume(stsName.Data(), stsShape, gStsMedium);
// TGeoVolume* sts = new TGeoVolume(stsName.Data(), stsBox, gStsMedium);
TGeoVolumeAssembly* sts = new TGeoVolumeAssembly(stsName.Data()); // do not produce keeping volumes
// --- Place stations in the STS
for (Int_t iStation = 1; iStation <= nStation; iStation++) {
TString statName = Form("Station%02d", iStation);
TGeoVolume* station = gGeoMan->GetVolume(statName);
Double_t posZ = statPos[iStation - 1] - stsPosZ;
TGeoTranslation* trans = new TGeoTranslation(0., 0., posZ); // standard
sts->AddNode(station, iStation, trans);
sts->GetShape()->ComputeBBox();
}
// plates
if (IncludeBox)
for (Int_t iPlate = 1; iPlate <=nPlates; iPlate++) {
TString platName = Form("Plate%02d", iPlate);
TGeoVolume* plate = gGeoMan->GetVolume(platName);
TGeoTranslation* boxdz01 = new TGeoTranslation("ty01", 0, 0, 2.50); // v23a - shift to 2x2 and 3x3 stations
sts->AddNode(plate, iPlate, boxdz01);
// sts->AddNode(plate, iPlate);
sts->GetShape()->ComputeBBox();
}
// --- Import passive elements from GDML file
if (gkImportPassive) { ImportPassive(sts, geoTag, infoFile); }
cout << endl;
CheckVolume(sts);
// --------------------------------------------------------------------------
// --------------- Finish -----------------------------------------------
TGeoTranslation* stsTrans = new TGeoTranslation(gOffX, gOffY, stsPosZ + gOffZ);
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");
sts->Export(geoFileName);
cout << endl;
cout << "Geometry " << sts->GetName() << " exported to " << geoFileName << endl;
geoFile->Close();
geoFile = new TFile(geoFileName, "UPDATE");
stsTrans->Write();
geoFile->Close();
TString geoFileName_ = "sts_";
geoFileName_ = geoFileName_ + geoTag + "_geo.root?reproducible";
geoFile = new TFile(geoFileName_, "RECREATE");
gGeoMan->Write(); // use this is you want GeoManager format in the output
geoFile->Close();
top->Draw("ogl");
gGeoManager->SetVisLevel(6);
infoFile.close();
///*
// create medialist for this geometry
TString createmedialist = gSystem->Getenv("VMCWORKDIR");
createmedialist += "/macro/geometry/create_medialist.C";
std::cout << "Loading macro " << createmedialist << std::endl;
gROOT->LoadMacro(createmedialist);
gROOT->ProcessLine("create_medialist(\"\", false)");
//*/
}
// ============================================================================
// ====== 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;
}
/** ======================================================================= **/
/** ======================================================================= **/
Int_t CreateSubplates()
{
Int_t nSubplates = 0;
Double_t xSize = 0.;
Double_t ySize = 0.;
Double_t zSize = 0.5; // cm // gkSubplateThickness;
TGeoMedium* aluminium = gGeoMan->GetMedium("aluminium");
// xsize 830 / (830 - 115+137-12) = 590
// ysize 518 / 222 / 125 = 865
// ysize 530 / 198 / 137 // corrected for 12 mm rim
// center z-axis in front cutout
// ysize 518 + 222/2. = 629
// ysize 530 + 198/2. = 629
// center z-axis in front cutout
// xsize 830/2. - (115 + 137)/2. = 415 - 126 = 289
// --- Subplate type 01: front plate (83.0 cm x 86.5 cm)
xSize = 83.0; // cm
ySize = 53.0; // cm
TGeoBBox* shape_subplate01 = new TGeoBBox("subplate01", xSize / 2., ySize / 2., zSize / 2.);
new TGeoVolume("Subplate01", shape_subplate01, aluminium);
nSubplates++;
// --- Subplate type 02: front plate (83.0 cm x 86.5 cm)
xSize = 59.0; // cm
ySize = 19.8; // cm
TGeoBBox* shape_subplate02 = new TGeoBBox("subplate02", xSize / 2., ySize / 2., zSize / 2.);
new TGeoVolume("Subplate02", shape_subplate02, aluminium);
nSubplates++;
// --- Subplate type 03: front plate (83.0 cm x 86.5 cm)
xSize = 83.0; // cm
ySize = 13.7; // cm
TGeoBBox* shape_subplate03 = new TGeoBBox("subplate03", xSize / 2., ySize / 2., zSize / 2.);
new TGeoVolume("Subplate03", shape_subplate03, aluminium);
nSubplates++;
// xsize 830 / (830 - 340 - 25) = 465
// ysize 483 / 293 / 89 = 865
// center z-axis in back cutout
// ysize 483 + 293/2. = 629.5
// center z-axis in backside cutout
// xsize 830/2. - ( 340/2. + 25 ) = 415 - 220 = 195
// --- Subplate type 04: front plate (83.0 cm x 86.5 cm)
xSize = 83.0; // cm
ySize = 48.3; // cm
TGeoBBox* shape_subplate04 = new TGeoBBox("subplate04", xSize / 2., ySize / 2., zSize / 2.);
new TGeoVolume("Subplate04", shape_subplate04, aluminium);
nSubplates++;
// --- Subplate type 05: front plate (83.0 cm x 86.5 cm)
xSize = 46.5; // cm
ySize = 29.3; // cm
TGeoBBox* shape_subplate05 = new TGeoBBox("subplate05", xSize / 2., ySize / 2., zSize / 2.);
new TGeoVolume("Subplate05", shape_subplate05, aluminium);
nSubplates++;
// --- Subplate type 06: front plate (83.0 cm x 86.5 cm)
xSize = 83.0; // cm
ySize = 8.9; // cm
TGeoBBox* shape_subplate06 = new TGeoBBox("subplate06", xSize / 2., ySize / 2., zSize / 2.);
new TGeoVolume("Subplate06", shape_subplate06, aluminium);
nSubplates++;
// bottom / top
// --- Subplate type 07: bottom/top plate (83.0 cm x 34.0 cm)
xSize = 83.0; // cm
ySize = 34.0; // cm
TGeoBBox* shape_subplate07 = new TGeoBBox("subplate07", xSize / 2., zSize / 2., ySize / 2.);
new TGeoVolume("Subplate07", shape_subplate07, aluminium);
nSubplates++;
// right
// --- Subplate type 08: right plate
xSize = 85.5; // cm
ySize = 34.0; // cm
TGeoBBox* shape_subplate08 = new TGeoBBox("subplate08", zSize / 2., xSize / 2., ySize / 2.);
new TGeoVolume("Subplate08", shape_subplate08, aluminium);
nSubplates++;
// left bottom
// --- Subplate type 09: left plate
xSize = 52.5; // cm
ySize = 34.0; // cm
TGeoBBox* shape_subplate09 = new TGeoBBox("subplate09", zSize / 2., xSize / 2., ySize / 2.);
new TGeoVolume("Subplate09", shape_subplate09, aluminium);
nSubplates++;
// left top
// --- Subplate type 10: left plate
xSize = 13.2; // cm
ySize = 34.0; // cm
TGeoBBox* shape_subplate10 = new TGeoBBox("subplate10", zSize / 2., xSize / 2., ySize / 2.);
new TGeoVolume("Subplate10", shape_subplate10, aluminium);
nSubplates++;
/*
xSize = 82.0; // cm
ySize = 50.0; // cm
TGeoBBox* shape_subplate01 = new TGeoBBox("subplate01", xSize / 2., ySize / 2., 1.5 / 2.);
new TGeoVolume("Subplate11", shape_subplate01, aluminium);
nSubplates++;
*/
return nSubplates;
}
/** ======================================================================= **/
/** ======================================================================= **/
Int_t CreatePlates()
{
Int_t nPlates = 0;
Double_t box_dx = 83.0; // cm
Double_t box_dy = 86.5; // cm
// Double_t dx = 0; // cm
// Double_t dx = -(box_dx/2 - 19.5); // cm - backside center
// Double_t dx = -(box_dx/2 - 12.6); // cm - frontside center
Double_t dx = -box_dx / 2 + 15.7; // cm - from CAD drawing
Double_t dy = box_dy / 2 - 62.9; // cm - from CAD drawing 23,6 cm
// Double_t box_dz_inner = 0; // cm
Double_t box_dz_inner = 34.0; // cm
TGeoVolume* subplate01 = gGeoMan->GetVolume("Subplate01");
TGeoVolume* subplate02 = gGeoMan->GetVolume("Subplate02");
TGeoVolume* subplate03 = gGeoMan->GetVolume("Subplate03");
TGeoBBox* box01 = (TGeoBBox*) subplate01->GetShape();
TGeoBBox* box02 = (TGeoBBox*) subplate02->GetShape();
TGeoBBox* box03 = (TGeoBBox*) subplate03->GetShape();
TGeoVolume* subplate04 = gGeoMan->GetVolume("Subplate04");
TGeoVolume* subplate05 = gGeoMan->GetVolume("Subplate05");
TGeoVolume* subplate06 = gGeoMan->GetVolume("Subplate06");
TGeoBBox* box04 = (TGeoBBox*) subplate04->GetShape();
TGeoBBox* box05 = (TGeoBBox*) subplate05->GetShape();
TGeoBBox* box06 = (TGeoBBox*) subplate06->GetShape();
TGeoVolume* subplate07 = gGeoMan->GetVolume("Subplate07");
TGeoBBox* box07 = (TGeoBBox*) subplate07->GetShape();
TGeoVolume* subplate08 = gGeoMan->GetVolume("Subplate08");
TGeoBBox* box08 = (TGeoBBox*) subplate08->GetShape();
TGeoVolume* subplate09 = gGeoMan->GetVolume("Subplate09");
TGeoBBox* box09 = (TGeoBBox*) subplate09->GetShape();
TGeoVolume* subplate10 = gGeoMan->GetVolume("Subplate10");
TGeoBBox* box10 = (TGeoBBox*) subplate10->GetShape();
// --- Plate type 1: front plate made of 3 subplates
TGeoVolumeAssembly* plate01 = new TGeoVolumeAssembly("Plate01");
Double_t sy01 = -box_dy / 2. + box01->GetDY();
Double_t sz01 = -(box01->GetDZ() + box_dz_inner / 2.);
TGeoTranslation* ty01 = new TGeoTranslation("ty01", dx, sy01 + dy, sz01);
plate01->AddNode(subplate01, 1, ty01);
Double_t sx02 = -box_dx / 2. + box02->GetDX();
Double_t sy02 = -box_dy / 2. + box01->GetDY() * 2 + box02->GetDY();
TGeoTranslation* ty02 = new TGeoTranslation("ty02", sx02 + dx, sy02 + dy, sz01);
plate01->AddNode(subplate02, 2, ty02);
Double_t sy03 = -box_dy / 2. + box01->GetDY() * 2 + box02->GetDY() * 2 + box03->GetDY();
TGeoTranslation* ty03 = new TGeoTranslation("ty03", dx, sy03 + dy, sz01);
plate01->AddNode(subplate03, 3, ty03);
plate01->GetShape()->ComputeBBox();
nPlates++;
// --- Plate type 2: back plate made of 3 subplates
TGeoVolumeAssembly* plate02 = new TGeoVolumeAssembly("Plate02");
Double_t sy04 = -box_dy / 2. + box04->GetDY();
Double_t sz04 = box04->GetDZ() + box_dz_inner / 2.;
TGeoTranslation* ty04 = new TGeoTranslation("ty04", dx, sy04 + dy, sz04);
plate02->AddNode(subplate04, 1, ty04);
Double_t sx05 = -box_dx / 2. + box05->GetDX();
Double_t sy05 = -box_dy / 2. + box04->GetDY() * 2 + box05->GetDY();
TGeoTranslation* ty05 = new TGeoTranslation("ty05", sx05 + dx, sy05 + dy, sz04);
plate02->AddNode(subplate05, 2, ty05);
Double_t sy06 = -box_dy / 2. + box04->GetDY() * 2 + box05->GetDY() * 2 + box06->GetDY();
TGeoTranslation* ty06 = new TGeoTranslation("ty06", dx, sy06 + dy, sz04);
plate02->AddNode(subplate06, 3, ty06);
plate02->GetShape()->ComputeBBox();
nPlates++;
// --- Plate type 3: bottom plate
TGeoVolumeAssembly* plate03 = new TGeoVolumeAssembly("Plate03");
Double_t sy07 = box_dy / 2. - box07->GetDY();
TGeoTranslation* ty07 = new TGeoTranslation("ty07", dx, -sy07 + dy, 0.);
plate03->AddNode(subplate07, 1, ty07);
plate03->GetShape()->ComputeBBox();
nPlates++;
// --- Plate type 4: top plate
TGeoVolumeAssembly* plate04 = new TGeoVolumeAssembly("Plate04");
TGeoTranslation* ty17 = new TGeoTranslation("ty17", dx, sy07 + dy, 0.);
plate04->AddNode(subplate07, 1, ty17);
plate04->GetShape()->ComputeBBox();
nPlates++;
// --- Plate type 5: -x plate
TGeoVolumeAssembly* plate05 = new TGeoVolumeAssembly("Plate05");
Double_t sx08 = box_dx / 2. - box08->GetDX();
TGeoTranslation* ty08 = new TGeoTranslation("ty08", -sx08 + dx, dy, 0.);
plate05->AddNode(subplate08, 1, ty08);
plate05->GetShape()->ComputeBBox();
nPlates++;
// --- Plate type 6: +x plate (shorted due to beampipe)
TGeoVolumeAssembly* plate06 = new TGeoVolumeAssembly("Plate06");
Double_t sy09 = -box_dy / 2. + box09->GetDY() + 2 * box09->GetDX();
TGeoTranslation* ty09 = new TGeoTranslation("ty09", sx08 + dx, sy09 + dy, 0.);
plate06->AddNode(subplate09, 1, ty09);
plate06->GetShape()->ComputeBBox();
nPlates++;
// --- Plate type 7: +x plate (shorted due to beampipe)
TGeoVolumeAssembly* plate07 = new TGeoVolumeAssembly("Plate07");
Double_t sy10 = -box_dy / 2. + box10->GetDY() + 2 * box10->GetDX();
TGeoTranslation* ty10 = new TGeoTranslation("ty10", sx08 + dx, -sy10 + dy, 0.);
plate07->AddNode(subplate10, 1, ty10);
plate07->GetShape()->ComputeBBox();
nPlates++;
return nPlates;
}
/** ======================================================================= **/
/** ===========================================================================
** 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;
TGeoVolume* s0vol = NULL;
TGeoVolume* halfLadderU = NULL;
TGeoVolume* halfLadderD = NULL;
Double_t shiftZ = 0.;
Double_t ladderY = 0.;
Double_t gapY = 0.;
// --- Ladder 01 x-mirror of 02: 10 sectors, type 4 4 3 2 1 1 2 3 4 4
nSectors = 5;
sectorTypes[0] = 1;
sectorTypes[1] = 2;
sectorTypes[2] = 3;
sectorTypes[3] = 4;
sectorTypes[4] = 4;
s0name = Form("Sector%02d", sectorTypes[0]);
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
shiftZ = 2. * shape->GetDZ() + gkSectorGapZ;
halfLadderU = ConstructHalfLadder(1, "HalfLadder01u", nSectors, sectorTypes, 'r'); // mirrored
halfLadderD = ConstructHalfLadder(1, "HalfLadder01d", nSectors, sectorTypes, 'l'); // mirrored
ConstructLadder(1, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 02: 10 sectors, type 4 4 3 2 1 1 2 3 4 4
nSectors = 5;
sectorTypes[0] = 1;
sectorTypes[1] = 2;
sectorTypes[2] = 3;
sectorTypes[3] = 4;
sectorTypes[4] = 4;
s0name = Form("Sector%02d", sectorTypes[0]);
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
shiftZ = 2. * shape->GetDZ() + gkSectorGapZ;
halfLadderU = ConstructHalfLadder(2, "HalfLadder02u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(2, "HalfLadder02d", nSectors, sectorTypes, 'r');
ConstructLadder(2, halfLadderU, halfLadderD, shiftZ);
nLadders++;
//=====================================================================================
// --- Ladder 13: 1 sector, type 3
nSectors = 1;
sectorTypes[0] = 3;
s0name = Form("Sector%02d", sectorTypes[0]);
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
shiftZ = 2. * shape->GetDZ() + gkSectorGapZ;
//
// top half ladder only (FEBs in the top)
//
halfLadderU = ConstructHalfLadder(13, "HalfLadder13u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(13, "HalfLadder13d", 0, sectorTypes, 'r');
// halfLadderD = ConstructHalfLadder(13, "HalfLadder13d", nSectors, sectorTypes, 'r');
ConstructLadder(13, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 09: 2 sectors, type 3 3 - mSTS
nSectors = 2;
sectorTypes[0] = 3;
sectorTypes[1] = 3;
s0name = Form("Sector%02d", sectorTypes[0]);
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
shiftZ = 2. * shape->GetDZ() + gkSectorGapZ;
//
// bottom half ladder only
//
// halfLadderU = ConstructHalfLadder(9, "HalfLadder09u", nSectors, sectorTypes, 'l');
halfLadderU = ConstructHalfLadder(9, "HalfLadder09u", 0, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(9, "HalfLadder09d", nSectors, sectorTypes, 'r');
//
ConstructLadder(9, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 10: 2 sectors, type 3 4 - mSTS
nSectors = 2;
sectorTypes[0] = 3;
sectorTypes[1] = 4;
s0name = Form("Sector%02d", sectorTypes[0]);
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
shiftZ = 2. * shape->GetDZ() + gkSectorGapZ;
//
// bottom half ladder only
//
// halfLadderU = ConstructHalfLadder(10, "HalfLadder10u", nSectors, sectorTypes, 'l');
halfLadderU = ConstructHalfLadder(10, "HalfLadder10u", 0, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(10, "HalfLadder10d", nSectors, sectorTypes, 'r');
//
ConstructLadder(10, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 11: 3 sectors, type 3 3 3 - mSTS
nSectors = 3;
sectorTypes[0] = 3;
sectorTypes[1] = 3;
sectorTypes[2] = 3;
s0name = Form("Sector%02d", sectorTypes[0]);
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
shiftZ = 2. * shape->GetDZ() + gkSectorGapZ;
//
// bottom half ladder only
//
// halfLadderU = ConstructHalfLadder(11, "HalfLadder11u", nSectors, sectorTypes, 'l');
halfLadderU = ConstructHalfLadder(11, "HalfLadder11u", 0, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(11, "HalfLadder11d", nSectors, sectorTypes, 'r');
//
ConstructLadder(11, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 12: 2 sectors, type 3 4 - mSTS - y-overlap different from 10
nSectors = 2;
sectorTypes[0] = 3;
sectorTypes[1] = 4;
s0name = Form("Sector%02d", sectorTypes[0]);
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
shiftZ = 2. * shape->GetDZ() + gkSectorGapZ;
//
// bottom half ladder only
//
// halfLadderU = ConstructHalfLadder(12, "HalfLadder12u", nSectors, sectorTypes, 'l');
halfLadderU = ConstructHalfLadder(12, "HalfLadder12u", 0, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(12, "HalfLadder12d", nSectors, sectorTypes, 'r');
//
ConstructLadder(12, halfLadderU, halfLadderD, shiftZ);
nLadders++;
//=====================================================================================
// --- Ladder 03 x-mirror of 04: 10 sectors, type 5 4 3 3 6 6 3 3 4 5
nSectors = 5;
sectorTypes[0] = 6;
sectorTypes[1] = 3;
sectorTypes[2] = 3;
sectorTypes[3] = 4;
sectorTypes[4] = 5;
s0name = Form("Sector%02d", sectorTypes[0]);
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
shiftZ = 2. * shape->GetDZ() + gkSectorGapZ;
halfLadderU = ConstructHalfLadder(3, "HalfLadder03u", nSectors, sectorTypes, 'r'); // mirrored
halfLadderD = ConstructHalfLadder(3, "HalfLadder03d", nSectors, sectorTypes, 'l'); // mirrored
ConstructLadder(3, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 04: 10 sectors, type 5 4 3 3 6 6 3 3 4 5
nSectors = 5;
sectorTypes[0] = 6;
sectorTypes[1] = 3;
sectorTypes[2] = 3;
sectorTypes[3] = 4;
sectorTypes[4] = 5;
s0name = Form("Sector%02d", sectorTypes[0]);
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
shiftZ = 2. * shape->GetDZ() + gkSectorGapZ;
halfLadderU = ConstructHalfLadder(4, "HalfLadder04u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(4, "HalfLadder04d", nSectors, sectorTypes, 'r');
ConstructLadder(4, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 14: 6 sensors, type 5 4 3 3 4 5
nSectors = 3;
sectorTypes[0] = 3;
sectorTypes[1] = 4;
sectorTypes[2] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(14, "HalfLadder14u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(14, "HalfLadder14d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(14, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 15: 4 sectors, type 4 4 4 4
nSectors = 2;
sectorTypes[0] = 4;
sectorTypes[1] = 4;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(15, "HalfLadder15u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(15, "HalfLadder15d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(15, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 05 x-mirror of 06: 10 sectors, type 5 5 4 3 7 7 3 4 5 5
nSectors = 5;
sectorTypes[0] = 7;
sectorTypes[1] = 3;
sectorTypes[2] = 4;
sectorTypes[3] = 5;
sectorTypes[4] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(5, "HalfLadder05u", nSectors, sectorTypes, 'r'); // mirrored
halfLadderD = ConstructHalfLadder(5, "HalfLadder05d", nSectors, sectorTypes, 'l'); // mirrored
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(5, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 06: 10 sectors, type 5 5 4 3 7 7 3 4 5 5
nSectors = 5;
sectorTypes[0] = 7;
sectorTypes[1] = 3;
sectorTypes[2] = 4;
sectorTypes[3] = 5;
sectorTypes[4] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(6, "HalfLadder06u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(6, "HalfLadder06d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(6, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 16: 10 sectors, type 5 5 4 3 3 3 3 4 5 5
nSectors = 5;
sectorTypes[0] = 3;
sectorTypes[1] = 3;
sectorTypes[2] = 4;
sectorTypes[3] = 5;
sectorTypes[4] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(16, "HalfLadder16u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(16, "HalfLadder16d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(16, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 17: 8 sectors, type 5 5 4 3 3 4 5 5
nSectors = 4;
sectorTypes[0] = 3;
sectorTypes[1] = 4;
sectorTypes[2] = 5;
sectorTypes[3] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(17, "HalfLadder17u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(17, "HalfLadder17d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(17, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 18: 6 sectors, type 5 5 4 4 5 5
nSectors = 3;
sectorTypes[0] = 4;
sectorTypes[1] = 5;
sectorTypes[2] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(18, "HalfLadder18u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(18, "HalfLadder18d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(18, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 19: 4 sectors, type 5 5 5 5
nSectors = 2;
sectorTypes[0] = 5;
sectorTypes[1] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(19, "HalfLadder19u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(19, "HalfLadder19d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(19, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 07: 10 sectors, type 5 5 4 3 3 gap 3 3 4 5 5, with gap
nSectors = 5;
sectorTypes[0] = 3;
sectorTypes[1] = 3;
sectorTypes[2] = 4;
sectorTypes[3] = 5;
sectorTypes[4] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(7, "HalfLadder07u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(7, "HalfLadder07d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
gapY = 4.4;
ConstructLadderWithGap(7, halfLadderU, halfLadderD, 2 * gapY);
nLadders++;
// --- Ladder 20: 10 sectors, type 5 5 5 3 2 2 3 5 5 5
nSectors = 5;
sectorTypes[0] = 2;
sectorTypes[1] = 3;
sectorTypes[2] = 5;
sectorTypes[3] = 5;
sectorTypes[4] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(20, "HalfLadder20u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(20, "HalfLadder20d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(20, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 21: 2 sectors, type 5 5
nSectors = 1;
sectorTypes[0] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(21, "HalfLadder21u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(21, "HalfLadder21d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(21, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 08: 8 sectors, type 5 5 5 4 gap 4 5 5 5, with gap
nSectors = 4;
sectorTypes[0] = 4;
sectorTypes[1] = 5;
sectorTypes[2] = 5;
sectorTypes[3] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(8, "HalfLadder08u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(8, "HalfLadder08d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
gapY = 4.57;
ConstructLadderWithGap(8, halfLadderU, halfLadderD, 2 * gapY);
nLadders++;
// --- Ladder 22: 10 sectors, type 5 5 5 4 3 3 4 5 5 5
nSectors = 5;
sectorTypes[0] = 3;
sectorTypes[1] = 4;
sectorTypes[2] = 5;
sectorTypes[3] = 5;
sectorTypes[4] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(22, "HalfLadder22u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(22, "HalfLadder22d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(22, halfLadderU, halfLadderD, shiftZ);
nLadders++;
// --- Ladder 23: 10 sectors, type 5 5 4 4 3 3 4 4 5 5
nSectors = 5;
sectorTypes[0] = 3;
sectorTypes[1] = 4;
sectorTypes[2] = 4;
sectorTypes[3] = 5;
sectorTypes[4] = 5;
s0vol = gGeoMan->GetVolume(s0name);
shape = (TGeoBBox*) s0vol->GetShape();
ladderY = 2. * shape->GetDY();
halfLadderU = ConstructHalfLadder(23, "HalfLadder23u", nSectors, sectorTypes, 'l');
halfLadderD = ConstructHalfLadder(23, "HalfLadder23d", nSectors, sectorTypes, 'r');
shape = (TGeoBBox*) halfLadderU->GetShape();
ConstructLadder(23, halfLadderU, halfLadderD, shiftZ);
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
**/
TGeoVolume* ConstructHalfLadder(Int_t ladderid, const TString& name, Int_t nSectors, Int_t* sectorTypes, char align)
{
// --- 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", (char*) 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
if (ladderid != 10)
ladderY -= Double_t(nSectors - 1) * gkSectorOverlapY;
else
ladderY -= Double_t(nSectors - 1) * gkSectorOverlapYL10;
// --- Add gaps in z direction
ladderZ += Double_t(nSectors - 1) * gkSectorGapZ;
// --- Create and place modules
Bool_t L12firstpass = true; // false, if ladder was shifted already once
Double_t yPosSect = 0.0;
if(ladderid == 13) {yPosSect = -0.5 * ladderY - 14 ;}
else {
yPosSect = -0.5 * ladderY - 16 ;
}
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
if (L12firstpass == true)
if (ladderid == 12)
{
L12firstpass = false; // false, if ladder was shifted already once
yPosSect += (gkSectorOverlapYL10 - gkSectorOverlapY) / 2.; // shift ladder type 12 downwards by 2.2 mm
// cout << "DE20230209 " << (gkSectorOverlapYL10 - gkSectorOverlapY) / 2. << endl;
}
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);
// // DEDE
// // drop 2nd module on this halfladder for mSTS Nov 2019
// // halfLadder->AddNode(module, iSector+1, trans);
// if (ladderid == 9) cout << "DE333 " << iSector << endl;
// if (ladderid == 9)
// if (iSector == 0)
// halfLadder->AddNode(module, iSector+1, trans);
halfLadder->AddNode(module, iSector + 1, trans);
halfLadder->GetShape()->ComputeBBox();
if (ladderid != 10)
yPosSect += 0.5 * sectorY - gkSectorOverlapY;
else
yPosSect += 0.5 * sectorY - gkSectorOverlapYL10;
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("Ladder%02d", LadderIndex);
Int_t i;
Double_t j;
Int_t YnumOfFrameBoxes = (Int_t)(ladderY / gkFrameStep) + 1; // calculate number of elements
if (LadderIndex == 1 || LadderIndex == 2) // set even number of ladder elements for these ladders in station 1 and 2
YnumOfFrameBoxes--;
// if (LadderIndex == 3 || LadderIndex == 4) // set even number of ladder elements for these ladders in station 3 and 4
// YnumOfFrameBoxes++;
YnumOfFrameBoxes += YnumOfFrameBoxes % 2; // use even number of frame elements for all ladders
// cout << "DE: lad " << LadderIndex << " inum " << YnumOfFrameBoxes << endl;
// DEDE
TGeoBBox* fullFrameShp = new TGeoBBox(name + "_FullFrameBox_shp", xu / 2., gkFrameStep / 2.,
(xu / 2. + sqrt(2.) * gkFrameThickness / 2.) / 2.);
// TGeoBBox* fullFrameShp = new TGeoBBox (name+"_FullFrameBox_shp", xu/2., gkFrameStep/2., (gkSectorGapZFrame+xu/2.+sqrt(2.)*gkFrameThickness/2.)/2.);
TGeoVolume* fullFrameBoxVol = new TGeoVolume(name + "_FullFrameBox", fullFrameShp, gStsMedium);
// cout << "DE: frame Z size " << (xu/2.+sqrt(2.)*gkFrameThickness/2.) << " cm" << endl;
ConstructFrameElement("FrameBox", 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);
// cout << "DE: i " << i << " j " << j << endl;
if (LadderIndex <= 2) // central ladders in stations 1 to 8
{
if ((j >= -1) && (j <= 1)) // keep the inner 4 elements free for the cone
continue;
}
else if (LadderIndex <= 8) // central ladders in stations 1 to 8
{
if ((j >= -2) && (j <= 2)) // keep the inner 4 elements free for the cone
continue;
}
// DEDE
ladder->AddNode(fullFrameBoxVol, i,
new TGeoCombiTrans(name + "_FullFrameBox_posrot", 0., j * gkFrameStep,
-ladderZ / 2. - (xu / 2. + sqrt(2.) * gkFrameThickness / 2.) / 2.,
fullFrameRot));
// ladder->AddNode(fullFrameBoxVol, i, new TGeoCombiTrans(name+"_FullFrameBox_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
**
** 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 overlap and displaced in z bz shiftZ.
**
** Arguments:
** name volume name
** halfLadderU pointer to upper half ladder
** halfLadderD pointer to lower half ladder
** shiftZ relative displacement along the z axis
**/
TGeoVolume* ConstructLadder(Int_t LadderIndex, TGeoVolume* halfLadderU, TGeoVolume* halfLadderD, 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("Ladder%02d", LadderIndex);
TGeoVolumeAssembly* ladder = new TGeoVolumeAssembly(name);
Double_t ladderX = TMath::Max(xu, xd);
// Double_t ladderY = yu + yd - gkSectorOverlapY;
Double_t ladderY = TMath::Max(yu, yd);
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
// cout << "DEEEE: li " << LadderIndex
// << " || xu " << xu << " yu " << yu << " zu " << zu
// << " || xd " << xd << " yd " << yd << " zd " << zd
// << " || ypu " << yPosU << " ypd " << yPosD
// << endl;
if (yu == 0) // if no top (= only bottom) half ladder
{
yPosD = 0.5 * (ladderY - yd); // top aligned
zPosD = 0.5 * (ladderZ - zd); // 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 && LadderIndex == 13){
// AddCarbonLadder(LadderIndex, ladder, xu, ladderY, ladderZ); // take width of top HL
AddCarbonLadder(LadderIndex, ladder, ladderX, ladderY + 14, ladderZ); // take width of any HL
}
else if (gkConstructFrames){
AddCarbonLadder(LadderIndex, ladder, ladderX, ladderY + 22, ladderZ); // take width of any HL
}
// --------------------------------------------------------------------------
return ladder;
}
/** ======================================================================= **/
/** ===========================================================================
** 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
**/
TGeoVolume* ConstructLadderWithGap(Int_t LadderIndex, TGeoVolume* halfLadderU, TGeoVolume* halfLadderD, Double_t gapY)
{
// --- Some variables
TGeoBBox* shape = NULL;
Int_t i;
Double_t j;
// --- 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("Ladder%02d", 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);
// --- 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 station
**
** The station 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
** rHole radius of inner hole
**/
// TGeoVolume* ConstructStation(const char* name,
// Int_t iStation,
TGeoVolume* ConstructStation(Int_t iStation, Int_t nLadders, Int_t* ladderTypes, Double_t rHole)
{
TString name;
name = Form("Station%02d", iStation + 1); // 1,2,3,4,5,6,7,8
// name = Form("Station%02d", iStation); // 0,1,2,3,4,5,6,7 - Station00 missing in output
// --- Some local variables
TGeoShape* statShape = NULL;
TGeoBBox* ladderShape = NULL;
TGeoBBox* shape = NULL;
TGeoVolume* ladder = NULL;
TString ladderName;
// --- Determine size of station from ladders
Double_t statX = 0.;
Double_t statY = 0.;
Double_t statZeven = 0.;
Double_t statZodd = 0.;
Double_t statZ = 0.;
for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) {
Int_t ladderType = ladderTypes[iLadder];
ladderName = Form("Ladder%02d", ladderType);
ladder = gGeoManager->GetVolume(ladderName);
if (!ladder) Fatal("ConstructStation", Form("Volume %s not found", ladderName.Data()));
shape = (TGeoBBox*) ladder->GetShape();
statX += 2. * shape->GetDX();
statY = TMath::Max(statY, 2. * shape->GetDY());
if (iLadder % 2) statZeven = TMath::Max(statZeven, 2. * shape->GetDZ());
else
statZodd = TMath::Max(statZodd, 2. * shape->GetDZ());
}
statX -= Double_t(nLadders - 1) * gkLadderOverlapX;
statZ = statZeven + gkLadderGapZ + statZodd;
// --- Create station volume
TString boxName(name);
boxName += "_box";
cout << "before statZ/2.: " << statZ / 2. << endl;
statZ = 2 * 4.5; // changed Z size of the station for cone and gkLadderGapZ
cout << "fixed to statZ/2.: " << statZ / 2. << endl;
TGeoBBox* statBox = new TGeoBBox(boxName, statX / 2., statY / 2., statZ / 2.);
// TString tubName(name);
// tubName += "_tub";
// TString expression = boxName + "-" + tubName;
// // TGeoTube* statTub = new TGeoTube(tubName, 0., rHole, statZ/2.);
// // TGeoBBox* statTub = new TGeoBBox(tubName, rHole, rHole, statZ/2.);
// TGeoBBox* statTub = new TGeoBBox(tubName, rHole, rHole, statZ/2.+.1); // .1 opens the hole in z direction
//
// statShape = new TGeoCompositeShape(name, expression.Data());
// TGeoVolume* station = new TGeoVolume(name, statShape, gStsMedium);
// TGeoVolume* station = new TGeoVolume(name, statBox, gStsMedium);
TGeoVolumeAssembly* station = new TGeoVolumeAssembly(name); // do not produce keeping volumes
Double_t subtractedVal;
// --- Place ladders in station
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++) {
Int_t ladderType = ladderTypes[iLadder];
ladderName = Form("Ladder%02d", ladderType);
ladder = gGeoManager->GetVolume(ladderName);
shape = (TGeoBBox*) ladder->GetShape();
if (maxdz < shape->GetDZ()) maxdz = shape->GetDZ();
}
for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) {
Int_t ladderType = ladderTypes[iLadder];
ladderName = Form("Ladder%02d", ladderType);
ladder = gGeoManager->GetVolume(ladderName);
shape = (TGeoBBox*) ladder->GetShape();
xPos += shape->GetDX();
cout << "xPos2: " << xPos << endl;
yPos = 0.; // vertically centred
TGeoRotation* rot = new TGeoRotation();
if (gkConstructFrames)
// DEDE
subtractedVal = sqrt(2.) * gkFrameThickness / 2. + shape->GetDX();
// subtractedVal = 2*gkSectorGapZFrame + sqrt(2.)*gkFrameThickness/2. + shape->GetDX();
else
subtractedVal = 0.;
// zPos = 0.5 * gkLadderGapZ + (shape->GetDZ()-subtractedVal/2.); // non z-aligned ladders
zPos = 0.5 * gkLadderGapZ + (2 * maxdz - shape->GetDZ() - subtractedVal / 2.); // z-aligned ladders
cout << "DE ladder" << ladderTypes[iLadder] << " dx: " << shape->GetDX() << " dy: " << shape->GetDY()
<< " dz: " << shape->GetDZ() << " max dz: " << maxdz << endl;
cout << "DE ladder" << ladderTypes[iLadder] << " fra: " << gkFrameThickness / 2. << " sub: " << subtractedVal
<< " zpo: " << zPos << endl
<< endl;
// mCBM
if ((iStation % 2 == 0) && (iStation >= 1)) // flip ladders to reproduce CAD layout
// if (iStation % 2 == 0) // flip ladders for even stations to reproduce CAD layout
// even station 0,2,4,6
// if (iStation % 2 == 1) // flip ladders for odd stations to reproduce CAD layout
// odd station 1,3,5,7
{
// --- Unrotated ladders --- downstream
if ((nLadders / 2 + iLadder) % 2) {
// zPos = 0.5 * gkLadderGapZ + (shape->GetDZ()-subtractedVal/2.);
rot->RotateY(180.);
}
// --- Rotated ladders --- upstream
else {
// zPos = -0.5 * gkLadderGapZ - (shape->GetDZ()-subtractedVal/2.);
zPos = -zPos;
}
}
else
// odd station 1,3,5,7
{
// --- Unrotated ladders --- upstream
if ((nLadders / 2 + iLadder) % 2) {
// zPos = -0.5 * gkLadderGapZ - (shape->GetDZ()-subtractedVal/2.);
zPos = -zPos;
}
// --- Rotated ladders --- downstream
else {
// zPos = 0.5 * gkLadderGapZ + (shape->GetDZ()-subtractedVal/2.);
rot->RotateY(180.);
// zPos += 14.; // move STS ladder from position of C-frame #1 to C-frame #3 - March 2019 version
}
}
TGeoCombiTrans* trans = new TGeoCombiTrans(xPos, yPos, zPos, rot);
// enable or disable units
// Unit -1
if ((ladderType == 13) && (iLadder + 1 == 1)) {
cout << "including " << ladderName << " " << ladderType << " " << iLadder + 1 << endl;
station->AddNode(ladder, iLadder + 1, new TGeoCombiTrans(xPos, yPos + 14, zPos, rot));
}
// Unit 0
if ((ladderType == 9) && (iLadder + 1 == 1)) {
cout << "including " << ladderName << " " << ladderType << " " << iLadder + 1 << endl;
station->AddNode(ladder, iLadder + 1, new TGeoCombiTrans(xPos, yPos - 16, zPos, rot));
}
// Unit 1
if ((ladderType == 9) && (iLadder + 1 == 2)) {
cout << "including " << ladderName << " " << ladderType << " " << iLadder + 1 << endl;
station->AddNode(ladder, iLadder + 1, new TGeoCombiTrans(xPos, yPos - 16, zPos, rot));
}
// Unit 2
if ((ladderType == 12) && (iLadder + 1 == 2)) {
cout << "including " << ladderName << " " << ladderType << " " << iLadder + 1 << endl;
station->AddNode(ladder, iLadder + 1, new TGeoCombiTrans(xPos, yPos - 16, zPos, rot));
}
// Unit 3 right (far from beam)
if ((ladderType == 10) && (iLadder + 1 == 1)) {
cout << "including " << ladderName << " " << ladderType << " " << iLadder + 1 << endl;
station->AddNode(ladder, iLadder + 1, new TGeoCombiTrans(xPos, yPos - 16, zPos, rot));
}
// Unit 3 left (close to beam)
if ((ladderType == 11) && (iLadder + 1 == 3)) {
cout << "including " << ladderName << " " << ladderType << " " << iLadder + 1 << endl;
station->AddNode(ladder, iLadder + 1, new TGeoCombiTrans(xPos, yPos - 16, zPos, rot));
}
// include all ladders
// station->AddNode(ladder, iLadder+1, trans);
// // drop upstream ladder for mSTS Nov 2019
// // station->AddNode(ladder, iLadder+1, trans);
// cout << "DE222 " << iLadder << endl;
// if (iLadder == 1) station->AddNode(ladder, iLadder+1, trans);
station->GetShape()->ComputeBBox();
xPos += shape->GetDX() - gkLadderOverlapX;
cout << "xPos3: " << xPos << endl;
}
return station;
}
/** ======================================================================= **/
/** ===========================================================================
** 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)
{
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()) {
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");
Double_t t = gkFrameThickness / 2.;
//cout << "I am HERE FOR T: " << t << endl;
// --- 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.));
TGeoBBox* frameVertPillarShp;
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 - 0.50456, vertRot)); // change done due to bug since 2019
//cout << "I am Here:::::::: ------------------- " << (x - sqrt(2.) * t) / 2 << endl;
// --- Small horizontal pillar
TGeoBBox* frameHorPillarShp =
new TGeoBBox(name + "_horpillar_shape", x - 2. * t + 0.56, gkThinFrameThickness / 2. + 0.015, gkThinFrameThickness / 2. + 0.015);
TGeoVolume* frameHorPillarVol = new TGeoVolume(name + "_horpillar", frameHorPillarShp, framesMaterial);
frameHorPillarVol->SetLineColor(kCyan);
//cout<< "Thickness of Wickung: ----- :" << gkThinFrameThickness / 2. + 0.015 << endl;
// Define the rotation for the first instance
TGeoRotation* horRot1 = new TGeoRotation(name + "_horpillar_rot1", 0., 0., 33.5); // 31.452 degrees rotation
// Define the combined transformation (translation + rotation) for the first instance
TGeoCombiTrans* horTrRot1 = new TGeoCombiTrans(name + "_horpillar_posrot1",
0., (gkFrameStep / 2. + gkThinFrameThickness / 2.) - 2.025,
-(x + sqrt(2.) * t - 2. * t) / 2. -0.12/2 ,
horRot1);
frameBoxVol->AddNode(frameHorPillarVol, 1, horTrRot1);
// Define the rotation for the second instance
TGeoRotation* horRot2 = new TGeoRotation(name + "_horpillar_rot2", 0., 0., -33.5); // -30 degrees rotation
// Define the combined transformation (translation + rotation) for the second instance
TGeoCombiTrans* horTrRot2 = new TGeoCombiTrans(name + "_horpillar_posrot2",
0., (gkFrameStep / 2. + gkThinFrameThickness / 2.) - 2.025 ,
-(x + sqrt(2.) * t - 2. * t) / 2. + 0.040/2,
horRot2);
frameBoxVol->AddNode(frameHorPillarVol, 2, horTrRot2);
//frameBoxVol->AddNode(frameHorPillarVol, 3,
// new TGeoTranslation(name + "_horpillar_pos_1", 0., -gkFrameStep / 2. + gkThinFrameThickness / 2. - 0.05/2,
// -(x + sqrt(2.) * t - 2. * t) / 2.));
if (gkConstructSmallFrames) {
// --- Small sloping pillar
TGeoPara* frameSlopePillarShp =
new TGeoPara(name + "_slopepillar_shape", (x - 2. * t) / TMath::Cos(31.4 / 180. * TMath::Pi()) ,
gkThinFrameThickness / 2. + 0.015, gkThinFrameThickness / 2. + 0.015, 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);
TGeoCombiTrans* slopeTrRot =
new TGeoCombiTrans(name + "_slopepillar_posrot_1", 0., 0., -(x + sqrt(2.) * t - 2. * t) / 2., slopeRot);
//frameBoxVol->AddNode(frameSlopePillarVol, 1, slopeTrRot);
Double_t angl = 23.;
Double_t reduction = 0.10; // Reduction value
Double_t newLength = (sqrt(2) * (x / 2. - t) - t - reduction / 2.) / TMath::Cos(angl / 180. * TMath::Pi());
// --- Small sub pillar
TGeoPara* frameSubPillarShp =
new TGeoPara(name + "_subpillar_shape", newLength,
gkThinFrameThickness / 2. + 0.015, gkThinFrameThickness / 2. + 0.015, angl, 0., 90.);
TGeoVolume* frameSubPillarVol = new TGeoVolume(name + "_subpillar", frameSubPillarShp, framesMaterial);
frameSubPillarVol->SetLineColor(kMagenta);
Double_t posZ = t * (1. - 3. / (2. * sqrt(2.))) - 0.50 /2 ;
Double_t xOffset = x / 2. - t + t / (2. * sqrt(2.));
Double_t yOffset = 1.0;
// one side of X direction
TGeoRotation* subRot1 = new TGeoRotation(name + "_subpillar_rot_1", 90., 40., -62.9);
TGeoCombiTrans* subTrRot1 =
new TGeoCombiTrans(name + "_subpillar_posrot_1", -(-x / 2. + t - t / (2. * sqrt(2.)) - 0.08/2), yOffset, posZ, subRot1);
//cout << "X OFFSET:: " << xOffset << endl;
TGeoRotation* subRot2 = new TGeoRotation(name + "_subpillar_rot_2", 90., -90. - 50., -62.9);
TGeoCombiTrans* subTrRot2 =
new TGeoCombiTrans(name + "_subpillar_posrot_2", -(-x / 2. + t - t / (2. * sqrt(2.)) - 0.08/2 ), -yOffset, posZ, subRot2);
// other side of X direction
TGeoRotation* subRot3 = new TGeoRotation(name + "_subpillar_rot_3", 90., 90. + 50., -62.9 );
TGeoCombiTrans* subTrRot3 =
new TGeoCombiTrans(name + "_subpillar_posrot_3", (-x / 2. + t - t / (2. * sqrt(2.) ) - 0.08/2 ), yOffset, posZ, subRot3);
TGeoRotation* subRot4 = new TGeoRotation(name + "_subpillar_rot_4", 90., -40., -62.9);
TGeoCombiTrans* subTrRot4 =
new TGeoCombiTrans(name + "_subpillar_posrot_4", (-x / 2. + t - t / (2. * sqrt(2.) ) - 0.08/2 ), -yOffset, 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;
}
/** ======================================================================= **/
void ImportPassive(TGeoVolume* stsVolume, TString geoTag, fstream& infoFile)
{
TString passiveName = TString("msts_passive_") + geoTag;
TString basePath = gSystem->Getenv("VMCWORKDIR");
TString relPath = "/geometry/sts/passive/msts/" + passiveName + ".gdml";
//TString relPath = "/home/siid/Fresh_CBM_ROOT/cbmroot_git_latest/geometry/sts/passive/msts/sts_passive_msts_v24d.gdml";
TString passiveFileName = basePath + relPath;
//TString passiveFileName = relPath;
infoFile << std::endl << std::endl;
std::cout<< "Passive File Name:" << passiveFileName << 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++) {
CheckVolumes(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 = kCyan + 2;
const UInt_t kCfTransparency = 0; // 10;
const UInt_t kmStsUpgradeBoxColor = kYellow + 1;
const UInt_t kmStsUpgradeBoxTransparency = 0; // 10;
const UInt_t kmStsFEBBoxColor = kOrange + 3;
const UInt_t kmStsFEBBoxTransparency = 0; // 10;
const UInt_t kmStsUpgradeScreenColor = kGray;
const UInt_t kmStsUpgradeScreenTransparency = 0; // 10;
// name <Color, Transparency>
std::map<std::string, std::tuple<UInt_t, UInt_t>> props {
{"mSTS_Upgrade_BOX", std::tuple<UInt_t, UInt_t> {kmStsUpgradeBoxColor, kmStsUpgradeBoxTransparency}},
{"mSTS_Big_Box", std::tuple<UInt_t, UInt_t> {kmStsUpgradeScreenColor, kmStsUpgradeScreenColor}},
{"First_C_Frame", std::tuple<UInt_t, UInt_t> {kCfColor, kCfTransparency}},
{"mSTS_FEB_Box", std::tuple<UInt_t, UInt_t> {kmStsFEBBoxColor, kmStsFEBBoxTransparency}},
{"mSTS_Upgrade_Screen_Cuts", std::tuple<UInt_t, UInt_t> {kmStsUpgradeScreenColor, kmStsUpgradeScreenTransparency}},
{"mSTS_Upgrade", std::tuple<UInt_t, UInt_t> {kmStsUpgradeBoxColor, kmStsUpgradeBoxTransparency}},
};
// Match volume name and apply visual properties passive_Box_Wall_Front_Light_Foam
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 output to file
**/
void CheckVolumes(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;
}
}
/** ======================================================================= **/
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;
}
/** ======================================================================= **/
/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt, Germany
SPDX-License-Identifier: GPL-3.0-only
Authors: Ingo Deppner [commiter] */
///
/// \file Create_TOF_Geometry_v24a_FullWall.C
/// \brief Generates TOF geometry in Root format.
///
// Changelog
// 2024-11-14 - ID - make a CFV by removing outer modules. Not completely realistic.
// 2021-11-15 - ID - update design of inner wall (current design, 300 counters, 2 MRPC types)
// 2020-02-23 - ID - implementation of Bucharest wall (current design), possibility to choose between simple, single stack and double stack MRPCs
// 2017-10-18 - PAL- Fix the overlaps in the support structure => v17c
// 2016-07-18 - DE - patch double free or corruption with poleshort: same TGeoVolume name was used in pole
// 2015-11-09 - PAL- Change naming convention to follow the more meaningfull one used in trd: YYv_ss
// with YY = year, v = version (a, b, ...) and ss = setup (1h for SIS100 hadron, ...)
// => Prepare tof_v16a_1h to tof_v16a_3m
// 2015-11-09 - PAL- Modify to easily prepare tof_v14_0a to tof_v14_0e on model of 13_5a to 13_5e
// 2014-06-30 - NH - prepare tof_v14_0 geometry - SIS 300 hadron : TOF_Z_Front = 880 cm //Bucharest
// 2014-06-27 - NH - prepare tof_v13_6b geometry - SIS 300 hadron : TOF_Z_Front = 880 cm //external input
// 2013-10-16 - DE - prepare tof_v13_5a geometry - SIS 100 hadron : TOF_Z_Front = 450 cm
// 2013-10-16 - DE - prepare tof_v13_5b geometry - SIS 100 electron: TOF_Z_Front = 600 cm
// 2013-10-16 - DE - prepare tof_v13_5c geometry - SIS 100 muon : TOF_Z_Front = 650 cm
// 2013-10-16 - DE - prepare tof_v13_5d geometry - SIS 300 electron: TOF_Z_Front = 880 cm
// 2013-10-16 - DE - prepare tof_v13_5e geometry - SIS 300 muon : TOF_Z_Front = 1020 cm
// 2013-10-16 - DE - patch pole_alu bug - skip 0 thickness air volume in pole
// 2013-09-04 - DE - prepare tof_v13_4a geometry - SIS 100 hadron : TOF_Z_Front = 450 cm
// 2013-09-04 - DE - prepare tof_v13_4b geometry - SIS 100 electron: TOF_Z_Front = 600 cm
// 2013-09-04 - DE - prepare tof_v13_4c geometry - SIS 100 muon : TOF_Z_Front = 650 cm
// 2013-09-04 - DE - prepare tof_v13_4d geometry - SIS 300 electron: TOF_Z_Front = 880 cm
// 2013-09-04 - DE - prepare tof_v13_4e geometry - SIS 300 muon : TOF_Z_Front = 1020 cm
// 2013-09-04 - DE - dump z-positions to .geo.info file
// 2013-09-04 - DE - define front z-position of TOF wall (TOF_Z_Front)
// 2013-09-04 - DE - fix arrangement of glass plates in RPC cells
// in root all sizes are given in cm
// read positions of modules from dat - file
#include "TFile.h"
#include "TGeoCompositeShape.h"
#include "TGeoManager.h"
#include "TGeoMaterial.h"
#include "TGeoMatrix.h"
#include "TGeoMedium.h"
#include "TGeoPgon.h"
#include "TGeoVolume.h"
#include "TList.h"
#include "TROOT.h"
#include "TString.h"
#include "TSystem.h"
#include <iostream>
#include <sstream>
const Bool_t IncludeSupports = true; // false; // true, if support structure is included in geometry
// Name of geometry version and output file
//const TString geoVersion = "tof_v24at_1h"; // SIS 100 hadron, 4.5 m
//const TString geoVersion = "tof_v24at_1e"; // SIS 100 electron, 6 m
//const TString geoVersion = "tof_v24at_1m"; // SIS 100 muon, 6.8 m
const TString geoVersion = "tof_v24a"; // SIS 300 electron, 8.8 m
//const TString geoVersion = "tof_v24at_3m"; // SIS 300 muon, 10 m
const TString FileNameSim = geoVersion + ".geo.root?reproducible";
const TString FileNameGeo = geoVersion + "_geo.root?reproducible";
const TString FileNameInfo = geoVersion + ".geo.info";
// TOF_Z_Front corresponds to front cover of outer super module towers
const Float_t TOF_Z_Front = ("tof_v24a_1h" == geoVersion ? 450 : // SIS 100 hadron
("tof_v24a_1e" == geoVersion ? 600 : // SIS 100 electron
("tof_v24a_1m" == geoVersion ? 680 : // SIS 100 muon
("tof_v24a_3e" == geoVersion ? 880 : // SIS 300 electron
("tof_v24a_3m" == geoVersion ? 1020 : // SIS 300 muon
0 // Set default to SIS 100 electron
)))));
const TString GeometryType = "20b";
const TString KeepingVolumeMedium = "air";
const TString BoxVolumeMedium = "aluminium";
const TString PoleVolumeMedium = "tof_pole_aluminium";
const TString NoActivGasMedium = "RPCgas_noact";
const TString ActivGasMedium = "RPCgas";
const TString GlasMedium = "RPCglass";
const TString ElectronicsMedium = "carbon";
const Int_t NumberOfDifferentCounterTypes = 6;
const Float_t PCB_X[NumberOfDifferentCounterTypes] = {32., 32., 32., 30., 30., 30.};
const Float_t PCB_Y[NumberOfDifferentCounterTypes] = {
52., 26.9, 26.9, 20., 10., 6,
};
const Float_t PCB_Z[NumberOfDifferentCounterTypes] = {0.1, 0.1, 0.1, 0.1, 0.1, 0.1};
const Float_t Glass_X[NumberOfDifferentCounterTypes] = {32., 32., 32., 30., 30., 30.};
const Float_t Glass_Y[NumberOfDifferentCounterTypes] = {
52., 26.9, 26.9, 20., 10., 6,
};
const Float_t Glass_Z[NumberOfDifferentCounterTypes] = {0.028, 0.028, 0.07, 0.07, 0.07, 0.07};
const Float_t GasGap_X[NumberOfDifferentCounterTypes] = {32., 32., 32., 30., 30., 30.};
const Float_t GasGap_Y[NumberOfDifferentCounterTypes] = {
52., 26.9, 26.9, 20., 10., 6,
};
const Float_t GasGap_Z[NumberOfDifferentCounterTypes] = {0.023, 0.023, 0.025, 0.02, 0.02, 0.02};
const Int_t NumberOfGaps[NumberOfDifferentCounterTypes] = {10, 10, 8, 10, 10, 10};
const Int_t NumberOfReadoutStrips[NumberOfDifferentCounterTypes] = {32, 32, 32, 32, 32, 32};
const Float_t Electronics_X[NumberOfDifferentCounterTypes] = {34.0, 34.0, 34.0, 32.0, 32.0, 32.0};
const Float_t Electronics_Y[NumberOfDifferentCounterTypes] = {5.0, 5.0, 5.0, 0.5, 0.5, 0.5};
const Float_t Electronics_Z[NumberOfDifferentCounterTypes] = {0.3, 0.3, 0.3, 0.3, 0.3, 0.3};
const Int_t NofModuleTypes = 15;
const Int_t MaxNofCounters = 60;
const Int_t MaxNofModules = 128;
const Int_t NCounterInModule[NofModuleTypes] = {5, 5, 5, 5, 5, 30, 24, 27, 18, 24, 30, 24, 27, 18, 24};
const Int_t NModulesOfModuleType[NofModuleTypes] = {62, 32, 8, 96, 16, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1};
Int_t iMod[NofModuleTypes] = {0};
//Int_t ActNofModuleTypes = 2;
//Int_t NModules[NofModuleTypes] = {0};
Float_t xPosCou[NofModuleTypes][MaxNofCounters];
Float_t yPosCou[NofModuleTypes][MaxNofCounters];
Float_t zPosCou[NofModuleTypes][MaxNofCounters];
Int_t CouType[NofModuleTypes][MaxNofCounters];
Float_t xPosMod[MaxNofModules];
Float_t yPosMod[MaxNofModules];
Float_t zPosMod[MaxNofModules];
Int_t ModType[MaxNofModules];
//Float_t FlipMod[NofModuleTypes][MaxNofModules];
const Float_t Module_Size_X[NofModuleTypes] = {180.2, 180.2, 180.2, 180.2, 180.2, 210.5, 124.4, 98.3,
69.3, 124.4, 210.5, 124.4, 98.3, 69.3, 124.4};
const Float_t Module_Size_Y[NofModuleTypes] = {74., 49., 49., 49., 49., 73.8, 130.0, 128.7,
128.7, 130.0, 73.8, 130.0, 128.7, 128.7, 130.0};
const Float_t Module_Size_Z[NofModuleTypes] = {11.2, 11.2, 11.2, 11.2, 11.2, 19.6, 19.6, 19.6,
19.6, 19.6, 19.6, 19.6, 19.6, 19.6, 19.6};
// Placement of the counter inside the module
const Float_t CounterRotationAngle[NofModuleTypes] = {10., 10., 0., 10., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.};
const Float_t Module_Thick_Alu_X_left = 1.;
const Float_t Module_Thick_Alu_X_right = 0.1;
const Float_t Module_Thick_Alu_Y = 0.1;
const Float_t Module_Thick_Alu_Z_front = 0.1;
const Float_t Module_Thick_Alu_Z_back = 1.;
const Float_t shift_gas_box_x = (Module_Thick_Alu_X_right - Module_Thick_Alu_X_left) / 2;
const Float_t shift_gas_box_z = (Module_Thick_Alu_Z_back - Module_Thick_Alu_Z_front) / 2;
const Float_t Wall_Z_Position =
TOF_Z_Front + 1000. - 884.; // if you want to know where this numbers come from ask Ingo
// Pole (support structure)
const Int_t MaxNumberOfPoles = 200;
Float_t Pole_ZPos[MaxNumberOfPoles];
Float_t Pole_XPos[MaxNumberOfPoles];
Float_t Pole_Col[MaxNumberOfPoles];
Int_t NumberOfPoles = 0;
const Float_t Pole_Size_X = 8.;
const Float_t Pole_Size_Y = 1000.;
const Float_t PoleShort_Size_Y = 370.;
const Float_t Pole_Size_Z = 2.;
const Float_t Pole_Thick_X = 0.4;
const Float_t Pole_Thick_Y = 0.4;
const Float_t Pole_Thick_Z = 0.4;
const Float_t XLimInner = 180.;
// Bars & frame (support structure)
const Float_t Frame_Size_X = 20.;
const Float_t Frame_Size_Y = 20.;
Float_t Bar_Size_Z = 176.;
const Float_t Frame_XLen = 1400;
const Float_t Frame_YLen = Pole_Size_Y + 2. * Frame_Size_Y;
Float_t Frame_Pos_Z = TOF_Z_Front + 88.;
const Float_t Bar_Size_X = 30;
const Float_t Bar_Size_Y = 20.;
Float_t Bar_Pos_Z;
const Int_t MaxNumberOfBars = 200;
Float_t Bar_ZPos[MaxNumberOfBars];
Float_t Bar_XPos[MaxNumberOfBars];
Int_t NumberOfBars = 0;
const Float_t ChamberOverlap = 40;
const Float_t DxColl = 158.0; //Module_Size_X-ChamberOverlap;
//const Float_t Pole_Offset=Module_Size_X/2.+Pole_Size_X/2.;
const Float_t Pole_Offset = 90.0 + Pole_Size_X / 2.;
// some global variables
TGeoManager* gGeoMan = NULL; // Pointer to TGeoManager instance
TGeoVolume* gModules[NofModuleTypes]; // Global storage for module types
TGeoVolume* gCounter[NumberOfDifferentCounterTypes];
TGeoVolume* gPole;
TGeoVolume* gPoleShort;
TGeoVolume* gBar[MaxNumberOfBars];
Float_t Last_Size_Y = 0.;
Float_t Last_Over_Y = 0.;
// Forward declarations
void create_materials_from_media_file();
TGeoVolume* create_counter_simple(Int_t);
TGeoVolume* create_counter_doublestack(Int_t);
TGeoVolume* create_counter_singlestack(Int_t);
TGeoVolume* create_tof_module(Int_t);
TGeoVolume* create_tof_module_m(Int_t);
TGeoVolume* create_new_tof_module(Int_t);
TGeoVolume* create_new_tof_module_m(Int_t);
TGeoVolume* create_tof_pole();
TGeoVolume* create_tof_poleshort();
TGeoVolume* create_tof_bar();
void position_tof_poles(Int_t);
void position_tof_bars(Int_t);
void position_inner_tof_modules(Int_t);
void position_side_tof_modules(Int_t);
void position_outer_tof_modules(Int_t);
void position_tof_modules();
void position_tof_modules_m(Int_t, Int_t);
void dump_info_file();
void read_module_positions();
void read_counter_positions();
void Create_TOF_Geometry_v24a_FullWall()
{
// Load the necessary FairRoot libraries
// gROOT->LoadMacro("$VMCWORKDIR/gconfig/basiclibs.C");
// basiclibs();
// gSystem->Load("libGeoBase");
// gSystem->Load("libParBase");
// gSystem->Load("libBase");
// Printout what we are generating
std::cout << "Generating geometry " << geoVersion << " at " << Wall_Z_Position << " cm from center of the magnet." << std::endl;
// read input Data
read_counter_positions();
read_module_positions();
// Load needed material definition from media.geo file
create_materials_from_media_file();
// Get the GeoManager for later usage
gGeoMan = (TGeoManager*) gROOT->FindObject("FAIRGeom");
gGeoMan->SetVisLevel(7); // 2 = super modules
gGeoMan->SetVisOption(1);
// Create the top volume
/*
TGeoBBox* topbox= new TGeoBBox("", 1000., 1000., 1000.);
TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air"));
gGeoMan->SetTopVolume(top);
*/
TGeoVolume* top = new TGeoVolumeAssembly("TOP");
gGeoMan->SetTopVolume(top);
TGeoVolume* tof = new TGeoVolumeAssembly(geoVersion);
top->AddNode(tof, 1);
for (Int_t counterType = 0; counterType < NumberOfDifferentCounterTypes; counterType++) {
//gCounter[counterType] = create_counter_simple(counterType);
gCounter[counterType] = create_counter_doublestack(counterType);
//gCounter[counterType] = create_counter_singlestack(counterType);
}
for (Int_t moduleType = 0; moduleType < NofModuleTypes; moduleType++) {
gModules[moduleType] = create_new_tof_module(moduleType);
gModules[moduleType]->SetVisContainers(1);
}
gPole = create_tof_pole();
gPoleShort = create_tof_poleshort();
position_tof_modules();
if (IncludeSupports) position_tof_poles(0);
if (IncludeSupports) position_tof_bars(0);
gGeoMan->CloseGeometry();
gGeoMan->CheckOverlaps(0.00001);
gGeoMan->CheckOverlaps(0.00001, "s");
gGeoMan->PrintOverlaps();
gGeoMan->GetListOfOverlaps()->Print();
gGeoMan->Test();
tof->Export(FileNameSim); // an alternative way of writing the tof volume
TFile* outfile = new TFile(FileNameSim, "UPDATE");
TGeoTranslation* tof_placement = new TGeoTranslation("tof_trans", 0., 0., 705.);
tof_placement->Write();
outfile->Close();
outfile = new TFile(FileNameGeo, "RECREATE");
gGeoMan->Write();
outfile->Close();
dump_info_file();
top->SetVisContainers(1);
gGeoMan->SetVisLevel(5);
top->Draw("ogl");
//top->Draw();
//gModules[0]->Draw("ogl");
// gModules[0]->Draw("");
gModules[0]->SetVisContainers(1);
// gModules[1]->Draw("");
gModules[1]->SetVisContainers(1);
//gModules[5]->Draw("");
// top->Raytrace();
// Printout what we are generating
std::cout << "Done generating geometry " << geoVersion << " at " << Wall_Z_Position << " cm from center of the magnet." << std::endl;
}
void read_counter_positions()
{
//TFile * fPosInput = new TFile( "TOF_10M.dat", "READ");
for (Int_t modtype = 0; modtype < NofModuleTypes; modtype++) {
TString moduleTypeName = Form("ModuleType%d_v21a.dat", modtype);
cout << "load parameters from file " << moduleTypeName << endl;
ifstream inFile;
inFile.open(moduleTypeName);
if (!inFile.is_open()) {
cout << "<E> cannot open input file " << endl;
return;
}
cout << "------------------------------" << endl;
cout << "Reading content of " << moduleTypeName << endl;
std::string strdummy;
std::getline(inFile, strdummy);
//cout<<strdummy<<endl;
Int_t iNum;
Int_t ictype;
Float_t iX;
Float_t iY;
Float_t iZ;
Int_t iCou = 0;
while (std::getline(inFile, strdummy)) {
// std::getline(inFile,strdummy);
//cout<<strdummy<<endl;
stringstream ss;
ss << strdummy;
ss >> iNum >> ictype >> iX >> iY >> iZ;
ss << strdummy;
//cout<<iCou<< " "<<iNum<<" "<<ictype<<" "<<iX<<" "<<iY<<" "<<iZ<<endl;
CouType[modtype][iCou] = ictype;
xPosCou[modtype][iCou] = iX;
yPosCou[modtype][iCou] = iY;
zPosCou[modtype][iCou] = iZ;
iCou++;
}
}
}
void read_module_positions()
{
//TFile * fPosInput = new TFile( "TOF_10M.dat", "READ");
ifstream inFile;
inFile.open("ModulePosition_10m_v24a.dat");
if (!inFile.is_open()) {
cout << "<E> cannot open input file " << endl;
return;
}
cout << "------------------------------" << endl;
cout << "Reading content of ModulePosition_10m_v24a.dat" << endl;
std::string strdummy;
std::getline(inFile, strdummy);
//cout<<strdummy<<endl;
Int_t iNum;
Int_t iModT;
Float_t iX;
Float_t iY;
Float_t iZ;
//Int_t iModType=0;
Int_t iMod = 0;
//while( !inFile.eof() )
//for(Int_t iL=0; iL<2; iL++)
while (std::getline(inFile, strdummy)) {
// std::getline(inFile,strdummy);
//cout<<strdummy<<endl;
stringstream ss;
ss << strdummy;
ss >> iNum >> iModT >> iX >> iY >> iZ;
ss << strdummy;
// ss>>iNum>>iX>>iY>>iZ>>cType[0]>>cType[1];
cout << iNum << " " << iModT << " " << iX << " " << iY << " " << iZ << endl;
//cout<<" ModType "<<iModType<<endl;
//cout<<" ModType "<<iModType<<", # "<<iMod<<endl;
ModType[iMod] = iModT;
xPosMod[iMod] = iX;
yPosMod[iMod] = iY;
zPosMod[iMod] = iZ;
iMod++;
/*
if(cPos=='l'){
FlipMod[iModType][iMod]=1.;
}else{
FlipMod[iModType][iMod]=0.;
}
// if (iModType==1 && iMod==1) return;
cout<<" ModType "<<iModType<<", Mod "<<iMod<<", x "<<xPosMod[iModType][iMod]<<", y "
<<yPosMod[iModType][iMod]<<", z "<<zPosMod[iModType][iMod]<<endl;
*/
}
cout << "Data reading finished for " << endl;
}
void create_materials_from_media_file()
{
// Use the FairRoot geometry interface to load the media which are already defined
FairGeoLoader* geoLoad = new FairGeoLoader("TGeo", "FairGeoLoader");
FairGeoInterface* geoFace = geoLoad->getGeoInterface();
TString geoPath = gSystem->Getenv("VMCWORKDIR");
TString geoFile = geoPath + "/geometry/media.geo";
geoFace->setMediaFile(geoFile);
geoFace->readMedia();
// Read the required media and create them in the GeoManager
FairGeoMedia* geoMedia = geoFace->getMedia();
FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder();
FairGeoMedium* air = geoMedia->getMedium("air");
FairGeoMedium* aluminium = geoMedia->getMedium("aluminium");
FairGeoMedium* tof_pole_aluminium = geoMedia->getMedium("tof_pole_aluminium");
FairGeoMedium* RPCgas = geoMedia->getMedium("RPCgas");
FairGeoMedium* RPCgas_noact = geoMedia->getMedium("RPCgas_noact");
FairGeoMedium* RPCglass = geoMedia->getMedium("RPCglass");
FairGeoMedium* carbon = geoMedia->getMedium("carbon");
// include check if all media are found
geoBuild->createMedium(air);
geoBuild->createMedium(aluminium);
geoBuild->createMedium(tof_pole_aluminium);
geoBuild->createMedium(RPCgas);
geoBuild->createMedium(RPCgas_noact);
geoBuild->createMedium(RPCglass);
geoBuild->createMedium(carbon);
}
TGeoVolume* create_counter_simple(Int_t countType)
{
TGeoMedium* activeGasVolMed = gGeoMan->GetMedium(ActivGasMedium);
TGeoMedium* noActiveGasVolMed = gGeoMan->GetMedium(NoActivGasMedium);
//TGeoMedium* glassPlateVolMed = gGeoMan->GetMedium(GlasMedium);
//gas gap
Int_t nstrips = NumberOfReadoutStrips[countType];
Float_t ggdx = GasGap_X[countType];
Float_t ggdy = GasGap_Y[countType];
//Float_t ggdz=GasGap_Z[countType];
Float_t ggdz = 1.;
Float_t gsdx = ggdx / float(nstrips);
TGeoBBox* counter_box = new TGeoBBox("", (ggdx + 0.2) / 2., (ggdy + 0.2) / 2., (ggdz + 0.2) / 2.);
TGeoVolume* counter = new TGeoVolume("counter", counter_box, noActiveGasVolMed);
counter->SetLineColor(kCyan); // set line color for the counter
counter->SetTransparency(70); // set transparency for the TOF
// Single gas gap
TGeoBBox* gas_gap = new TGeoBBox("", ggdx / 2., ggdy / 2., ggdz / 2.);
TGeoVolume* gas_gap_vol = new TGeoVolume("Gap", gas_gap, activeGasVolMed);
gas_gap_vol->Divide("Cell", 1, nstrips, -ggdx / 2., 0);
gas_gap_vol->SetLineColor(kRed); // set line color for the gas gap
gas_gap_vol->SetTransparency(70); // set transparency for the TOF
TGeoTranslation* gas_gap_trans = new TGeoTranslation("", 0., 0., 0.);
counter->AddNode(gas_gap_vol, 0, gas_gap_trans);
return counter;
}
TGeoVolume* create_counter_doublestack(Int_t countType)
{
//glass
Float_t pdx = PCB_X[countType];
Float_t pdy = PCB_Y[countType];
Float_t pdz = PCB_Z[countType];
//glass
Float_t gdx = Glass_X[countType];
Float_t gdy = Glass_Y[countType];
Float_t gdz = Glass_Z[countType];
//gas gap
Int_t nstrips = NumberOfReadoutStrips[countType];
Int_t ngaps = NumberOfGaps[countType];
Float_t ggdx = GasGap_X[countType];
Float_t ggdy = GasGap_Y[countType];
Float_t ggdz = GasGap_Z[countType];
Float_t gsdx = ggdx / float(nstrips);
//single stack
//Float_t dzpos=gdz+ggdz;
// Float_t startzpos=SingleStackStartPosition_Z[modType];
// electronics
//pcb dimensions
Float_t dxe = Electronics_X[countType];
Float_t dye = Electronics_Y[countType];
Float_t dze = Electronics_Z[countType];
Float_t yele = (gdy + 0.1) / 2. + dye / 2.;
// needed materials
TGeoMedium* glassPlateVolMed = gGeoMan->GetMedium(GlasMedium);
TGeoMedium* noActiveGasVolMed = gGeoMan->GetMedium(NoActivGasMedium);
TGeoMedium* activeGasVolMed = gGeoMan->GetMedium(ActivGasMedium);
TGeoMedium* electronicsVolMed = gGeoMan->GetMedium(ElectronicsMedium);
// Single PCB
TGeoBBox* pcb = new TGeoBBox("", pdx / 2., pdy / 2., pdz / 2.);
TGeoVolume* pcb_vol = new TGeoVolume("tof_pcb", pcb, electronicsVolMed);
pcb_vol->SetLineColor(kGreen); // set line color for the pcb
pcb_vol->SetTransparency(20); // set transparency for the TOF
TGeoTranslation* pcb_trans0 = new TGeoTranslation("", 0., 0., 0.);
// Single glass plate
TGeoBBox* glass_plate = new TGeoBBox("", gdx / 2., gdy / 2., gdz / 2.);
TGeoVolume* glass_plate_vol = new TGeoVolume("tof_glass", glass_plate, glassPlateVolMed);
glass_plate_vol->SetLineColor(kMagenta); // set line color for the glass plate
glass_plate_vol->SetTransparency(20); // set transparency for the TOF
//TGeoTranslation* glass_plate_trans = new TGeoTranslation("", 0., 0., 0.);
// Single gas gap
TGeoBBox* gas_gap = new TGeoBBox("", ggdx / 2., ggdy / 2., ggdz / 2.);
TGeoVolume* gas_gap_vol = new TGeoVolume("Gap", gas_gap, activeGasVolMed);
gas_gap_vol->Divide("Cell", 1, nstrips, -ggdx / 2., 0);
gas_gap_vol->SetLineColor(kRed); // set line color for the gas gap
gas_gap_vol->SetTransparency(70); // set transparency for the TOF
//TGeoTranslation* gas_gap_trans = new TGeoTranslation("", 0., 0., (gdz+ggdz)/2.);
TGeoVolume* counter = new TGeoVolumeAssembly("counter");
counter->AddNode(pcb_vol, 0, pcb_trans0);
Int_t l = 0;
for (l = 0; l < ngaps + 1; l++) {
if (l % 2 == 0) {
if (l == 0) {
TGeoTranslation* glass_plate_trans = new TGeoTranslation("", 0., 0., 0.5 * (pdz + gdz));
counter->AddNode(glass_plate_vol, l, glass_plate_trans);
TGeoTranslation* glass_plate_trans1 = new TGeoTranslation("", 0., 0., -0.5 * (pdz + gdz));
counter->AddNode(glass_plate_vol, l + ngaps + 1, glass_plate_trans1);
}
else {
TGeoTranslation* glass_plate_trans =
new TGeoTranslation("", 0., 0., 0.5 * (pdz + gdz) + l * (0.5 * (ggdz + gdz)));
counter->AddNode(glass_plate_vol, l, glass_plate_trans);
TGeoTranslation* glass_plate_trans1 =
new TGeoTranslation("", 0., 0., -0.5 * (pdz + gdz) - l * (0.5 * (ggdz + gdz)));
counter->AddNode(glass_plate_vol, l + ngaps + 1, glass_plate_trans1);
}
}
else {
TGeoTranslation* gas_gap_trans = new TGeoTranslation("", 0., 0., 0.5 * (pdz + gdz) + l * (0.5 * (ggdz + gdz)));
counter->AddNode(gas_gap_vol, l, gas_gap_trans);
TGeoTranslation* gas_gap_trans1 = new TGeoTranslation("", 0., 0., -0.5 * (pdz + gdz) - l * (0.5 * (ggdz + gdz)));
counter->AddNode(gas_gap_vol, l + ngaps + 1, gas_gap_trans1);
}
}
TGeoTranslation* pcb_trans1 = new TGeoTranslation("", 0., 0., (pdz + gdz) + (l - 1) * (0.5 * (ggdz + gdz)));
counter->AddNode(pcb_vol, l + ngaps + 1, pcb_trans1);
TGeoTranslation* pcb_trans2 = new TGeoTranslation("", 0., 0., -(pdz + gdz) - (l - 1) * (0.5 * (ggdz + gdz)));
counter->AddNode(pcb_vol, l + ngaps + 1, pcb_trans2);
TGeoBBox* epcb = new TGeoBBox("", dxe / 2., dye / 2., dze / 2.);
TGeoVolume* epcb_vol = new TGeoVolume("epcb", epcb, electronicsVolMed);
epcb_vol->SetLineColor(kCyan); // set line color for the electronic
epcb_vol->SetTransparency(10); // set transparency for the TOF
for (Int_t l = 0; l < 2; l++) {
yele *= -1.;
TGeoTranslation* epcb_trans = new TGeoTranslation("", 0., yele, 0.);
counter->AddNode(epcb_vol, l, epcb_trans);
}
return counter;
}
TGeoVolume* create_counter_singlestack(Int_t modType)
{
//glass
Float_t gdx = Glass_X[modType];
Float_t gdy = Glass_Y[modType];
Float_t gdz = Glass_Z[modType];
//gas gap
Int_t nstrips = NumberOfReadoutStrips[modType];
Int_t ngaps = NumberOfGaps[modType];
Float_t ggdx = GasGap_X[modType];
Float_t ggdy = GasGap_Y[modType];
Float_t ggdz = GasGap_Z[modType];
Float_t gsdx = ggdx / (Float_t)(nstrips);
// electronics
//pcb dimensions
Float_t dxe = Electronics_X[modType];
Float_t dye = Electronics_Y[modType];
Float_t dze = Electronics_Z[modType];
Float_t yele = gdy / 2. + dye / 2.;
// counter size (calculate from glas, gap and electronics sizes)
Float_t cdx = TMath::Max(gdx, ggdx);
cdx = TMath::Max(cdx, dxe) + 0.2;
Float_t cdy = TMath::Max(gdy, ggdy) + 2 * dye + 0.2;
Float_t cdz = ngaps * ggdz + (ngaps + 1) * gdz + 0.2; // ngaps * (gdz+ggdz) + gdz + 0.2; // ok
//calculate thickness and first position in counter of single stack
Float_t dzpos = gdz + ggdz;
Float_t startzposglas = -ngaps * (gdz + ggdz) / 2.; // -cdz/2.+0.1+gdz/2.; // ok // (-cdz+gdz)/2.; // not ok
Float_t startzposgas = startzposglas + gdz / 2. + ggdz / 2.; // -cdz/2.+0.1+gdz +ggdz/2.; // ok
// needed materials
TGeoMedium* glassPlateVolMed = gGeoMan->GetMedium(GlasMedium);
TGeoMedium* noActiveGasVolMed = gGeoMan->GetMedium(NoActivGasMedium);
TGeoMedium* activeGasVolMed = gGeoMan->GetMedium(ActivGasMedium);
TGeoMedium* electronicsVolMed = gGeoMan->GetMedium(ElectronicsMedium);
// define counter volume
TGeoBBox* counter_box = new TGeoBBox("", cdx / 2., cdy / 2., cdz / 2.);
TGeoVolume* counter = new TGeoVolume("counter", counter_box, noActiveGasVolMed);
counter->SetLineColor(kCyan); // set line color for the counter
counter->SetTransparency(70); // set transparency for the TOF
// define single glass plate volume
TGeoBBox* glass_plate = new TGeoBBox("", gdx / 2., gdy / 2., gdz / 2.);
TGeoVolume* glass_plate_vol = new TGeoVolume("tof_glass", glass_plate, glassPlateVolMed);
glass_plate_vol->SetLineColor(kMagenta); // set line color for the glass plate
glass_plate_vol->SetTransparency(20); // set transparency for the TOF
// define single gas gap volume
TGeoBBox* gas_gap = new TGeoBBox("", ggdx / 2., ggdy / 2., ggdz / 2.);
TGeoVolume* gas_gap_vol = new TGeoVolume("Gap", gas_gap, activeGasVolMed);
gas_gap_vol->Divide("Cell", 1, nstrips, -ggdx / 2., 0);
gas_gap_vol->SetLineColor(kRed); // set line color for the gas gap
gas_gap_vol->SetTransparency(99); // set transparency for the TOF
// place 8 gas gaps and 9 glas plates in the counter
for (Int_t igap = 0; igap <= ngaps; igap++) {
// place (ngaps+1) glass plates
Float_t zpos_glas = startzposglas + igap * dzpos;
TGeoTranslation* glass_plate_trans = new TGeoTranslation("", 0., 0., zpos_glas);
counter->AddNode(glass_plate_vol, igap, glass_plate_trans);
// place ngaps gas gaps
if (igap < ngaps) {
Float_t zpos_gas = startzposgas + igap * dzpos;
TGeoTranslation* gas_gap_trans = new TGeoTranslation("", 0., 0., zpos_gas);
counter->AddNode(gas_gap_vol, igap, gas_gap_trans);
}
// cout <<"Zpos(Glas): "<< zpos_glas << endl;
// cout <<"Zpos(Gas): "<< zpos_gas << endl;
}
// create and place the electronics above and below the glas stack
TGeoBBox* pcb = new TGeoBBox("", dxe / 2., dye / 2., dze / 2.);
TGeoVolume* pcb_vol = new TGeoVolume("pcb", pcb, electronicsVolMed);
pcb_vol->SetLineColor(kYellow); // kCyan); // set line color for electronics
pcb_vol->SetTransparency(10); // set transparency for the TOF
for (Int_t l = 0; l < 2; l++) {
yele *= -1.;
TGeoTranslation* pcb_trans = new TGeoTranslation("", 0., yele, 0.);
counter->AddNode(pcb_vol, l, pcb_trans);
}
return counter;
}
TGeoVolume* create_new_tof_module(Int_t modType)
{
Float_t dx = Module_Size_X[modType];
Float_t dy = Module_Size_Y[modType];
Float_t dz = Module_Size_Z[modType];
Float_t width_aluxl = Module_Thick_Alu_X_left;
Float_t width_aluxr = Module_Thick_Alu_X_right;
Float_t width_aluy = Module_Thick_Alu_Y;
Float_t width_aluzf = Module_Thick_Alu_Z_front;
Float_t width_aluzb = Module_Thick_Alu_Z_back;
Float_t rotangle = CounterRotationAngle[modType];
TGeoMedium* boxVolMed = gGeoMan->GetMedium(BoxVolumeMedium);
TGeoMedium* noActiveGasVolMed = gGeoMan->GetMedium(NoActivGasMedium);
TString moduleName = Form("module_%d", modType);
TGeoBBox* module_box = new TGeoBBox("", dx / 2., dy / 2., dz / 2.);
TGeoVolume* module = new TGeoVolume(moduleName, module_box, boxVolMed);
module->SetLineColor(kGreen); // set line color for the alu box
module->SetTransparency(20); // set transparency for the TOF
if (modType < 5) {
TGeoBBox* gas_box = new TGeoBBox("", (dx - (width_aluxl + width_aluxr)) / 2., (dy - 2 * width_aluy) / 2.,
(dz - 2 * width_aluzf) / 2.);
TGeoVolume* gas_box_vol = new TGeoVolume("gas_box", gas_box, noActiveGasVolMed);
gas_box_vol->SetLineColor(kBlue); // set line color for the alu box
gas_box_vol->SetTransparency(50); // set transparency for the TOF
TGeoTranslation* gas_box_trans = new TGeoTranslation("", shift_gas_box_x, 0., 0.);
module->AddNode(gas_box_vol, 0, gas_box_trans);
for (Int_t j = 0; j < NCounterInModule[modType]; j++) { //loop over counters (modules)
cout << j << " " << modType << " xPos " << xPosCou[modType][j] << " yPos " << yPosCou[modType][j] << " zPos "
<< zPosCou[modType][j] << endl;
TGeoTranslation* counter_trans =
new TGeoTranslation("", xPosCou[modType][j], yPosCou[modType][j], zPosCou[modType][j]);
TGeoRotation* counter_rot = new TGeoRotation();
counter_rot->RotateY(rotangle);
TGeoCombiTrans* counter_combi_trans = new TGeoCombiTrans(*counter_trans, *counter_rot);
gas_box_vol->AddNode(gCounter[CouType[modType][j]], j, counter_combi_trans);
}
cout << "-------------------------------" << endl;
}
else {
TGeoBBox* gas_box = new TGeoBBox("", (dx - 2 * width_aluxr) / 2., (dy - 2 * width_aluy) / 2.,
(dz + (width_aluzf - width_aluzb)) / 2.);
TGeoVolume* gas_box_vol = new TGeoVolume("gas_box", gas_box, noActiveGasVolMed);
gas_box_vol->SetLineColor(kBlue); // set line color for the alu box
gas_box_vol->SetTransparency(50); // set transparency for the TOF
TGeoTranslation* gas_box_trans = new TGeoTranslation("", 0., 0., -shift_gas_box_z);
module->AddNode(gas_box_vol, 0, gas_box_trans);
for (Int_t j = 0; j < NCounterInModule[modType]; j++) { //loop over counters (modules)
cout << j << " " << modType << " xPos " << xPosCou[modType][j] << " yPos " << yPosCou[modType][j] << " zPos "
<< zPosCou[modType][j] << endl;
TGeoTranslation* counter_trans =
new TGeoTranslation("", xPosCou[modType][j], yPosCou[modType][j], zPosCou[modType][j]);
TGeoRotation* counter_rot = new TGeoRotation();
counter_rot->RotateY(rotangle);
TGeoCombiTrans* counter_combi_trans = new TGeoCombiTrans(*counter_trans, *counter_rot);
gas_box_vol->AddNode(gCounter[CouType[modType][j]], j, counter_combi_trans);
}
cout << "-------------------------------" << endl;
}
return module;
}
TGeoVolume* create_tof_pole()
{
// needed materials
TGeoMedium* boxVolMed = gGeoMan->GetMedium(PoleVolumeMedium);
TGeoMedium* airVolMed = gGeoMan->GetMedium(KeepingVolumeMedium);
Float_t dx = Pole_Size_X;
Float_t dy = Pole_Size_Y;
Float_t dz = Pole_Size_Z;
Float_t width_alux = Pole_Thick_X;
Float_t width_aluy = Pole_Thick_Y;
Float_t width_aluz = Pole_Thick_Z;
TGeoVolume* pole = new TGeoVolumeAssembly("Pole");
TGeoBBox* pole_alu_box = new TGeoBBox("", dx / 2., dy / 2., dz / 2.);
TGeoVolume* pole_alu_vol = new TGeoVolume("pole_alu", pole_alu_box, boxVolMed);
pole_alu_vol->SetLineColor(kGreen); // set line color for the alu box
// pole_alu_vol->SetTransparency(20); // set transparency for the TOF
TGeoTranslation* pole_alu_trans = new TGeoTranslation("", 0., 0., 0.);
pole->AddNode(pole_alu_vol, 0, pole_alu_trans);
Float_t air_dx = dx / 2. - width_alux;
Float_t air_dy = dy / 2. - width_aluy;
Float_t air_dz = dz / 2. - width_aluz;
// cout << "My pole." << endl;
if (air_dx <= 0.) cout << "ERROR - No air volume in pole X, size: " << air_dx << endl;
if (air_dy <= 0.) cout << "ERROR - No air volume in pole Y, size: " << air_dy << endl;
if (air_dz <= 0.) cout << "ERROR - No air volume in pole Z, size: " << air_dz << endl;
if ((air_dx > 0.) && (air_dy > 0.) && (air_dz > 0.)) // crate air volume only, if larger than zero
{
TGeoBBox* pole_air_box = new TGeoBBox("", air_dx, air_dy, air_dz);
// TGeoBBox* pole_air_box = new TGeoBBox("", dx/2.-width_alux, dy/2.-width_aluy, dz/2.-width_aluz);
TGeoVolume* pole_air_vol = new TGeoVolume("pole_air", pole_air_box, airVolMed);
pole_air_vol->SetLineColor(kYellow); // set line color for the alu box
pole_air_vol->SetTransparency(70); // set transparency for the TOF
TGeoTranslation* pole_air_trans = new TGeoTranslation("", 0., 0., 0.);
pole_alu_vol->AddNode(pole_air_vol, 0, pole_air_trans);
}
else
cout << "Skipping pole_air_vol, no thickness: " << air_dx << " " << air_dy << " " << air_dz << endl;
return pole;
}
TGeoVolume* create_tof_poleshort()
{
// needed materials
TGeoMedium* boxVolMed = gGeoMan->GetMedium(PoleVolumeMedium);
TGeoMedium* airVolMed = gGeoMan->GetMedium(KeepingVolumeMedium);
Float_t dx = Pole_Size_X;
Float_t dy = PoleShort_Size_Y;
Float_t dz = Pole_Size_Z;
Float_t width_alux = Pole_Thick_X;
Float_t width_aluy = Pole_Thick_Y;
Float_t width_aluz = Pole_Thick_Z;
TGeoVolume* pole = new TGeoVolumeAssembly("PoleShort");
TGeoBBox* pole_alu_box = new TGeoBBox("", dx / 2., dy / 2., dz / 2.);
TGeoVolume* pole_alu_vol = new TGeoVolume("poleshort_alu", pole_alu_box, boxVolMed);
pole_alu_vol->SetLineColor(kGreen); // set line color for the alu box
// pole_alu_vol->SetTransparency(20); // set transparency for the TOF
TGeoTranslation* pole_alu_trans = new TGeoTranslation("", 0., 0., 0.);
pole->AddNode(pole_alu_vol, 0, pole_alu_trans);
Float_t air_dx = dx / 2. - width_alux;
Float_t air_dy = dy / 2. - width_aluy;
Float_t air_dz = dz / 2. - width_aluz;
// cout << "My pole." << endl;
if (air_dx <= 0.) cout << "ERROR - No air volume in pole X, size: " << air_dx << endl;
if (air_dy <= 0.) cout << "ERROR - No air volume in pole Y, size: " << air_dy << endl;
if (air_dz <= 0.) cout << "ERROR - No air volume in pole Z, size: " << air_dz << endl;
if ((air_dx > 0.) && (air_dy > 0.) && (air_dz > 0.)) // crate air volume only, if larger than zero
{
TGeoBBox* pole_air_box = new TGeoBBox("", air_dx, air_dy, air_dz);
// TGeoBBox* pole_air_box = new TGeoBBox("", dx/2.-width_alux, dy/2.-width_aluy, dz/2.-width_aluz);
TGeoVolume* pole_air_vol = new TGeoVolume("poleshort_air", pole_air_box, airVolMed);
pole_air_vol->SetLineColor(kYellow); // set line color for the alu box
pole_air_vol->SetTransparency(70); // set transparency for the TOF
TGeoTranslation* pole_air_trans = new TGeoTranslation("", 0., 0., 0.);
pole_alu_vol->AddNode(pole_air_vol, 0, pole_air_trans);
}
else
cout << "Skipping pole_air_vol, no thickness: " << air_dx << " " << air_dy << " " << air_dz << endl;
return pole;
}
TGeoVolume* create_tof_bar(Float_t dx, Float_t dy, Float_t dz)
{
// needed materials
TGeoMedium* boxVolMed = gGeoMan->GetMedium(PoleVolumeMedium);
TGeoMedium* airVolMed = gGeoMan->GetMedium(KeepingVolumeMedium);
Float_t width_alux = Pole_Thick_X;
Float_t width_aluy = Pole_Thick_Y;
Float_t width_aluz = Pole_Thick_Z;
TGeoVolume* bar = new TGeoVolumeAssembly("Bar");
TGeoBBox* bar_alu_box = new TGeoBBox("", dx / 2., dy / 2., dz / 2.);
TGeoVolume* bar_alu_vol = new TGeoVolume("bar_alu", bar_alu_box, boxVolMed);
bar_alu_vol->SetLineColor(kGreen); // set line color for the alu box
// bar_alu_vol->SetTransparency(20); // set transparency for the TOF
TGeoTranslation* bar_alu_trans = new TGeoTranslation("", 0., 0., 0.);
bar->AddNode(bar_alu_vol, 0, bar_alu_trans);
TGeoBBox* bar_air_box = new TGeoBBox("", dx / 2. - width_alux, dy / 2. - width_aluy, dz / 2. - width_aluz);
TGeoVolume* bar_air_vol = new TGeoVolume("bar_air", bar_air_box, airVolMed);
bar_air_vol->SetLineColor(kYellow); // set line color for the alu box
bar_air_vol->SetTransparency(70); // set transparency for the TOF
TGeoTranslation* bar_air_trans = new TGeoTranslation("", 0., 0., 0.);
bar_alu_vol->AddNode(bar_air_vol, 0, bar_air_trans);
return bar;
}
void position_tof_poles(Int_t modType)
{
TGeoTranslation* pole_trans = NULL;
Int_t numPoles = 0;
Int_t numPolesShort = 0;
for (Int_t i = 0; i < NumberOfPoles; i++) {
Float_t xPos = Pole_XPos[i];
Float_t zPos = Pole_ZPos[i];
if (TMath::Abs(xPos) > XLimInner) {
pole_trans = new TGeoTranslation("", xPos, 0., zPos);
gGeoMan->GetVolume(geoVersion)->AddNode(gPole, numPoles, pole_trans);
numPoles++;
}
else { // position 2 short poles
// upper short poles
pole_trans = new TGeoTranslation("", xPos, Pole_Size_Y / 2. - PoleShort_Size_Y / 2., zPos);
gGeoMan->GetVolume(geoVersion)->AddNode(gPoleShort, numPolesShort, pole_trans);
numPolesShort++;
// lower short poles
pole_trans = new TGeoTranslation("", xPos, PoleShort_Size_Y / 2. - Pole_Size_Y / 2., zPos);
gGeoMan->GetVolume(geoVersion)->AddNode(gPoleShort, numPolesShort, pole_trans);
numPolesShort++;
}
// cout << " Position Pole "<< numPoles<<" at z="<< Pole_ZPos[i] <<", x "<<Pole_XPos[i]<< endl;
}
}
void position_tof_bars(Int_t modType)
{
TGeoTranslation* bar_trans = NULL;
Int_t numBars = 0;
Int_t i, j;
for (i = 0; i < NumberOfBars; i++) {
Float_t xPos = Bar_XPos[i];
Float_t zPos = Bar_ZPos[i];
Float_t yPos = Pole_Size_Y / 2. + Bar_Size_Y / 2.;
bar_trans = new TGeoTranslation("", xPos, yPos, zPos);
gGeoMan->GetVolume(geoVersion)->AddNode(gBar[i], numBars, bar_trans);
numBars++;
bar_trans = new TGeoTranslation("", xPos, -yPos, zPos);
gGeoMan->GetVolume(geoVersion)->AddNode(gBar[i], numBars, bar_trans);
numBars++;
bar_trans = new TGeoTranslation("", -xPos, yPos, zPos);
gGeoMan->GetVolume(geoVersion)->AddNode(gBar[i], numBars, bar_trans);
numBars++;
bar_trans = new TGeoTranslation("", -xPos, -yPos, zPos);
gGeoMan->GetVolume(geoVersion)->AddNode(gBar[i], numBars, bar_trans);
numBars++;
}
cout << " Position Bar " << numBars << " at z=" << Bar_ZPos[i] << endl;
// outer horizontal and vertical frame bars
NumberOfBars++;
i = NumberOfBars;
gBar[i] = create_tof_bar(Frame_XLen, Frame_Size_Y, Frame_Size_Y); // Outer frame big bar along X
j = i + 1;
gBar[j] = create_tof_bar(Frame_Size_X, Frame_YLen, Frame_Size_Y); // Outer frame big bar along Y
Float_t numBarY = 0;
numBars = 0;
for (Float_t dZ = -1.; dZ < 2.; dZ += 2.) {
Float_t zPos = Frame_Pos_Z - dZ * (Bar_Size_Z / 2. - 10.);
Float_t yPos = Frame_YLen / 2. + Frame_Size_Y / 2; // Make outer frame independent of the inner poles!!!!
// Outer Frame Top bar
bar_trans = new TGeoTranslation("", 0., yPos, zPos);
gGeoMan->GetVolume(geoVersion)->AddNode(gBar[i], numBars, bar_trans);
numBars++;
// Outer Frame Bottom bar
bar_trans = new TGeoTranslation("", 0., -yPos, zPos);
gGeoMan->GetVolume(geoVersion)->AddNode(gBar[i], numBars, bar_trans);
numBars++;
// Outer Frame Right bar
Float_t xPos = Frame_XLen / 2 - Frame_Size_Y / 2.;
bar_trans = new TGeoTranslation("", xPos, 0., zPos);
gGeoMan->GetVolume(geoVersion)->AddNode(gBar[j], numBarY, bar_trans);
numBarY++;
// Outer Frame Left bar
bar_trans = new TGeoTranslation("", -xPos, 0., zPos);
gGeoMan->GetVolume(geoVersion)->AddNode(gBar[j], numBarY, bar_trans);
numBarY++;
}
}
void position_tof_modules()
{
TGeoTranslation* module_trans = NULL;
TGeoRotation* module_rot0 = new TGeoRotation();
module_rot0->RotateZ(0.);
TGeoRotation* module_rot1 = new TGeoRotation();
module_rot1->RotateZ(180.);
TGeoCombiTrans* module_combi_trans = NULL;
// if(modType != 0) continue; // debugging
for (Int_t i = 0; i < MaxNofModules; i++) {
// for(Int_t i=0; i<5; i++) {
//if(i != 0) continue; // debugging
Float_t xPos = xPosMod[i];
Float_t yPos = yPosMod[i];
Float_t zPos = zPosMod[i] - 884.0 + TOF_Z_Front;
//cout<<"Place Mod Type "<<j<<" at x "<<xPos<<", y "<<yPos<<", z "<<zPos<<", Flip "<<FlipMod[j][i]<<endl;
module_trans = new TGeoTranslation("", xPos, yPos, zPos);
if (ModType[i] < 5 && xPosMod[i] < 0.0) { module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot1); }
else {
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot0);
}
cout << i << " ModType " << ModType[i] << " iMod: " << iMod[ModType[i]] << endl;
gGeoMan->GetVolume(geoVersion)->AddNode(gModules[ModType[i]], iMod[ModType[i]], module_combi_trans);
iMod[ModType[i]]++;
}
}
void dump_info_file()
{
TDatime datetime; // used to get timestamp
printf("writing info file: %s\n", FileNameInfo.Data());
FILE* ifile;
ifile = fopen(FileNameInfo.Data(), "w");
if (ifile == NULL) {
printf("error opening %s\n", FileNameInfo.Data());
exit(1);
}
fprintf(ifile, "#\n## %s information file\n#\n\n", geoVersion.Data());
fprintf(ifile, "# created %d\n\n", datetime.GetDate());
fprintf(ifile, "# TOF setup\n");
if (TOF_Z_Front == 450) fprintf(ifile, "SIS 100 hadron setup\n");
if (TOF_Z_Front == 600) fprintf(ifile, "SIS 100 electron\n");
if (TOF_Z_Front == 650) fprintf(ifile, "SIS 100 muon\n");
if (TOF_Z_Front == 880) fprintf(ifile, "SIS 300 electron\n");
if (TOF_Z_Front == 1020) fprintf(ifile, "SIS 300 muon\n");
fprintf(ifile, "\n");
const Float_t TOF_Z_Back = Wall_Z_Position + 176.5; // back of TOF wall
fprintf(ifile, "# envelope\n");
// Show extension of TRD
fprintf(ifile, "%7.2f cm start of TOF (z)\n", Wall_Z_Position - 10.);
fprintf(ifile, "%7.2f cm end of TOF (z)\n", TOF_Z_Back + 10.);
fprintf(ifile, "\n");
// Layer thickness
fprintf(ifile, "# central tower position\n");
fprintf(ifile, "%7.2f cm center of staggered, front RPC cell at x=0\n", Wall_Z_Position);
fprintf(ifile, "\n");
fclose(ifile);
}
# ModType X Y Z
1 3 -408.2 75.0 944.7
2 3 -423.2 51.0 957.7
3 3 -408.2 25.0 944.7
4 3 -423.2 0.0 957.7
5 3 -408.2 -25.0 944.7
6 3 -423.2 -51.0 957.7
7 3 -408.2 -75.0 944.7
8 3 -276.7 319.5 944.7
9 3 -286.7 298.2 957.7
10 3 -276.7 269.5 944.7
11 3 -286.7 247.7 957.7
12 3 -276.7 219.5 944.7
13 3 -286.7 197.2 957.7
14 3 -276.7 165.9 944.7
15 3 -286.7 146.7 957.7
16 3 -276.7 125.0 971.2
17 3 -286.7 102.0 984.2
18 3 -276.7 75.0 971.2
19 3 -286.7 51.0 984.2
20 3 -276.7 25.0 971.2
21 3 -286.7 0.0 984.2
22 3 -276.7 -25.0 971.2
23 3 -286.7 -51.0 984.2
24 3 -276.7 -75.0 971.2
25 3 -286.7 -102.0 984.2
26 3 -276.7 -125.0 971.2
27 3 -286.7 -146.7 957.7
28 3 -276.7 -165.9 944.7
29 3 -286.7 -197.2 957.7
30 3 -276.7 -219.5 944.7
31 3 -286.7 -247.7 957.7
32 3 -276.7 -269.5 944.7
33 3 -286.7 -298.2 957.7
34 3 -276.7 -319.5 944.7
35 3 -141.7 325.0 971.2
36 3 -146.7 303.8 984.2
37 3 -141.7 275.0 971.2
38 3 -146.7 253.3 984.2
39 3 -141.7 225.0 971.2
40 3 -146.7 202.8 984.2
41 3 -141.7 175.0 971.2
42 3 -146.7 152.3 984.2
43 3 -146.7 -152.3 984.2
44 3 -141.7 -175.0 971.2
45 3 -146.7 -202.8 984.2
46 3 -141.7 -225.0 971.2
47 3 -146.7 -253.3 984.2
48 3 -141.7 -275.0 971.2
49 3 -146.7 -303.8 984.2
50 3 -141.7 -325.0 971.2
51 4 0 325.5 1000.0
52 4 0 304.1 1013.0
53 4 0 275.5 1000.0
54 4 0 253.5 1013.0
55 4 0 225.5 1000.0
56 4 0 202.9 1013.0
57 4 0 175.5 1000.0
58 4 0 152.3 1013.0
59 4 0 -152.3 1013.0
60 4 0 -175.5 1000.0
61 4 0 -202.9 1013.0
62 4 0 -225.5 1000.0
63 4 0 -253.5 1013.0
64 4 0 -275.5 1000.0
65 4 0 -304.1 1013.0
66 4 0 -325.5 1000.0
67 3 141.7 325.0 971.2
68 3 146.7 303.8 984.2
69 3 141.7 275.0 971.2
70 3 146.7 253.3 984.2
71 3 141.7 225.0 971.2
72 3 146.7 202.8 984.2
73 3 141.7 175.0 971.2
74 3 146.7 152.3 984.2
75 3 146.7 -152.3 984.2
76 3 141.7 -175.0 971.2
77 3 146.7 -202.8 984.2
78 3 141.7 -225.0 971.2
79 3 146.7 -253.3 984.2
80 3 141.7 -275.0 971.2
81 3 146.7 -303.8 984.2
82 3 141.7 -325.0 971.2
83 3 276.7 319.5 944.7
84 3 286.7 298.2 957.7
85 3 276.7 269.5 944.7
86 3 286.7 247.7 957.7
87 3 276.7 219.5 944.7
88 3 286.7 197.2 957.7
89 3 276.7 165.9 944.7
90 3 286.7 146.7 957.7
91 3 276.7 125.0 971.2
92 3 286.7 102.0 984.2
93 3 276.7 75.0 971.2
94 3 286.7 51.0 984.2
95 3 276.7 25.0 971.2
96 3 286.7 0.0 984.2
97 3 276.7 -25.0 971.2
98 3 286.7 -51.0 984.2
99 3 276.7 -75.0 971.2
100 3 286.7 -102.0 984.2
101 3 276.7 -125.0 971.2
102 3 286.7 -146.7 957.7
103 3 276.7 -165.9 944.7
104 3 286.7 -197.2 957.7
105 3 276.7 -219.5 944.7
106 3 286.7 -247.7 957.7
107 3 276.7 -269.5 944.7
108 3 286.7 -298.2 957.7
109 3 276.7 -319.5 944.7
110 3 408.2 75.0 944.7
111 3 423.2 51.0 957.7
112 3 408.2 25.0 944.7
113 3 423.2 0.0 957.7
114 3 408.2 -25.0 944.7
115 3 423.2 -51.0 957.7
116 3 408.2 -75.0 944.7
117 5 -109.05 0.0 1011
118 6 -172.15 89.6 1050.4
119 7 -71.7 89.4 1030.7
120 8 0.0 89.4 1050.4
121 7 71.7 89.4 1030.7
122 9 172.15 89.6 1050.4
123 10 149.05 0.0 1011
124 11 172.15 -89.6 1050.4
125 12 71.7 -89.6 1030.7
126 13 0.0 -89.4 1050.4
127 12 -71.15 -87.85 1030.7
128 14 -172.15 -89.6 1050.4
/* Copyright (C) 2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Florian Uhlig [committer] */
///
/// \file Create_TOF_Geometry_v21k_mcbm.C
/// \brief Generates TOF geometry in Root format.
///
// clang-format off
// Changelog
//
// 2023-10-01 - v21k - ID - adjust to fit data
// 2022-11-03 - v21j - ID - Setup for Nickel and Goald run 2022
// 2022-05-07 - v21h - DE - shift v21g by x += 53.5 cm to align triple stack on z-axis
// 2022-04-10 - v21g - NH - setup for U-run, March 2022
// 2022-03-23 - v21f - DE - apply global rotation of TOF around target _after_ z-shift
// 2022-03-19 - v21f - ID - Setup for Iron run of March 22nd
// 2021-05-24 - v21n - NH - add M6 module
// 2020-04-14 - v20b - NH - swapped double stack layer 2 with STAR2 moodule, buc kept as dummy
// 2020-04-01 - v20a - NH - move mTOF +20 cm in x direction for the Mar 2020 run
// 2019-11-28 - v19b - DE - move mTOF +12 cm in x direction for the Nov 2019 run
// 2019-07-31 - v19a - DE - this TOF March 2019 geometry is also known as v18m
// 2017-11-03 - v18i - DE - shift mTOF to z=298 cm for acceptance matching with mSTS
// 2017-10-06 - v18h - DE - put v18f into vertical position to fit into the mCBM cave
// 2017-07-15 - v18g - DE - swap the z-position of TOF modules: 2 in the front, 3 in the back
// 2017-07-14 - v18f - DE - reduce vertical gap between TOF modules to fix the gap between modules 1-2 and 4-5
// 2017-05-17 - v18e - DE - rotate electronics away from beam, shift 16 cm away from beam along x-axis
// 2017-05-17 - v18d - DE - change geometry name to v18d
// in root all sizes are given in cm
#include "TFile.h"
#include "TGeoCompositeShape.h"
#include "TGeoManager.h"
#include "TGeoMaterial.h"
#include "TGeoMatrix.h"
#include "TGeoMedium.h"
#include "TGeoPgon.h"
#include "TGeoVolume.h"
#include "TList.h"
#include "TMath.h"
#include "TROOT.h"
#include "TString.h"
#include "TSystem.h"
#include <iostream>
// Name of geometry version and output file
const TString geoVersion = "tof_v21k_mcbm"; // do not change
const TString geoVersionStand = geoVersion + "Stand";
//
const TString fileTag = "tof_v21k";
const TString FileNameSim = fileTag + "_mcbm.geo.root?reproducible";
const TString FileNameGeo = fileTag + "_mcbm_geo.root?reproducible";
const TString FileNameInfo = fileTag + "_mcbm.geo.info";
// TOF_Z_Front corresponds to front cover of outer super module towers
const Float_t TOF_Z_Front_Stand = 233.1; // = z=298 mCBM@SIS18
const Float_t TOF_X_Front_Stand = 0.33; //
const Float_t TOF_Y_Front_Stand = 0.1; //
const Float_t TOF_Z_Front = 0.; //
//const Float_t TOF_Z_Front = 130; // = z=225 mCBM@SIS18
//const Float_t TOF_Z_Front = 250; // SIS 100 hadron
//const Float_t TOF_Z_Front = 450; // SIS 100 hadron
//const Float_t TOF_Z_Front = 600; // SIS 100 electron
//const Float_t TOF_Z_Front = 650; // SIS 100 muon
//const Float_t TOF_Z_Front = 880; // SIS 300 electron
//const Float_t TOF_Z_Front = 1020; // SIS 300 muon
//
//const Float_t TOF_Z_Front = 951.5; // Wall_Z_Position = 1050 cm
// Names of the different used materials which are used to build the modules
// The materials are defined in the global media.geo file
const TString KeepingVolumeMedium = "air";
const TString BoxVolumeMedium = "aluminium";
const TString NoActivGasMedium = "RPCgas_noact";
const TString ActivGasMedium = "RPCgas";
const TString GlasMedium = "RPCglass";
const TString ElectronicsMedium = "carbon";
// Counters:
// 0 MRPC3a
// 1 MRPC3b
// 2 USTC
// 3
// 4 Diamond
//
// 6 Buc 2019
// 7 CERN 20gap
// 8 Ceramic Pad
const Int_t NumberOfDifferentCounterTypes = 9;
const Float_t Glass_X[NumberOfDifferentCounterTypes] = {32., 32., 32., 32., 0.2, 32., 28.8, 20., 2.4};
const Float_t Glass_Y[NumberOfDifferentCounterTypes] = {27.0, 53., 26.8, 10., 0.2, 10., 6., 20., 2.4};
const Float_t Glass_Z[NumberOfDifferentCounterTypes] = {0.1, 0.1, 0.1, 0.1, 0.01, 0.1, 0.1, 0.1, 0.1};
const Float_t GasGap_X[NumberOfDifferentCounterTypes] = {32., 32., 32., 32., 0.2, 32., 28.8, 20., 2.4};
const Float_t GasGap_Y[NumberOfDifferentCounterTypes] = {27.0, 53., 26.8, 10., 0.2, 10., 6., 20., 2.4};
const Float_t GasGap_Z[NumberOfDifferentCounterTypes] = {0.025, 0.025, 0.025, 0.025, 0.01, 0.02, 0.02, 0.02, 0.025};
const Int_t NumberOfGaps[NumberOfDifferentCounterTypes] = {8, 8, 8, 8, 1, 8, 10, 20, 4};
//const Int_t NumberOfGaps[NumberOfDifferentCounterTypes] = {1,1,1,1}; //deb
const Int_t NumberOfReadoutStrips[NumberOfDifferentCounterTypes] = {32, 32, 32, 32, 16, 32, 32, 20, 1};
//const Int_t NumberOfReadoutStrips[NumberOfDifferentCounterTypes] = {1,1,1,1}; //deb
const Float_t SingleStackStartPosition_Z[NumberOfDifferentCounterTypes] = {-0.6, -0.6, -0.6, -0.6, -0.1,
-0.6, -0.6, -0.6, -1.};
const Float_t Electronics_X[NumberOfDifferentCounterTypes] = {32.0, 32.0, 32.0, 32., 0.3, 0.1, 28.8, 20., 0.1};
const Float_t Electronics_Y[NumberOfDifferentCounterTypes] = {5.0, 5.0, 1.0, 1., 0.1, 0.1, 1.0, 1.0, 0.1};
const Float_t Electronics_Z[NumberOfDifferentCounterTypes] = {0.3, 0.3, 0.3, 0.3, 0.1, 0.1, 0.1, 0.1, 0.1};
const Int_t NofModuleTypes = 10;
// 0 M4 (TSHU)
// 1 M4 (USTC)
// 2 M6 (USTC)
// 5 Diamond
// 6 Buc
// 7 Testbox MRPC4
// 8 Ceramic
// 9 Star2
// Aluminum box for all module types
const Float_t Module_Size_X[NofModuleTypes] = {180., 180., 180., 180., 180., 5., 40., 100., 10., 100.};
const Float_t Module_Size_Y[NofModuleTypes] = {49., 49., 74., 28., 18., 5., 15., 49., 10., 49.};
const Float_t Module_Over_Y[NofModuleTypes] = {11.5, 11.5, 11., 4.5, 4.5, 0., 0., 0., 0., 0.};
const Float_t Module_Size_Z[NofModuleTypes] = {11., 11., 13., 11., 11., 1., 12., 11., 1., 11.2};
const Float_t Module_Thick_Alu_X_left = 0.1;
const Float_t Module_Thick_Alu_X_right = 1.0;
const Float_t Module_Thick_Alu_Y = 0.1;
const Float_t Module_Thick_Alu_Z = 0.1;
// Distance to the center of the TOF wall [cm];
const Float_t Wall_Z_Position = 400.;
const Float_t MeanTheta = 0.;
//Type of Counter for module
const Int_t CounterTypeInModule[NofModuleTypes] = {0, 0, 1, 2, 3, 4, 6, 1, 8, 2};
const Int_t NCounterInModule[NofModuleTypes] = {5, 5, 5, 5, 5, 1, 2, 2, 1, 2};
// Placement of the counter inside the module
const Float_t CounterXStartPosition[NofModuleTypes] = {-60., -66.0, -61.1, -60.0, -60.0, 0.0, 0., 0., 0., 0.};
const Float_t CounterXDistance[NofModuleTypes] = { 30., 32.0, 30.45, 30.0, 30.0, 0.0, 0., 0., 0., 0.};
const Float_t CounterYStartPosition[NofModuleTypes] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0., 0., 0., 0., 0.};
const Float_t CounterYDistance[NofModuleTypes] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0., 0., 0., 0., 0.};
const Float_t CounterZDistance[NofModuleTypes] = { -2.5, 0.0, 0.0, 2.5, 2.5, 0., 6., 4., 0.1, 4.};
const Float_t CounterZStartPosition[NofModuleTypes] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0., -3., -2., 0.0,-2.};
const Float_t CounterRotationAngle[NofModuleTypes] = { 0., 8.7, -7.0, 0., 0., 0., 0., 0., 0., 0.};
const Float_t CounterRotationAngleZ[NofModuleTypes] = { 0., 0., 0.0, 0., 0., 0., 0., 90., 0., 0.};
// clang-format on
// Pole (support structure)
const Int_t MaxNumberOfPoles = 20;
Float_t Pole_ZPos[MaxNumberOfPoles];
Float_t Pole_Col[MaxNumberOfPoles];
Int_t NumberOfPoles = 0;
const Float_t Pole_Size_X = 20.;
const Float_t Pole_Size_Y = 300.;
const Float_t Pole_Size_Z = 10.;
const Float_t Pole_Thick_X = 5.;
const Float_t Pole_Thick_Y = 5.;
const Float_t Pole_Thick_Z = 5.;
// Bars (support structure)
const Float_t Bar_Size_X = 20.;
const Float_t Bar_Size_Y = 20.;
Float_t Bar_Size_Z = 100.;
const Int_t MaxNumberOfBars = 20;
Float_t Bar_ZPos[MaxNumberOfBars];
Float_t Bar_XPos[MaxNumberOfBars];
Int_t NumberOfBars = 0;
const Float_t ChamberOverlap = 40;
const Float_t DxColl = 158.0; //Module_Size_X-ChamberOverlap;
//const Float_t Pole_Offset=Module_Size_X/2.+Pole_Size_X/2.;
const Float_t Pole_Offset = 90.0 + Pole_Size_X / 2.;
// Position for module placement
const Float_t Inner_Module_First_Y_Position = 16.;
const Float_t Inner_Module_Last_Y_Position = 480.;
const Float_t Inner_Module_X_Offset = 0.; // centered position in x/y
//const Float_t Inner_Module_X_Offset=18; // shift by 16 cm in x
const Int_t Inner_Module_NTypes = 3;
const Float_t Inner_Module_Types[Inner_Module_NTypes] = {4., 3., 0.};
//const Float_t Inner_Module_Number[Inner_Module_NTypes] = {2.,2.,6.}; //V13_3a
const Float_t Inner_Module_Number[Inner_Module_NTypes] = {2., 2., 1.}; //V13_3a
//const Float_t Inner_Module_Number[Inner_Module_NTypes] = {0.,0.,0.}; //debugging
const Float_t InnerSide_Module_X_Offset = 51.;
const Float_t InnerSide_Module_NTypes = 1;
const Float_t InnerSide_Module_Types[Inner_Module_NTypes] = {5.};
const Float_t InnerSide_Module_Number[Inner_Module_NTypes] = {2.}; //v13_3a
//const Float_t InnerSide_Module_Number[Inner_Module_NTypes] = {0.}; //debug
const Float_t Outer_Module_First_Y_Position = 0.;
const Float_t Outer_Module_Last_Y_Position = 480.;
const Float_t Outer_Module_X_Offset = 3.;
const Int_t Outer_Module_Col = 4;
const Int_t Outer_Module_NTypes = 2;
const Float_t Outer_Module_Types[Outer_Module_NTypes][Outer_Module_Col] = {1., 1., 1., 1., 2., 2., 2., 2.};
const Float_t Outer_Module_Number[Outer_Module_NTypes][Outer_Module_Col] = {9., 9., 2., 0., 0., 0., 3., 4.}; //V13_3a
//const Float_t Outer_Module_Number[Outer_Module_NTypes][Outer_Module_Col] = {1.,1.,0.,0., 0.,0.,0.,0.};//debug
const Float_t Star2_First_Z_Position = TOF_Z_Front + 15.9 + 16.1;
const Float_t Star2_Delta_Z_Position = 16.3;
const Float_t Star2_First_Y_Position = 30.34; //
const Float_t Star2_Delta_Y_Position = 0.; //
const Int_t Star2_NTypes = 1;
const Float_t Star2_rotate_Z[Star2_NTypes] = {-90.};
const Float_t Star2_Types[Star2_NTypes] = {9.};
const Float_t Star2_Number[Star2_NTypes] = {1.}; //debugging, V16b
const Float_t Star2_X_Offset[Star2_NTypes] = {49.75};
const Float_t Buc_First_Z_Position = TOF_Z_Front + 16.5 + 4.; //put 600 to position of 601
const Float_t Buc_Delta_Z_Position = 0.;
const Float_t Buc_First_Y_Position = -29.1; //
const Float_t Buc_Delta_Y_Position = 0.; //
const Float_t Buc_rotate_Y = 180.;
const Float_t Buc_rotate_Z = 0.;
const Int_t Buc_NTypes = 1;
const Float_t Buc_Types[Buc_NTypes] = {6.};
const Float_t Buc_Number[Buc_NTypes] = {1.}; //debugging, V16b
const Float_t Buc_X_Offset[Buc_NTypes] = {47.85};
const Int_t Cer_NTypes = 2;
const Float_t Cer_Z_Position[Cer_NTypes] = {(float) (TOF_Z_Front + 46.), (float) (TOF_Z_Front + 47.1)};
const Float_t Cer_X_Position[Cer_NTypes] = {1., 1.};
const Float_t Cer_Y_Position[Cer_NTypes] = {-29., -29.};
const Float_t Cer_rotate_Z[Cer_NTypes] = {0., 0.};
const Float_t Cer_Types[Cer_NTypes] = {8., 8.};
const Float_t Cer_Number[Cer_NTypes] = {1., 1.};
const Float_t Testbox_MRPC4_Z_Position = TOF_Z_Front + 15.9; //
const Float_t Testbox_MRPC4_First_Y_Position = 32.70;
const Float_t Testbox_MRPC4_X_Offset = 50.17; //65.5;
const Float_t Testbox_MRPC4_rotate_Z = -90.;
const Int_t Testbox_MRPC4_NTypes = 1;
const Float_t Testbox_MRPC4_Types[Testbox_MRPC4_NTypes] = {7.}; // this is the SmType!
const Float_t Testbox_MRPC4_Number[Testbox_MRPC4_NTypes] = {1.}; // evtl. double for split signals
// some global variables
TGeoManager* gGeoMan = NULL; // Pointer to TGeoManager instance
TGeoVolume* gModules[NofModuleTypes]; // Global storage for module types
TGeoVolume* gCounter[NumberOfDifferentCounterTypes];
TGeoVolume* gPole;
TGeoVolume* gBar[MaxNumberOfBars];
const Float_t Dia_Z_Position = -0.2 - TOF_Z_Front_Stand;
const Float_t Dia_First_Y_Position = 0.; //- TOF_Y_Front_Stand;
const Float_t Dia_X_Offset = 3.5; // - TOF_X_Front_Stand;
const Float_t Dia_rotate_Z = 0.;
const Int_t Dia_NTypes = 1;
const Float_t Dia_Types[Dia_NTypes] = {5.};
const Float_t Dia_Number[Dia_NTypes] = {1.};
Float_t Last_Size_Y = 0.;
Float_t Last_Over_Y = 0.;
// Forward declarations
void create_materials_from_media_file();
TGeoVolume* create_counter(Int_t);
TGeoVolume* create_new_counter(Int_t);
TGeoVolume* create_tof_module(Int_t);
TGeoVolume* create_new_tof_module(Int_t);
TGeoVolume* create_tof_pole();
TGeoVolume* create_tof_bar();
void position_tof_poles(Int_t);
void position_tof_bars(Int_t);
void position_inner_tof_modules(Int_t);
void position_side_tof_modules(Int_t);
void position_outer_tof_modules(Int_t);
void position_Dia(Int_t);
void position_Star2(Int_t);
void position_Buc(Int_t);
void position_cer_modules(Int_t);
void position_Testbox_MRPC4(Int_t);
void dump_info_file();
void Create_TOF_Geometry_v21k_mcbm()
{
// Load FairRunSim to ensure the correct unit system
FairRunSim* sim = new FairRunSim();
// Load needed material definition from media.geo file
create_materials_from_media_file();
// Get the GeoManager for later usage
gGeoMan = (TGeoManager*) gROOT->FindObject("FAIRGeom");
gGeoMan->SetVisLevel(5); // 2 = super modules
gGeoMan->SetVisOption(0);
// Create the top volume
/*
TGeoBBox* topbox= new TGeoBBox("", 1000., 1000., 1000.);
TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air"));
gGeoMan->SetTopVolume(top);
*/
TGeoVolume* top = new TGeoVolumeAssembly("TOP");
gGeoMan->SetTopVolume(top);
TGeoRotation* tof_rotation = new TGeoRotation();
tof_rotation->RotateY(0.); // angle with respect to beam axis
// tof_rotation->RotateZ( 0 ); // electronics on 9 o'clock position = +x
// tof_rotation->RotateZ( 0 ); // electronics on 9 o'clock position = +x
// tof_rotation->RotateZ( 90 ); // electronics on 12 o'clock position (top)
// tof_rotation->RotateZ( 180 ); // electronics on 3 o'clock position = -x
// tof_rotation->RotateZ( 270 ); // electronics on 6 o'clock position (bottom)
TGeoVolume* tof = new TGeoVolumeAssembly(geoVersion);
top->AddNode(tof, 1, tof_rotation);
//top->AddNode(tof, -2.); // ??
TGeoVolume* tofstand = new TGeoVolumeAssembly(geoVersionStand);
// Mar 2020 run
TGeoTranslation* stand_trans_local = new TGeoTranslation("", TOF_X_Front_Stand, TOF_Y_Front_Stand, 0.);
TGeoTranslation* stand_trans = new TGeoTranslation("", 0., 0., TOF_Z_Front_Stand);
TGeoCombiTrans* stand_combi_trans = new TGeoCombiTrans(*stand_trans, *tof_rotation);
TGeoRotation* stand_rot = new TGeoRotation();
//stand_rot->RotateY(0.);
stand_rot->RotateY(0.97);
TGeoCombiTrans* stand_combi_trans_local = new TGeoCombiTrans(*stand_trans_local, *stand_rot);
//tof->AddNode(tofstand, 1, stand_combi_trans);
tof->AddNode(tofstand, 1, stand_combi_trans_local);
//tof->AddNode(tofstand, 1);
for (Int_t counterType = 0; counterType < NumberOfDifferentCounterTypes; counterType++) {
gCounter[counterType] = create_new_counter(counterType);
}
for (Int_t moduleType = 0; moduleType < NofModuleTypes; moduleType++) {
gModules[moduleType] = create_new_tof_module(moduleType);
gModules[moduleType]->SetVisContainers(1);
}
// no pole
// gPole = create_tof_pole();
// position_side_tof_modules(1); // keep order !!
// position_inner_tof_modules(2);
position_inner_tof_modules(3);
position_Dia(1);
position_Star2(1);
// position_cer_modules(2);
position_Testbox_MRPC4(1);
position_Buc(1);
cout << "Outer Types " << Outer_Module_Types[0][0] << ", " << Outer_Module_Types[1][0]
<< ", col=1: " << Outer_Module_Types[0][1] << ", " << Outer_Module_Types[1][1] << endl;
cout << "Outer Number " << Outer_Module_Number[0][0] << ", " << Outer_Module_Number[1][0]
<< ", col=1: " << Outer_Module_Number[0][1] << ", " << Outer_Module_Number[1][1] << endl;
// position_outer_tof_modules(4);
// position_tof_poles(0);
// position_tof_bars(0);
gGeoMan->CloseGeometry();
gGeoMan->CheckOverlaps(0.001);
gGeoMan->PrintOverlaps();
gGeoMan->CheckOverlaps(0.001, "s");
gGeoMan->PrintOverlaps();
gGeoMan->Test();
tof->Export(FileNameSim);
TFile* geoFile = new TFile(FileNameSim, "UPDATE");
stand_combi_trans->Write();
geoFile->Close();
// create medialist for this geometry
TString createmedialist = gSystem->Getenv("VMCWORKDIR");
createmedialist += "/macro/geometry/create_medialist.C";
std::cout << "Loading macro " << createmedialist << std::endl;
gROOT->LoadMacro(createmedialist);
gROOT->ProcessLine("create_medialist(\"\", false)");
/*
TFile* outfile1 = new TFile(FileNameSim,"RECREATE");
top->Write();
//gGeoMan->Write();
outfile1->Close();
*/
//tof->RemoveNode((TGeoNode*)tofstand);
//top->AddNode(tof, 1, tof_rotation);
//tof->ReplaceNode((TGeoNode*)tofstand, 0, stand_combi_trans);
/*
CbmTransport run;
run.SetGeoFileName(FileNameGeo);
run.LoadSetup("setup_mcbm_tof_2020");
run.SetField(new CbmFieldConst());
*/
//top->Export(FileNameGeo);
TFile* outfile2 = new TFile(FileNameGeo, "RECREATE");
gGeoMan->Write();
outfile2->Close();
dump_info_file();
top->SetVisContainers(1);
gGeoMan->SetVisLevel(5);
top->Draw("ogl");
//top->Draw();
//gModules[0]->Draw("ogl");
// gModules[0]->Draw("");
gModules[0]->SetVisContainers(1);
// gModules[1]->Draw("");
gModules[1]->SetVisContainers(1);
//gModules[5]->Draw("");
// top->Raytrace();
}
void create_materials_from_media_file()
{
// Use the FairRoot geometry interface to load the media which are already defined
FairGeoLoader* geoLoad = new FairGeoLoader("TGeo", "FairGeoLoader");
FairGeoInterface* geoFace = geoLoad->getGeoInterface();
TString geoPath = gSystem->Getenv("VMCWORKDIR");
TString geoFile = geoPath + "/geometry/media.geo";
geoFace->setMediaFile(geoFile);
geoFace->readMedia();
// Read the required media and create them in the GeoManager
FairGeoMedia* geoMedia = geoFace->getMedia();
FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder();
FairGeoMedium* air = geoMedia->getMedium("air");
FairGeoMedium* aluminium = geoMedia->getMedium("aluminium");
FairGeoMedium* RPCgas = geoMedia->getMedium("RPCgas");
FairGeoMedium* RPCgas_noact = geoMedia->getMedium("RPCgas_noact");
FairGeoMedium* RPCglass = geoMedia->getMedium("RPCglass");
FairGeoMedium* carbon = geoMedia->getMedium("carbon");
// include check if all media are found
geoBuild->createMedium(air);
geoBuild->createMedium(aluminium);
geoBuild->createMedium(RPCgas);
geoBuild->createMedium(RPCgas_noact);
geoBuild->createMedium(RPCglass);
geoBuild->createMedium(carbon);
}
TGeoVolume* create_counter(Int_t modType)
{
//glass
Float_t gdx = Glass_X[modType];
Float_t gdy = Glass_Y[modType];
Float_t gdz = Glass_Z[modType];
//gas gap
Int_t nstrips = NumberOfReadoutStrips[modType];
Int_t ngaps = NumberOfGaps[modType];
Float_t ggdx = GasGap_X[modType];
Float_t ggdy = GasGap_Y[modType];
Float_t ggdz = GasGap_Z[modType];
Float_t gsdx = ggdx / float(nstrips);
//single stack
Float_t dzpos = gdz + ggdz;
Float_t startzpos = SingleStackStartPosition_Z[modType];
// electronics
//pcb dimensions
Float_t dxe = Electronics_X[modType];
Float_t dye = Electronics_Y[modType];
Float_t dze = Electronics_Z[modType];
Float_t yele = (gdy + 0.1) / 2. + dye / 2.;
// needed materials
TGeoMedium* glassPlateVolMed = gGeoMan->GetMedium(GlasMedium);
TGeoMedium* noActiveGasVolMed = gGeoMan->GetMedium(NoActivGasMedium);
TGeoMedium* activeGasVolMed = gGeoMan->GetMedium(ActivGasMedium);
TGeoMedium* electronicsVolMed = gGeoMan->GetMedium(ElectronicsMedium);
// Single glass plate
TGeoBBox* glass_plate = new TGeoBBox("", gdx / 2., gdy / 2., gdz / 2.);
TGeoVolume* glass_plate_vol = new TGeoVolume("tof_glass", glass_plate, glassPlateVolMed);
glass_plate_vol->SetLineColor(kMagenta); // set line color for the glass plate
glass_plate_vol->SetTransparency(20); // set transparency for the TOF
TGeoTranslation* glass_plate_trans = new TGeoTranslation("", 0., 0., 0.);
// Single gas gap
TGeoBBox* gas_gap = new TGeoBBox("", ggdx / 2., ggdy / 2., ggdz / 2.);
//TGeoVolume* gas_gap_vol =
//new TGeoVolume("tof_gas_gap", gas_gap, noActiveGasVolMed);
TGeoVolume* gas_gap_vol = new TGeoVolume("tof_gas_active", gas_gap, activeGasVolMed);
gas_gap_vol->Divide("Strip", 1, nstrips, -ggdx / 2., 0);
gas_gap_vol->SetLineColor(kRed); // set line color for the gas gap
gas_gap_vol->SetTransparency(70); // set transparency for the TOF
TGeoTranslation* gas_gap_trans = new TGeoTranslation("", 0., 0., (gdz + ggdz) / 2.);
// Single subdivided active gas gap
/*
TGeoBBox* gas_active = new TGeoBBox("", gsdx/2., ggdy/2., ggdz/2.);
TGeoVolume* gas_active_vol =
new TGeoVolume("tof_gas_active", gas_active, activeGasVolMed);
gas_active_vol->SetLineColor(kBlack); // set line color for the gas gap
gas_active_vol->SetTransparency(70); // set transparency for the TOF
*/
// Add glass plate, inactive gas gap and active gas gaps to a single stack
TGeoVolume* single_stack = new TGeoVolumeAssembly("single_stack");
single_stack->AddNode(glass_plate_vol, 0, glass_plate_trans);
single_stack->AddNode(gas_gap_vol, 0, gas_gap_trans);
/*
for (Int_t l=0; l<nstrips; l++){
TGeoTranslation* gas_active_trans
= new TGeoTranslation("", -ggdx/2+(l+0.5)*gsdx, 0., 0.);
gas_gap_vol->AddNode(gas_active_vol, l, gas_active_trans);
// single_stack->AddNode(gas_active_vol, l, gas_active_trans);
}
*/
// Add 8 single stacks + one glass plate at the e09.750nd to a multi stack
TGeoVolume* multi_stack = new TGeoVolumeAssembly("multi_stack");
Int_t l;
for (l = 0; l < ngaps; l++) {
TGeoTranslation* single_stack_trans = new TGeoTranslation("", 0., 0., startzpos + l * dzpos);
multi_stack->AddNode(single_stack, l, single_stack_trans);
}
TGeoTranslation* single_glass_back_trans = new TGeoTranslation("", 0., 0., startzpos + ngaps * dzpos);
multi_stack->AddNode(glass_plate_vol, l, single_glass_back_trans);
// Add electronics above and below the glass stack to build a complete counter
TGeoVolume* counter = new TGeoVolumeAssembly("counter");
TGeoTranslation* multi_stack_trans = new TGeoTranslation("", 0., 0., 0.);
counter->AddNode(multi_stack, l, multi_stack_trans);
TGeoBBox* pcb = new TGeoBBox("", dxe / 2., dye / 2., dze / 2.);
TGeoVolume* pcb_vol = new TGeoVolume("pcb", pcb, electronicsVolMed);
pcb_vol->SetLineColor(kCyan); // set line color for the gas gap
pcb_vol->SetTransparency(10); // set transparency for the TOF
for (Int_t l = 0; l < 2; l++) {
yele *= -1.;
TGeoTranslation* pcb_trans = new TGeoTranslation("", 0., yele, 0.);
counter->AddNode(pcb_vol, l, pcb_trans);
}
return counter;
}
TGeoVolume* create_new_counter(Int_t modType)
{
//glass
Float_t gdx = Glass_X[modType];
Float_t gdy = Glass_Y[modType];
Float_t gdz = Glass_Z[modType];
//gas gap
Int_t nstrips = NumberOfReadoutStrips[modType];
Int_t ngaps = NumberOfGaps[modType];
Float_t ggdx = GasGap_X[modType];
Float_t ggdy = GasGap_Y[modType];
Float_t ggdz = GasGap_Z[modType];
Float_t gsdx = ggdx / (Float_t)(nstrips);
// electronics
//pcb dimensions
Float_t dxe = Electronics_X[modType];
Float_t dye = Electronics_Y[modType];
Float_t dze = Electronics_Z[modType];
Float_t yele = gdy / 2. + dye / 2.;
// counter size (calculate from glas, gap and electronics sizes)
Float_t cdx = TMath::Max(gdx, ggdx);
cdx = TMath::Max(cdx, dxe) + 0.2;
Float_t cdy = TMath::Max(gdy, ggdy) + 2 * dye + 0.2;
Float_t cdz = ngaps * ggdz + (ngaps + 1) * gdz + 0.2; // ngaps * (gdz+ggdz) + gdz + 0.2; // ok
//calculate thickness and first position in counter of single stack
Float_t dzpos = gdz + ggdz;
Float_t startzposglas = -ngaps * (gdz + ggdz) / 2.; // -cdz/2.+0.1+gdz/2.; // ok // (-cdz+gdz)/2.; // not ok
Float_t startzposgas = startzposglas + gdz / 2. + ggdz / 2.; // -cdz/2.+0.1+gdz +ggdz/2.; // ok
// needed materials
TGeoMedium* glassPlateVolMed = gGeoMan->GetMedium(GlasMedium);
TGeoMedium* noActiveGasVolMed = gGeoMan->GetMedium(NoActivGasMedium);
TGeoMedium* activeGasVolMed = gGeoMan->GetMedium(ActivGasMedium);
TGeoMedium* electronicsVolMed = gGeoMan->GetMedium(ElectronicsMedium);
// define counter volume
TGeoBBox* counter_box = new TGeoBBox("", cdx / 2., cdy / 2., cdz / 2.);
TGeoVolume* counter = new TGeoVolume("counter", counter_box, noActiveGasVolMed);
counter->SetLineColor(kRed); // set line color for the counter
counter->SetTransparency(70); // set transparency for the TOF
// define single glass plate volume
TGeoBBox* glass_plate = new TGeoBBox("", gdx / 2., gdy / 2., gdz / 2.);
TGeoVolume* glass_plate_vol = new TGeoVolume("tof_glass", glass_plate, glassPlateVolMed);
glass_plate_vol->SetLineColor(kMagenta); // set line color for the glass plate
glass_plate_vol->SetTransparency(20); // set transparency for the TOF
// define single gas gap volume
TGeoBBox* gas_gap = new TGeoBBox("", ggdx / 2., ggdy / 2., ggdz / 2.);
TGeoVolume* gas_gap_vol = new TGeoVolume("Gap", gas_gap, activeGasVolMed);
gas_gap_vol->Divide("Cell", 1, nstrips, -ggdx / 2., 0);
gas_gap_vol->SetLineColor(kRed); // set line color for the gas gap
gas_gap_vol->SetTransparency(99); // set transparency for the TOF
// place 8 gas gaps and 9 glas plates in the counter
for (Int_t igap = 0; igap <= ngaps; igap++) {
// place (ngaps+1) glass plates
Float_t zpos_glas = startzposglas + igap * dzpos;
TGeoTranslation* glass_plate_trans = new TGeoTranslation("", 0., 0., zpos_glas);
counter->AddNode(glass_plate_vol, igap, glass_plate_trans);
// place ngaps gas gaps
if (igap < ngaps) {
Float_t zpos_gas = startzposgas + igap * dzpos;
TGeoTranslation* gas_gap_trans = new TGeoTranslation("", 0., 0., zpos_gas);
counter->AddNode(gas_gap_vol, igap, gas_gap_trans);
}
// cout <<"Zpos(Glas): "<< zpos_glas << endl;
// cout <<"Zpos(Gas): "<< zpos_gas << endl;
}
// create and place the electronics above and below the glas stack
TGeoBBox* pcb = new TGeoBBox("", dxe / 2., dye / 2., dze / 2.);
TGeoVolume* pcb_vol = new TGeoVolume("pcb", pcb, electronicsVolMed);
pcb_vol->SetLineColor(kYellow); // kCyan); // set line color for electronics
pcb_vol->SetTransparency(10); // set transparency for the TOF
for (Int_t l = 0; l < 2; l++) {
yele *= -1.;
TGeoTranslation* pcb_trans = new TGeoTranslation("", 0., yele, 0.);
counter->AddNode(pcb_vol, l, pcb_trans);
}
return counter;
}
TGeoVolume* create_tof_module(Int_t modType)
{
Int_t cType = CounterTypeInModule[modType];
Float_t dx = Module_Size_X[modType];
Float_t dy = Module_Size_Y[modType];
Float_t dz = Module_Size_Z[modType];
Float_t width_aluxl = Module_Thick_Alu_X_left;
Float_t width_aluxr = Module_Thick_Alu_X_right;
Float_t width_aluy = Module_Thick_Alu_Y;
Float_t width_aluz = Module_Thick_Alu_Z;
Float_t shift_gas_box = (Module_Thick_Alu_X_right - Module_Thick_Alu_X_left) / 2;
Float_t dxpos = CounterXDistance[modType];
Float_t startxpos = CounterXStartPosition[modType];
Float_t dzoff = CounterZDistance[modType];
Float_t rotangle = CounterRotationAngle[modType];
TGeoMedium* boxVolMed = gGeoMan->GetMedium(BoxVolumeMedium);
TGeoMedium* noActiveGasVolMed = gGeoMan->GetMedium(NoActivGasMedium);
TString moduleName = Form("module_%d", modType);
TGeoVolume* module = new TGeoVolumeAssembly(moduleName);
TGeoBBox* alu_box = new TGeoBBox("", dx / 2., dy / 2., dz / 2.);
TGeoVolume* alu_box_vol = new TGeoVolume("alu_box", alu_box, boxVolMed);
alu_box_vol->SetLineColor(kGreen); // set line color for the alu box
alu_box_vol->SetTransparency(20); // set transparency for the TOF
TGeoTranslation* alu_box_trans = new TGeoTranslation("", 0., 0., 0.);
module->AddNode(alu_box_vol, 0, alu_box_trans);
TGeoBBox* gas_box =
new TGeoBBox("", (dx - (width_aluxl + width_aluxr)) / 2., (dy - 2 * width_aluy) / 2., (dz - 2 * width_aluz) / 2.);
TGeoVolume* gas_box_vol = new TGeoVolume("gas_box", gas_box, noActiveGasVolMed);
gas_box_vol->SetLineColor(kYellow); // set line color for the gas box
gas_box_vol->SetTransparency(70); // set transparency for the TOF
TGeoTranslation* gas_box_trans = new TGeoTranslation("", shift_gas_box, 0., 0.);
alu_box_vol->AddNode(gas_box_vol, 0, gas_box_trans);
for (Int_t j = 0; j < 5; j++) { //loop over counters (modules)
Float_t zpos;
if (0 == modType) { zpos = dzoff *= -1; }
else {
zpos = 0.;
}
//cout << "counter z position " << zpos << endl;
TGeoTranslation* counter_trans = new TGeoTranslation("", startxpos + j * dxpos, 0.0, zpos);
TGeoRotation* counter_rot = new TGeoRotation();
counter_rot->RotateY(rotangle);
TGeoCombiTrans* counter_combi_trans = new TGeoCombiTrans(*counter_trans, *counter_rot);
gas_box_vol->AddNode(gCounter[cType], j, counter_combi_trans);
}
return module;
}
TGeoVolume* create_new_tof_module(Int_t modType)
{
Int_t cType = CounterTypeInModule[modType];
Float_t dx = Module_Size_X[modType];
Float_t dy = Module_Size_Y[modType];
Float_t dz = Module_Size_Z[modType];
Float_t width_aluxl = Module_Thick_Alu_X_left;
Float_t width_aluxr = Module_Thick_Alu_X_right;
Float_t width_aluy = Module_Thick_Alu_Y;
Float_t width_aluz = Module_Thick_Alu_Z;
Float_t shift_gas_box = (Module_Thick_Alu_X_right - Module_Thick_Alu_X_left) / 2;
Float_t dxpos = CounterXDistance[modType];
Float_t startxpos = CounterXStartPosition[modType];
Float_t dypos = CounterYDistance[modType];
Float_t startypos = CounterYStartPosition[modType];
Float_t dzoff = CounterZDistance[modType];
Float_t rotangle = CounterRotationAngle[modType];
TGeoMedium* boxVolMed = gGeoMan->GetMedium(BoxVolumeMedium);
TGeoMedium* noActiveGasVolMed = gGeoMan->GetMedium(NoActivGasMedium);
TString moduleName = Form("module_%d", modType);
TGeoBBox* module_box = new TGeoBBox("", dx / 2., dy / 2., dz / 2.);
TGeoVolume* module = new TGeoVolume(moduleName, module_box, boxVolMed);
module->SetLineColor(kGreen); // set line color for the alu box
module->SetTransparency(20); // set transparency for the TOF
TGeoBBox* gas_box =
new TGeoBBox("", (dx - (width_aluxl + width_aluxr)) / 2., (dy - 2 * width_aluy) / 2., (dz - 2 * width_aluz) / 2.);
TGeoVolume* gas_box_vol = new TGeoVolume("gas_box", gas_box, noActiveGasVolMed);
gas_box_vol->SetLineColor(kBlue); // set line color for the alu box
gas_box_vol->SetTransparency(50); // set transparency for the TOF
TGeoTranslation* gas_box_trans = new TGeoTranslation("", shift_gas_box, 0., 0.);
module->AddNode(gas_box_vol, 0, gas_box_trans);
for (Int_t j = 0; j < NCounterInModule[modType]; j++) { //loop over counters (modules)
//for (Int_t j=0; j< 1; j++){ //loop over counters (modules)
Float_t xpos, ypos, zpos;
if (0 == modType || 3 == modType || 4 == modType || 5 == modType) { zpos = dzoff *= -1; }
else {
zpos = CounterZStartPosition[modType] + j * dzoff;
}
//cout << "counter z position " << zpos << endl;
xpos = startxpos + j * dxpos;
ypos = startypos + j * dypos;
TGeoTranslation* counter_trans = new TGeoTranslation("", xpos, ypos, zpos);
TGeoRotation* counter_rot = new TGeoRotation();
counter_rot->RotateY(rotangle);
if ( CounterRotationAngleZ[modType] != 0. ) counter_rot->RotateZ(CounterRotationAngleZ[modType]);
TGeoCombiTrans* counter_combi_trans = new TGeoCombiTrans(*counter_trans, *counter_rot);
gas_box_vol->AddNode(gCounter[cType], j, counter_combi_trans);
}
return module;
}
TGeoVolume* create_tof_pole()
{
// needed materials
TGeoMedium* boxVolMed = gGeoMan->GetMedium(BoxVolumeMedium);
TGeoMedium* airVolMed = gGeoMan->GetMedium(KeepingVolumeMedium);
Float_t dx = Pole_Size_X;
Float_t dy = Pole_Size_Y;
Float_t dz = Pole_Size_Z;
Float_t width_alux = Pole_Thick_X;
Float_t width_aluy = Pole_Thick_Y;
Float_t width_aluz = Pole_Thick_Z;
TGeoVolume* pole = new TGeoVolumeAssembly("Pole");
TGeoBBox* pole_alu_box = new TGeoBBox("", dx / 2., dy / 2., dz / 2.);
TGeoVolume* pole_alu_vol = new TGeoVolume("pole_alu", pole_alu_box, boxVolMed);
pole_alu_vol->SetLineColor(kGreen); // set line color for the alu box
pole_alu_vol->SetTransparency(20); // set transparency for the TOF
TGeoTranslation* pole_alu_trans = new TGeoTranslation("", 0., 0., 0.);
pole->AddNode(pole_alu_vol, 0, pole_alu_trans);
Float_t air_dx = dx / 2. - width_alux;
Float_t air_dy = dy / 2. - width_aluy;
Float_t air_dz = dz / 2. - width_aluz;
// cout << "My pole." << endl;
if (air_dx <= 0.) cout << "ERROR - No air volume in pole X, size: " << air_dx << endl;
if (air_dy <= 0.) cout << "ERROR - No air volume in pole Y, size: " << air_dy << endl;
if (air_dz <= 0.) cout << "ERROR - No air volume in pole Z, size: " << air_dz << endl;
if ((air_dx > 0.) && (air_dy > 0.) && (air_dz > 0.)) // crate air volume only, if larger than zero
{
TGeoBBox* pole_air_box = new TGeoBBox("", air_dx, air_dy, air_dz);
// TGeoBBox* pole_air_box = new TGeoBBox("", dx/2.-width_alux, dy/2.-width_aluy, dz/2.-width_aluz);
TGeoVolume* pole_air_vol = new TGeoVolume("pole_air", pole_air_box, airVolMed);
pole_air_vol->SetLineColor(kYellow); // set line color for the alu box
pole_air_vol->SetTransparency(70); // set transparency for the TOF
TGeoTranslation* pole_air_trans = new TGeoTranslation("", 0., 0., 0.);
pole_alu_vol->AddNode(pole_air_vol, 0, pole_air_trans);
}
else
cout << "Skipping pole_air_vol, no thickness: " << air_dx << " " << air_dy << " " << air_dz << endl;
return pole;
}
TGeoVolume* create_tof_bar(Float_t dx, Float_t dy, Float_t dz)
{
// needed materials
TGeoMedium* boxVolMed = gGeoMan->GetMedium(BoxVolumeMedium);
TGeoMedium* airVolMed = gGeoMan->GetMedium(KeepingVolumeMedium);
Float_t width_alux = Pole_Thick_X;
Float_t width_aluy = Pole_Thick_Y;
Float_t width_aluz = Pole_Thick_Z;
TGeoVolume* bar = new TGeoVolumeAssembly("Bar");
TGeoBBox* bar_alu_box = new TGeoBBox("", dx / 2., dy / 2., dz / 2.);
TGeoVolume* bar_alu_vol = new TGeoVolume("bar_alu", bar_alu_box, boxVolMed);
bar_alu_vol->SetLineColor(kGreen); // set line color for the alu box
bar_alu_vol->SetTransparency(20); // set transparency for the TOF
TGeoTranslation* bar_alu_trans = new TGeoTranslation("", 0., 0., 0.);
bar->AddNode(bar_alu_vol, 0, bar_alu_trans);
TGeoBBox* bar_air_box = new TGeoBBox("", dx / 2. - width_alux, dy / 2. - width_aluy, dz / 2. - width_aluz);
TGeoVolume* bar_air_vol = new TGeoVolume("bar_air", bar_air_box, airVolMed);
bar_air_vol->SetLineColor(kYellow); // set line color for the alu box
bar_air_vol->SetTransparency(70); // set transparency for the TOF
TGeoTranslation* bar_air_trans = new TGeoTranslation("", 0., 0., 0.);
bar_alu_vol->AddNode(bar_air_vol, 0, bar_air_trans);
return bar;
}
void position_tof_poles(Int_t modType)
{
TGeoTranslation* pole_trans = NULL;
Int_t numPoles = 0;
for (Int_t i = 0; i < NumberOfPoles; i++) {
if (i < 2) {
pole_trans = new TGeoTranslation("", -Pole_Offset + 2.0, 0., Pole_ZPos[i]);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gPole, numPoles, pole_trans);
numPoles++;
}
else {
Float_t xPos = Pole_Offset + Pole_Size_X / 2. + Pole_Col[i] * DxColl;
Float_t zPos = Pole_ZPos[i];
pole_trans = new TGeoTranslation("", xPos, 0., zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gPole, numPoles, pole_trans);
numPoles++;
pole_trans = new TGeoTranslation("", -xPos, 0., zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gPole, numPoles, pole_trans);
numPoles++;
}
cout << " Position Pole " << numPoles << " at z=" << Pole_ZPos[i] << endl;
}
}
void position_tof_bars(Int_t modType)
{
TGeoTranslation* bar_trans = NULL;
Int_t numBars = 0;
Int_t i;
Float_t xPos;
Float_t yPos;
Float_t zPos;
for (i = 0; i < NumberOfBars; i++) {
xPos = Bar_XPos[i];
zPos = Bar_ZPos[i];
yPos = Pole_Size_Y / 2. + Bar_Size_Y / 2.;
bar_trans = new TGeoTranslation("", xPos, yPos, zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gBar[i], numBars, bar_trans);
numBars++;
bar_trans = new TGeoTranslation("", xPos, -yPos, zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gBar[i], numBars, bar_trans);
numBars++;
bar_trans = new TGeoTranslation("", -xPos, yPos, zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gBar[i], numBars, bar_trans);
numBars++;
bar_trans = new TGeoTranslation("", -xPos, -yPos, zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gBar[i], numBars, bar_trans);
numBars++;
}
cout << " Position Bar " << numBars << " at z=" << Bar_ZPos[i] << endl;
// horizontal frame bars
i = NumberOfBars;
NumberOfBars++;
// no bar
// gBar[i]=create_tof_bar(2.*xPos+Pole_Size_X,Bar_Size_Y,Bar_Size_Y);
zPos = Pole_ZPos[0] + Pole_Size_Z / 2.;
bar_trans = new TGeoTranslation("", 0., yPos, zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gBar[i], numBars, bar_trans);
numBars++;
bar_trans = new TGeoTranslation("", 0., -yPos, zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gBar[i], numBars, bar_trans);
numBars++;
}
void position_inner_tof_modules(Int_t modNType)
{
TGeoTranslation* module_trans = NULL;
// for (Int_t j=0; j<modNType; j++){
// for (Int_t j=1; j<modNType; j++){
Int_t modType;
Int_t modNum[4] = {4 * 0};
// May2021 setup
const Int_t NModules = 6;
Double_t xPos = 0.;
Double_t yPos = 0.;
Double_t zPos = TOF_Z_Front;
const Int_t ModType[NModules] = {0, 0, 0, 0, 0, 2};
//const Double_t ModDx[NModules] = {-53.5, -56.3, -66.8, 0., 0., -65.}; //Au, jun2022, run 2454
//const Double_t ModDx[NModules] = { 0.3, -3.3, -13.5, 50.7, 50.7, -12.0}; //Ni, may2022, run 2391
const Double_t ModDx[NModules] = { 0.2, -3.3, -13.8, 50.7, 49.5, -11.77}; //Ni, may2022, run 2391, data driven
//const Double_t ModDx[NModules] = {-53.5, -57., -72.7, 0., -21.5, -64.};
//const Double_t ModDx[NModules] = {-53.5, -57., -57.7, 0., -21.5, -64.};
//const Double_t ModDx[NModules] = {-53.5, -57., -75.7, 0., -21., -66.};
//const Double_t ModDx[NModules] = { 1.5, 0., -1.5, 49.8, 55.8};
const Double_t ModDy[NModules] = {0., 0., 0., 0., 0., -0.49};
const Double_t ModDz[NModules] = {0., 15.9, 56., 0., 56., 32.}; // regular
const Double_t ModAng[NModules] = {-90., -90., -90., -90., -90.0, -90.};
TGeoRotation* module_rot = NULL;
TGeoCombiTrans* module_combi_trans = NULL;
for (Int_t iMod = 0; iMod < NModules; iMod++) {
module_trans = new TGeoTranslation("", xPos + ModDx[iMod], yPos + ModDy[iMod], zPos + ModDz[iMod]);
module_rot = new TGeoRotation();
module_rot->RotateZ(ModAng[iMod]);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[ModType[iMod]], modNum[ModType[iMod]], module_combi_trans);
cout << "Placed Module " << modNum[ModType[iMod]] << ", Type " << ModType[iMod] << endl;
modNum[ModType[iMod]]++;
}
}
void position_Dia(Int_t modNType)
{
TGeoTranslation* module_trans = NULL;
TGeoRotation* module_rot = new TGeoRotation();
module_rot->RotateZ(Dia_rotate_Z);
TGeoCombiTrans* module_combi_trans = NULL;
// Int_t numModules=(Int_t)( (Inner_Module_Last_Y_Position-Inner_Module_First_Y_Position)/Module_Size_Y[modType])+1;
Float_t yPos = Dia_First_Y_Position;
Int_t ii = 0;
Float_t xPos = Dia_X_Offset;
Float_t zPos = Dia_Z_Position;
Int_t modNum = 0;
for (Int_t j = 0; j < modNType; j++) {
Int_t modType = Dia_Types[j];
for (Int_t i = 0; i < Dia_Number[j]; i++) {
ii++;
module_trans = new TGeoTranslation("", xPos, yPos, zPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_combi_trans);
//top->AddNode(gModules[modType], modNum, module_combi_trans);
modNum++;
}
}
}
void position_Star2(Int_t modNType)
{
TGeoTranslation* module_trans = NULL;
TGeoCombiTrans* module_combi_trans = NULL;
TGeoRotation* module_rot = NULL;
Float_t yPos = Star2_First_Y_Position;
Float_t zPos = Star2_First_Z_Position;
Int_t ii = 0;
Int_t modNum = 0;
for (Int_t j = 0; j < modNType; j++) {
Int_t modType = Star2_Types[j];
Float_t xPos = Star2_X_Offset[j];
module_rot = new TGeoRotation();
module_rot->RotateZ(Star2_rotate_Z[j]);
for (Int_t i = 0; i < Star2_Number[j]; i++) {
ii++;
module_trans = new TGeoTranslation("", xPos, yPos, zPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_combi_trans);
modNum++;
yPos += Star2_Delta_Y_Position;
zPos += Star2_Delta_Z_Position;
}
}
}
void position_Buc(Int_t modNType)
{
TGeoTranslation* module_trans = NULL;
TGeoRotation* module_rot = new TGeoRotation();
module_rot->RotateZ(Buc_rotate_Z);
module_rot->RotateY(Buc_rotate_Y);
TGeoCombiTrans* module_combi_trans = NULL;
Float_t yPos = Buc_First_Y_Position;
Float_t zPos = Buc_First_Z_Position;
Int_t ii = 0;
Int_t modNum = 0;
for (Int_t j = 0; j < modNType; j++) {
Int_t modType = Buc_Types[j];
Float_t xPos = Buc_X_Offset[j];
for (Int_t i = 0; i < Buc_Number[j]; i++) {
ii++;
module_trans = new TGeoTranslation("", xPos, yPos, zPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_combi_trans);
modNum++;
yPos += Buc_Delta_Y_Position;
zPos += Buc_Delta_Z_Position;
}
}
}
void position_cer_modules(Int_t modNType)
{
Int_t ii = 0;
Int_t modNum = 0;
for (Int_t j = 0; j < modNType; j++) {
Int_t modType = Cer_Types[j];
Float_t xPos = Cer_X_Position[j];
Float_t yPos = Cer_Y_Position[j];
Float_t zPos = Cer_Z_Position[j];
TGeoTranslation* module_trans = NULL;
TGeoRotation* module_rot = new TGeoRotation(Form("Cer%d", j), Cer_rotate_Z[j], -MeanTheta, 0.);
// module_rot->RotateZ(Cer_rotate_Z[j]);
TGeoCombiTrans* module_combi_trans = NULL;
for (Int_t i = 0; i < Cer_Number[j]; i++) {
ii++;
cout << "Position Ceramic Module " << i << " of " << Cer_Number[j] << " Type " << modType << " at X = " << xPos
<< ", Y = " << yPos << ", Z = " << zPos << endl;
// Front staggered module (Top if pair), top
module_trans = new TGeoTranslation("", xPos, yPos, zPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_combi_trans);
modNum++;
}
}
}
void position_Testbox_MRPC4(Int_t modNType)
{
TGeoTranslation* module_trans = NULL;
TGeoRotation* module_rot = new TGeoRotation();
module_rot->RotateZ(Testbox_MRPC4_rotate_Z);
TGeoCombiTrans* module_combi_trans = NULL;
// Int_t numModules=(Int_t)( (Inner_Module_Last_Y_Position-Inner_Module_First_Y_Position)/Module_Size_Y[modType])+1;
Float_t yPos = Testbox_MRPC4_First_Y_Position;
Int_t ii = 0;
Float_t xPos = Testbox_MRPC4_X_Offset;
Float_t zPos = Testbox_MRPC4_Z_Position;
for (Int_t j = 0; j < modNType; j++) {
Int_t modType = Testbox_MRPC4_Types[j];
Int_t modNum = 0;
for (Int_t i = 0; i < Testbox_MRPC4_Number[j]; i++) {
ii++;
module_trans = new TGeoTranslation("", xPos, yPos, zPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_combi_trans);
modNum++;
}
}
}
void position_side_tof_modules(Int_t modNType)
{
TGeoTranslation* module_trans = NULL;
TGeoRotation* module_rot = new TGeoRotation();
module_rot->RotateZ(180.);
TGeoCombiTrans* module_combi_trans = NULL;
// Int_t numModules=(Int_t)( (Inner_Module_Last_Y_Position-Inner_Module_First_Y_Position)/Module_Size_Y[modType])+1;
Float_t yPos = 0.; //Inner_Module_First_Y_Position;
Int_t ii = 0;
for (Int_t j = 0; j < modNType; j++) {
Int_t modType = InnerSide_Module_Types[j];
Int_t modNum = 0;
for (Int_t i = 0; i < InnerSide_Module_Number[j]; i++) {
ii++;
cout << "InnerSide ii " << ii << " Last " << Last_Size_Y << "," << Last_Over_Y << endl;
Float_t DeltaY = Module_Size_Y[modType] + Last_Size_Y - 2. * (Module_Over_Y[modType] + Last_Over_Y);
if (ii > 1) { yPos += DeltaY; }
Last_Size_Y = Module_Size_Y[modType];
Last_Over_Y = Module_Over_Y[modType];
Float_t xPos = InnerSide_Module_X_Offset;
Float_t zPos = Wall_Z_Position;
cout << "Position InnerSide Module " << i << " of " << InnerSide_Module_Number[j] << " Type " << modType
<< " at Y = " << yPos << " Ysize = " << Module_Size_Y[modType] << " DeltaY = " << DeltaY << endl;
module_trans = new TGeoTranslation("", xPos, yPos, zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_trans);
modNum++;
module_trans = new TGeoTranslation("", -xPos, yPos, zPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_combi_trans);
modNum++;
if (ii > 1) {
module_trans = new TGeoTranslation("", xPos, -yPos, zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_trans);
modNum++;
module_trans = new TGeoTranslation("", -xPos, -yPos, zPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_combi_trans);
modNum++;
module_trans = new TGeoTranslation("", xPos, yPos - DeltaY / 2, zPos + Module_Size_Z[modType]);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_trans);
modNum++;
module_trans = new TGeoTranslation("", -xPos, yPos - DeltaY / 2, zPos + Module_Size_Z[modType]);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_combi_trans);
modNum++;
module_trans = new TGeoTranslation("", xPos, -(yPos - DeltaY / 2), zPos + Module_Size_Z[modType]);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_trans);
modNum++;
module_trans = new TGeoTranslation("", -xPos, -(yPos - DeltaY / 2), zPos + Module_Size_Z[modType]);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_combi_trans);
modNum++;
}
}
}
}
void position_outer_tof_modules(Int_t nCol) //modType, Int_t col1, Int_t col2)
{
TGeoTranslation* module_trans = NULL;
TGeoRotation* module_rot = new TGeoRotation();
module_rot->RotateZ(180.);
TGeoCombiTrans* module_combi_trans = NULL;
// Int_t numModules=(Int_t)( (Outer_Module_Last_Y_Position-Outer_Module_First_Y_Position)/Module_Size_Y[modType])+1;
Int_t modNum[NofModuleTypes];
for (Int_t k = 0; k < NofModuleTypes; k++) {
modNum[k] = 0;
}
Float_t zPos = Wall_Z_Position;
for (Int_t j = 0; j < nCol; j++) {
Float_t xPos = Outer_Module_X_Offset + ((j + 1) * DxColl);
Last_Size_Y = 0.;
Last_Over_Y = 0.;
Float_t yPos = 0.;
Int_t ii = 0;
Float_t DzPos = 0.;
for (Int_t k = 0; k < Outer_Module_NTypes; k++) {
Int_t modType = Outer_Module_Types[k][j];
if (Module_Size_Z[modType] > DzPos) {
if (Outer_Module_Number[k][j] > 0) { DzPos = Module_Size_Z[modType]; }
}
}
zPos -= 2. * DzPos; //((j+1)*2*Module_Size_Z[modType]);
Pole_ZPos[NumberOfPoles] = zPos;
Pole_Col[NumberOfPoles] = j + 1;
NumberOfPoles++;
Pole_ZPos[NumberOfPoles] = zPos + DzPos;
Pole_Col[NumberOfPoles] = j + 1;
NumberOfPoles++;
//if (j+1==nCol) {
if (1) {
Pole_ZPos[NumberOfPoles] = Pole_ZPos[0];
Pole_Col[NumberOfPoles] = j + 1;
NumberOfPoles++;
Bar_Size_Z = Pole_ZPos[0] - zPos;
gBar[NumberOfBars] = create_tof_bar(Bar_Size_X, Bar_Size_Y, Bar_Size_Z);
Bar_ZPos[NumberOfBars] = zPos + Bar_Size_Z / 2. - Pole_Size_Z / 2.;
Bar_XPos[NumberOfBars] = xPos + Pole_Offset;
NumberOfBars++;
}
for (Int_t k = 0; k < Outer_Module_NTypes; k++) {
Int_t modType = Outer_Module_Types[k][j];
Int_t numModules = Outer_Module_Number[k][j];
cout << " Outer: position " << numModules << " of type " << modType << " in col " << j << " at z = " << zPos
<< ", DzPos = " << DzPos << endl;
for (Int_t i = 0; i < numModules; i++) {
ii++;
cout << "Outer ii " << ii << " Last " << Last_Size_Y << "," << Last_Over_Y << endl;
Float_t DeltaY = Module_Size_Y[modType] + Last_Size_Y - 2. * (Module_Over_Y[modType] + Last_Over_Y);
if (ii > 1) { yPos += DeltaY; }
Last_Size_Y = Module_Size_Y[modType];
Last_Over_Y = Module_Over_Y[modType];
cout << "Position Outer Module " << i << " of " << Outer_Module_Number[k][j] << " Type " << modType << "(#"
<< modNum[modType] << ") "
<< " at Y = " << yPos << " Ysize = " << Module_Size_Y[modType] << " DeltaY = " << DeltaY << endl;
module_trans = new TGeoTranslation("", xPos, yPos, zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum[modType], module_trans);
modNum[modType]++;
module_trans = new TGeoTranslation("", -xPos, yPos, zPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum[modType], module_combi_trans);
modNum[modType]++;
if (ii > 1) {
module_trans = new TGeoTranslation("", xPos, -yPos, zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum[modType], module_trans);
modNum[modType]++;
module_trans = new TGeoTranslation("", -xPos, -yPos, zPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum[modType], module_combi_trans);
modNum[modType]++;
// second layer
module_trans = new TGeoTranslation("", xPos, yPos - DeltaY / 2., zPos + DzPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum[modType], module_trans);
modNum[modType]++;
module_trans = new TGeoTranslation("", -xPos, yPos - DeltaY / 2., zPos + DzPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum[modType], module_combi_trans);
modNum[modType]++;
module_trans = new TGeoTranslation("", xPos, -(yPos - DeltaY / 2.), zPos + DzPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum[modType], module_trans);
modNum[modType]++;
module_trans = new TGeoTranslation("", -xPos, -(yPos - DeltaY / 2.), zPos + DzPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum[modType], module_combi_trans);
modNum[modType]++;
}
}
}
}
}
void dump_info_file()
{
TDatime datetime; // used to get timestamp
printf("writing info file: %s\n", FileNameInfo.Data());
FILE* ifile;
ifile = fopen(FileNameInfo.Data(), "w");
if (ifile == NULL) {
printf("error opening %s\n", FileNameInfo.Data());
exit(1);
}
fprintf(ifile, "#\n## %s information file\n#\n\n", geoVersion.Data());
fprintf(ifile, "# created %d\n\n", datetime.GetDate());
fprintf(ifile, "# TOF setup\n");
if (TOF_Z_Front == 450) fprintf(ifile, "SIS 100 hadron setup\n");
if (TOF_Z_Front == 600) fprintf(ifile, "SIS 100 electron\n");
if (TOF_Z_Front == 650) fprintf(ifile, "SIS 100 muon\n");
if (TOF_Z_Front == 880) fprintf(ifile, "SIS 300 electron\n");
if (TOF_Z_Front == 1020) fprintf(ifile, "SIS 300 muon\n");
fprintf(ifile, "\n");
const Float_t TOF_Z_Back = Wall_Z_Position + 1.5 * Module_Size_Z[0]; // back of TOF wall
fprintf(ifile, "# envelope\n");
// Show extension of TRD
fprintf(ifile, "%7.2f cm start of TOF (z)\n", TOF_Z_Front);
fprintf(ifile, "%7.2f cm end of TOF (z)\n", TOF_Z_Back);
fprintf(ifile, "\n");
// Layer thickness
fprintf(ifile, "# central tower position\n");
fprintf(ifile, "%7.2f cm center of staggered, front RPC cell at x=0\n", Wall_Z_Position);
fprintf(ifile, "\n");
fclose(ifile);
}
/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Florian Uhlig, Ingo Deppner [committer], A. Bercuci */
///
/// \file Create_TOF_Geometry_v24d_mcbm.C
/// \brief Generates TOF geometry in Root format.
///
// Changelog
// 2024-10-27 - v24d - NH - Update for 2nd Diamond support by adding 4 "channels" to 1st Diamond
// 2024-06-17 - v24d - AB - Fix Z position of odd and even RPCs in module type 0
// 2024-04-30 - v24d - ID - Add 2nd downstream wall of TOF modules
// 2024-03-26 - v24b - DE - Shifted in z to position measured in the cave
// 2024-03-26 - v24a - DE - March 2024 setup by NH, script patched by DE in lines 1000 and 1004 to show only 2 STAR modules
// 2021-11-17 - v24a - QZ - Modified v20d to fit the logic of digibdf.par
// 2020-04-14 - v20b - NH - swapped double stack layer 2 with STAR2 moodule, buc kept as dummy
// 2020-04-01 - v20a - NH - move mTOF +20 cm in x direction for the Mar 2020 run
// 2019-11-28 - v19b - DE - move mTOF +12 cm in x direction for the Nov 2019 run
// 2019-07-31 - v19a - DE - this TOF March 2019 geometry is also known as v18m
// 2017-11-03 - v18i - DE - shift mTOF to z=298 cm for acceptance matching with mSTS
// 2017-10-06 - v18h - DE - put v18f into vertical position to fit into the mCBM cave
// 2017-07-15 - v18g - DE - swap the z-position of TOF modules: 2 in the front, 3 in the back
// 2017-07-14 - v18f - DE - reduce vertical gap between TOF modules to fix the gap between modules 1-2 and 4-5
// 2017-05-17 - v18e - DE - rotate electronics away from beam, shift 16 cm away from beam along x-axis
// 2017-05-17 - v18d - DE - change geometry name to v18d
// in root all sizes are given in cm
#include "TFile.h"
#include "TGeoCompositeShape.h"
#include "TGeoManager.h"
#include "TGeoMaterial.h"
#include "TGeoMatrix.h"
#include "TGeoMedium.h"
#include "TGeoPgon.h"
#include "TGeoVolume.h"
#include "TList.h"
#include "TMath.h"
#include "TROOT.h"
#include "TString.h"
#include "TSystem.h"
#include <iostream>
// Name of geometry version and output file
const TString geoVersion = "tof_v24d_mcbm"; // do not change
const TString geoVersionStand = geoVersion + "Stand";
//
const TString fileTag = "tof_v24d";
const TString FileNameSim = fileTag + "_mcbm.geo.root?reproducible";
const TString FileNameGeo = fileTag + "_mcbm_geo.root?reproducible";
const TString FileNameInfo = fileTag + "_mcbm.geo.info";
// TOF_Z_Front corresponds to front cover of outer super module towers
const Float_t TOF_Z_Front_Stand = 233.2; // = z=298 mCBM@SIS18
const Float_t TOF_Y_Front_Stand = 0.;
const Float_t TOF_X_Front_Stand = 0.;
const Float_t TOF_Z_Front = 0;
//const Float_t TOF_Z_Front = 130; // = z=225 mCBM@SIS18
//const Float_t TOF_Z_Front = 250; // SIS 100 hadron
//const Float_t TOF_Z_Front = 450; // SIS 100 hadron
//const Float_t TOF_Z_Front = 600; // SIS 100 electron
//const Float_t TOF_Z_Front = 650; // SIS 100 muon
//const Float_t TOF_Z_Front = 880; // SIS 300 electron
//const Float_t TOF_Z_Front = 1020; // SIS 300 muon
//
//const Float_t TOF_Z_Front = 951.5; // Wall_Z_Position = 1050 cm
// Names of the different used materials which are used to build the modules
// The materials are defined in the global media.geo file
const TString KeepingVolumeMedium = "air";
const TString BoxVolumeMedium = "aluminium";
const TString NoActivGasMedium = "RPCgas_noact";
const TString ActivGasMedium = "RPCgas";
const TString GlasMedium = "RPCglass";
const TString ElectronicsMedium = "carbon";
// Counters:
// 0 MRPC3a
// 1 MRPC3b
// 2 USTC
// 3
// 4 Diamond
//
// 6 Buc 2019
// 7 CERN 20gap
// 8 Ceramic Pad
const Int_t NumberOfDifferentCounterTypes = 9;
const Float_t Glass_X[NumberOfDifferentCounterTypes] = {32., 32., 32., 32., 0.2, 32., 28.8, 20., 2.4};
const Float_t Glass_Y[NumberOfDifferentCounterTypes] = {27.0, 53., 26.8, 10., 0.2, 10., 6., 20., 2.4};
const Float_t Glass_Z[NumberOfDifferentCounterTypes] = {0.1, 0.1, 0.1, 0.1, 0.01, 0.1, 0.1, 0.1, 0.1};
const Float_t GasGap_X[NumberOfDifferentCounterTypes] = {32., 32., 32., 32., 0.2, 32., 28.8, 20., 2.4};
const Float_t GasGap_Y[NumberOfDifferentCounterTypes] = {27.0, 53., 26.8, 10., 0.2, 10., 6., 20., 2.4};
const Float_t GasGap_Z[NumberOfDifferentCounterTypes] = {0.025, 0.025, 0.025, 0.025, 0.01, 0.02, 0.02, 0.02, 0.025};
const Int_t NumberOfGaps[NumberOfDifferentCounterTypes] = {8, 8, 8, 8, 1, 8, 10, 20, 4};
//const Int_t NumberOfGaps[NumberOfDifferentCounterTypes] = {1,1,1,1}; //deb
const Int_t NumberOfReadoutStrips[NumberOfDifferentCounterTypes] = {32, 32, 32, 32, 20, 32, 32, 20, 1};
//const Int_t NumberOfReadoutStrips[NumberOfDifferentCounterTypes] = {1,1,1,1}; //deb
const Float_t SingleStackStartPosition_Z[NumberOfDifferentCounterTypes] = {-0.6, -0.6, -0.6, -0.6, -0.1,
-0.6, -0.6, -0.6, -1.};
const Float_t Electronics_X[NumberOfDifferentCounterTypes] = {32.0, 32.0, 32.0, 32., 0.3, 0.1, 28.8, 20., 0.1};
const Float_t Electronics_Y[NumberOfDifferentCounterTypes] = {5.0, 5.0, 1.0, 1., 0.1, 0.1, 1.0, 1.0, 0.1};
const Float_t Electronics_Z[NumberOfDifferentCounterTypes] = {0.3, 0.3, 0.3, 0.3, 0.1, 0.1, 0.1, 0.1, 0.1};
const Int_t NofModuleTypes = 10;
// 0 M4 (TSHU)
// 1 M4 (USTC)
// 2 M6 (USTC)
// 5 Diamond
// 6 Buc
// 7 Testbox MRPC4
// 8 Ceramic
// 9 Star2
// Aluminum box for all module types
const Float_t Module_Size_X[NofModuleTypes] = {180., 180., 180., 180., 180., 5., 40., 100., 10., 100.};
const Float_t Module_Size_Y[NofModuleTypes] = {49., 49., 74., 28., 18., 5., 15., 49., 10., 49.};
const Float_t Module_Over_Y[NofModuleTypes] = {11.5, 11.5, 11., 4.5, 4.5, 0., 0., 0., 0., 0.};
const Float_t Module_Size_Z[NofModuleTypes] = {11., 11., 13., 11., 11., 1., 14.5, 11., 1., 11.2};
const Float_t Module_Thick_Alu_X_left = 0.1;
const Float_t Module_Thick_Alu_X_right = 1.0;
const Float_t Module_Thick_Alu_Y = 0.1;
const Float_t Module_Thick_Alu_Z = 0.1;
// Distance to the center of the TOF wall [cm];
const Float_t Wall_Z_Position = 400.;
const Float_t MeanTheta = 0.;
//Type of Counter for module
const Int_t CounterTypeInModule[NofModuleTypes] = {0, 0, 1, 2, 3, 4, 6, 7, 8, 0};
const Int_t NCounterInModule[NofModuleTypes] = {5, 5, 5, 5, 5, 1, 2, 1, 8, 2};
// Placement of the counter inside the module
const Float_t CounterXStartPosition[NofModuleTypes] = {-60.0, -66.0, -61.0, -60.0, -60.0, 0.0, 0., 0., 0., 0.};
const Float_t CounterXDistance[NofModuleTypes] = { 30., 32.0, 30.5, 30.0, 30.0, 0.0, 0., 0., 0., 0.};
//Alex const Float_t CounterXStartPosition[NofModuleTypes] = {-60.0, -66.0, -61.1, -60.0, -60.0, 0.0, 0., 0., 0., 0.};
//Alex const Float_t CounterXDistance[NofModuleTypes] = { 30.0, 32.0, 30.45, 30.0, 30.0, 0.0, 0., 0., 0., 0.};
const Float_t CounterYStartPosition[NofModuleTypes] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0., 0., 0., 0., 0.};
const Float_t CounterYDistance[NofModuleTypes] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0., 0., 0., 0., 0.};
//Norbert const Float_t CounterZDistance[NofModuleTypes] = { -2.25, 0.0, 0.0, 2.5, 2.5, 0., -3.8, 4., 0.1, 4.3};
//Norbert const Float_t CounterZStartPosition[NofModuleTypes] = { 3.3, 0.0, 0.0, 0.0, 0.0, 0., 1.9, -2., 0.0,-2.2};
const Float_t CounterZDistance[NofModuleTypes] = { -2.25, 0.0, 0.0, 2.5, 2.5, 0., 3.8, 4., 0.1, 4.3};
const Float_t CounterZStartPosition[NofModuleTypes] = { 3.3, 0.0, 0.0, 0.0, 0.0, 0., -1.9, -2., 0.0,-2.2};
const Float_t CounterRotationAngle[NofModuleTypes] = { 0., 8.7, -10.0, 0., 0., 0., 0., 0., 0., 0.};
const Float_t CounterRotationAngleZ[NofModuleTypes] = { 0., 0., 0.0, 0., 0., 0., 0., 90., 0., 0.};
// clang-format on
// Pole (support structure)
const Int_t MaxNumberOfPoles = 20;
Float_t Pole_ZPos[MaxNumberOfPoles];
Float_t Pole_Col[MaxNumberOfPoles];
Int_t NumberOfPoles = 0;
const Float_t Pole_Size_X = 20.;
const Float_t Pole_Size_Y = 300.;
const Float_t Pole_Size_Z = 10.;
const Float_t Pole_Thick_X = 5.;
const Float_t Pole_Thick_Y = 5.;
const Float_t Pole_Thick_Z = 5.;
// Bars (support structure)
const Float_t Bar_Size_X = 20.;
const Float_t Bar_Size_Y = 20.;
Float_t Bar_Size_Z = 100.;
const Int_t MaxNumberOfBars = 20;
Float_t Bar_ZPos[MaxNumberOfBars];
Float_t Bar_XPos[MaxNumberOfBars];
Int_t NumberOfBars = 0;
const Float_t ChamberOverlap = 40;
const Float_t DxColl = 158.0; //Module_Size_X-ChamberOverlap;
//const Float_t Pole_Offset=Module_Size_X/2.+Pole_Size_X/2.;
const Float_t Pole_Offset = 90.0 + Pole_Size_X / 2.;
// Position for module placement
const Float_t Inner_Module_First_Y_Position = 16.;
const Float_t Inner_Module_Last_Y_Position = 480.;
const Float_t Inner_Module_X_Offset = 0.; // centered position in x/y
//const Float_t Inner_Module_X_Offset=18; // shift by 16 cm in x
const Int_t Inner_Module_NTypes = 3;
const Float_t Inner_Module_Types[Inner_Module_NTypes] = {4., 3., 0.};
//const Float_t Inner_Module_Number[Inner_Module_NTypes] = {2.,2.,6.}; //V13_3a
const Float_t Inner_Module_Number[Inner_Module_NTypes] = {2., 2., 1.}; //V13_3a
//const Float_t Inner_Module_Number[Inner_Module_NTypes] = {0.,0.,0.}; //debugging
const Float_t InnerSide_Module_X_Offset = 51.;
const Float_t InnerSide_Module_NTypes = 1;
const Float_t InnerSide_Module_Types[Inner_Module_NTypes] = {5.};
const Float_t InnerSide_Module_Number[Inner_Module_NTypes] = {2.}; //v13_3a
//const Float_t InnerSide_Module_Number[Inner_Module_NTypes] = {0.}; //debug
const Float_t Outer_Module_First_Y_Position = 0.;
const Float_t Outer_Module_Last_Y_Position = 480.;
const Float_t Outer_Module_X_Offset = 3.;
const Int_t Outer_Module_Col = 4;
const Int_t Outer_Module_NTypes = 2;
const Float_t Outer_Module_Types[Outer_Module_NTypes][Outer_Module_Col] = {1., 1., 1., 1., 2., 2., 2., 2.};
const Float_t Outer_Module_Number[Outer_Module_NTypes][Outer_Module_Col] = {9., 9., 2., 0., 0., 0., 3., 4.}; //V13_3a
//const Float_t Outer_Module_Number[Outer_Module_NTypes][Outer_Module_Col] = {1.,1.,0.,0., 0.,0.,0.,0.};//debug
const Float_t Star2_First_Z_Position = TOF_Z_Front + 36.;
const Float_t Star2_Delta_Z_Position = 16.;
const Float_t Star2_First_Y_Position = -1.3; //
const Float_t Star2_Delta_Y_Position = 0.; //
const Int_t Star2_NTypes = 2;
const Float_t Star2_rotate_Z[Star2_NTypes] = {90.,90};
const Float_t Star2_Types[Star2_NTypes] = {9.,9};
const Float_t Star2_Number[Star2_NTypes] = {1.,1.}; //debugging, V16b
const Float_t Star2_X_Offset[Star2_NTypes] = {-15.,-15.0}; //{62.};
const Float_t Buc_First_Z_Position = TOF_Z_Front + 34.75;
const Float_t Buc_Delta_Z_Position = 0.;
const Float_t Buc_First_Y_Position = 33.5; //
const Float_t Buc_Delta_Y_Position = 0.; //
const Float_t Buc_rotate_Z = 180.;
const Float_t Buc_rotate_Y = 0.;
const Int_t Buc_NTypes = 1;
const Float_t Buc_Types[Buc_NTypes] = {6.};
const Float_t Buc_Number[Buc_NTypes] = {1.}; //debugging, V16b
const Float_t Buc_X_Offset[Buc_NTypes] = {32.};
const Int_t Cer_NTypes = 3;
const Float_t Cer_Z_Position[Cer_NTypes] = {(float) (TOF_Z_Front + 13.2), (float) (TOF_Z_Front + 45.),
(float) (TOF_Z_Front + 45.)};
const Float_t Cer_X_Position[Cer_NTypes] = {0., 49.8, 49.8};
const Float_t Cer_Y_Position[Cer_NTypes] = {-1., 5., 5.};
const Float_t Cer_rotate_Z[Cer_NTypes] = {0., 0., 0.};
const Float_t Cer_Types[Cer_NTypes] = {5., 8., 8.};
const Float_t Cer_Number[Cer_NTypes] = {1., 1., 1.}; //V16b
const Float_t Testbox_MRPC4_Z_Position = TOF_Z_Front + 15.9; //
const Float_t Testbox_MRPC4_First_Y_Position = 32.70;
const Float_t Testbox_MRPC4_X_Offset = 50.17; //65.5;
const Float_t Testbox_MRPC4_rotate_Z = -90.;
const Int_t Testbox_MRPC4_NTypes = 1;
const Float_t Testbox_MRPC4_Types[Testbox_MRPC4_NTypes] = {7.}; // this is the SmType!
const Float_t Testbox_MRPC4_Number[Testbox_MRPC4_NTypes] = {1.}; // evtl. double for split signals
// some global variables
TGeoManager* gGeoMan = NULL; // Pointer to TGeoManager instance
TGeoVolume* gModules[NofModuleTypes]; // Global storage for module types
TGeoVolume* gCounter[NumberOfDifferentCounterTypes];
TGeoVolume* gPole;
TGeoVolume* gBar[MaxNumberOfBars];
const Float_t Dia_Z_Position = -0.5 - TOF_Z_Front_Stand;
const Float_t Dia_First_Y_Position = 0.;
const Float_t Dia_X_Offset = 0.;
const Float_t Dia_rotate_Z = 0.;
const Float_t Dia_DZ = 5.;
const Int_t Dia_NTypes = 2;
const Float_t Dia_Types[Dia_NTypes] = {5.,5.};
const Float_t Dia_Number[Dia_NTypes] = {1.,1.};
Float_t Last_Size_Y = 0.;
Float_t Last_Over_Y = 0.;
// Forward declarations
void create_materials_from_media_file();
TGeoVolume* create_counter(Int_t);
TGeoVolume* create_new_counter(Int_t);
TGeoVolume* create_tof_module(Int_t);
TGeoVolume* create_new_tof_module(Int_t);
TGeoVolume* create_tof_pole();
TGeoVolume* create_tof_bar();
void position_tof_poles(Int_t);
void position_tof_bars(Int_t);
void position_inner_tof_modules(Int_t);
void position_side_tof_modules(Int_t);
void position_outer_tof_modules(Int_t);
void position_Dia(Int_t);
void position_Star2(Int_t);
void position_Buc(Int_t);
void position_cer_modules(Int_t);
void position_Testbox_MRPC4(Int_t);
void dump_info_file();
void Create_TOF_Geometry_v24d_mcbm()
{
// Load needed material definition from media.geo file
create_materials_from_media_file();
// Get the GeoManager for later usage
gGeoMan = (TGeoManager*) gROOT->FindObject("FAIRGeom");
gGeoMan->SetVisLevel(5); // 2 = super modules
gGeoMan->SetVisOption(0);
// Create the top volume
/*
TGeoBBox* topbox= new TGeoBBox("", 1000., 1000., 1000.);
TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air"));
gGeoMan->SetTopVolume(top);
*/
TGeoVolume* top = new TGeoVolumeAssembly("TOP");
gGeoMan->SetTopVolume(top);
TGeoRotation* tof_rotation = new TGeoRotation();
tof_rotation->RotateY(0.); // angle with respect to beam axis
//tof_rotation->RotateZ( 0 ); // electronics on 9 o'clock position = +x
// tof_rotation->RotateZ( 0 ); // electronics on 9 o'clock position = +x
// tof_rotation->RotateZ( 90 ); // electronics on 12 o'clock position (top)
// tof_rotation->RotateZ( 180 ); // electronics on 3 o'clock position = -x
// tof_rotation->RotateZ( 270 ); // electronics on 6 o'clock position (bottom)
TGeoVolume* tof = new TGeoVolumeAssembly(geoVersion);
// top->AddNode(tof, 1, tof_rotation);
top->AddNode(tof, 1);
TGeoVolume* tofstand = new TGeoVolumeAssembly(geoVersionStand);
// Mar 2020 run
TGeoTranslation* stand_trans_local = new TGeoTranslation("", TOF_X_Front_Stand, TOF_Y_Front_Stand, 0.);
TGeoTranslation* stand_trans = new TGeoTranslation("", 0., 0., TOF_Z_Front_Stand);
TGeoCombiTrans* stand_combi_trans = new TGeoCombiTrans(*stand_trans, *tof_rotation);
TGeoRotation* stand_rot = new TGeoRotation();
stand_rot->RotateY(0.);
//stand_rot->RotateY(0.97);
TGeoCombiTrans* stand_combi_trans_local = new TGeoCombiTrans(*stand_trans_local, *stand_rot);
//tof->AddNode(tofstand, 1, stand_combi_trans);
tof->AddNode(tofstand, 1, stand_combi_trans_local);
//tof->AddNode(tofstand, 1);
for (Int_t counterType = 0; counterType < NumberOfDifferentCounterTypes; counterType++) {
gCounter[counterType] = create_new_counter(counterType);
}
for (Int_t moduleType = 0; moduleType < NofModuleTypes; moduleType++) {
gModules[moduleType] = create_new_tof_module(moduleType);
gModules[moduleType]->SetVisContainers(1);
}
// no pole
// gPole = create_tof_pole();
// position_side_tof_modules(1); // keep order !!
// position_inner_tof_modules(2);
position_inner_tof_modules(1);
position_Dia(2);
position_Star2(2);
// position_cer_modules(3);
// position_CERN(1);
position_Buc(1);
cout << "Outer Types " << Outer_Module_Types[0][0] << ", " << Outer_Module_Types[1][0]
<< ", col=1: " << Outer_Module_Types[0][1] << ", " << Outer_Module_Types[1][1] << endl;
cout << "Outer Number " << Outer_Module_Number[0][0] << ", " << Outer_Module_Number[1][0]
<< ", col=1: " << Outer_Module_Number[0][1] << ", " << Outer_Module_Number[1][1] << endl;
// position_outer_tof_modules(4);
// position_tof_poles(0);
// position_tof_bars(0);
gGeoMan->CloseGeometry();
gGeoMan->CheckOverlaps(0.001);
gGeoMan->PrintOverlaps();
gGeoMan->CheckOverlaps(0.001, "s");
gGeoMan->PrintOverlaps();
gGeoMan->Test();
tof->Export(FileNameSim);
TFile* geoFile = new TFile(FileNameSim, "UPDATE");
stand_combi_trans->Write();
geoFile->Close();
/*
TFile* outfile1 = new TFile(FileNameSim,"RECREATE");
top->Write();
//gGeoMan->Write();
outfile1->Close();
*/
TFile* outfile2 = new TFile(FileNameGeo, "RECREATE");
gGeoMan->Write();
outfile2->Close();
dump_info_file();
top->SetVisContainers(1);
gGeoMan->SetVisLevel(5);
top->Draw("ogl");
//top->Draw();
//gModules[0]->Draw("ogl");
// gModules[0]->Draw("");
gModules[0]->SetVisContainers(1);
// gModules[1]->Draw("");
gModules[1]->SetVisContainers(1);
//gModules[5]->Draw("");
// top->Raytrace();
}
void create_materials_from_media_file()
{
// Use the FairRoot geometry interface to load the media which are already defined
FairGeoLoader* geoLoad = new FairGeoLoader("TGeo", "FairGeoLoader");
FairGeoInterface* geoFace = geoLoad->getGeoInterface();
TString geoPath = gSystem->Getenv("VMCWORKDIR");
TString geoFile = geoPath + "/geometry/media.geo";
geoFace->setMediaFile(geoFile);
geoFace->readMedia();
// Read the required media and create them in the GeoManager
FairGeoMedia* geoMedia = geoFace->getMedia();
FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder();
FairGeoMedium* air = geoMedia->getMedium("air");
FairGeoMedium* aluminium = geoMedia->getMedium("aluminium");
FairGeoMedium* RPCgas = geoMedia->getMedium("RPCgas");
FairGeoMedium* RPCgas_noact = geoMedia->getMedium("RPCgas_noact");
FairGeoMedium* RPCglass = geoMedia->getMedium("RPCglass");
FairGeoMedium* carbon = geoMedia->getMedium("carbon");
// include check if all media are found
geoBuild->createMedium(air);
geoBuild->createMedium(aluminium);
geoBuild->createMedium(RPCgas);
geoBuild->createMedium(RPCgas_noact);
geoBuild->createMedium(RPCglass);
geoBuild->createMedium(carbon);
}
TGeoVolume* create_counter(Int_t modType)
{
//glass
Float_t gdx = Glass_X[modType];
Float_t gdy = Glass_Y[modType];
Float_t gdz = Glass_Z[modType];
//gas gap
Int_t nstrips = NumberOfReadoutStrips[modType];
Int_t ngaps = NumberOfGaps[modType];
Float_t ggdx = GasGap_X[modType];
Float_t ggdy = GasGap_Y[modType];
Float_t ggdz = GasGap_Z[modType];
Float_t gsdx = ggdx / float(nstrips);
//single stack
Float_t dzpos = gdz + ggdz;
Float_t startzpos = SingleStackStartPosition_Z[modType];
// electronics
//pcb dimensions
Float_t dxe = Electronics_X[modType];
Float_t dye = Electronics_Y[modType];
Float_t dze = Electronics_Z[modType];
Float_t yele = (gdy + 0.1) / 2. + dye / 2.;
// needed materials
TGeoMedium* glassPlateVolMed = gGeoMan->GetMedium(GlasMedium);
TGeoMedium* noActiveGasVolMed = gGeoMan->GetMedium(NoActivGasMedium);
TGeoMedium* activeGasVolMed = gGeoMan->GetMedium(ActivGasMedium);
TGeoMedium* electronicsVolMed = gGeoMan->GetMedium(ElectronicsMedium);
// Single glass plate
TGeoBBox* glass_plate = new TGeoBBox("", gdx / 2., gdy / 2., gdz / 2.);
TGeoVolume* glass_plate_vol = new TGeoVolume("tof_glass", glass_plate, glassPlateVolMed);
glass_plate_vol->SetLineColor(kMagenta); // set line color for the glass plate
glass_plate_vol->SetTransparency(20); // set transparency for the TOF
TGeoTranslation* glass_plate_trans = new TGeoTranslation("", 0., 0., 0.);
// Single gas gap
TGeoBBox* gas_gap = new TGeoBBox("", ggdx / 2., ggdy / 2., ggdz / 2.);
//TGeoVolume* gas_gap_vol =
//new TGeoVolume("tof_gas_gap", gas_gap, noActiveGasVolMed);
TGeoVolume* gas_gap_vol = new TGeoVolume("tof_gas_active", gas_gap, activeGasVolMed);
gas_gap_vol->Divide("Strip", 1, nstrips, -ggdx / 2., 0);
gas_gap_vol->SetLineColor(kRed); // set line color for the gas gap
gas_gap_vol->SetTransparency(70); // set transparency for the TOF
TGeoTranslation* gas_gap_trans = new TGeoTranslation("", 0., 0., (gdz + ggdz) / 2.);
// Single subdivided active gas gap
/*
TGeoBBox* gas_active = new TGeoBBox("", gsdx/2., ggdy/2., ggdz/2.);
TGeoVolume* gas_active_vol =
new TGeoVolume("tof_gas_active", gas_active, activeGasVolMed);
gas_active_vol->SetLineColor(kBlack); // set line color for the gas gap
gas_active_vol->SetTransparency(70); // set transparency for the TOF
*/
// Add glass plate, inactive gas gap and active gas gaps to a single stack
TGeoVolume* single_stack = new TGeoVolumeAssembly("single_stack");
single_stack->AddNode(glass_plate_vol, 0, glass_plate_trans);
single_stack->AddNode(gas_gap_vol, 0, gas_gap_trans);
/*
for (Int_t l=0; l<nstrips; l++){
TGeoTranslation* gas_active_trans
= new TGeoTranslation("", -ggdx/2+(l+0.5)*gsdx, 0., 0.);
gas_gap_vol->AddNode(gas_active_vol, l, gas_active_trans);
// single_stack->AddNode(gas_active_vol, l, gas_active_trans);
}
*/
// Add 8 single stacks + one glass plate at the e09.750nd to a multi stack
TGeoVolume* multi_stack = new TGeoVolumeAssembly("multi_stack");
Int_t l;
for (l = 0; l < ngaps; l++) {
TGeoTranslation* single_stack_trans = new TGeoTranslation("", 0., 0., startzpos + l * dzpos);
multi_stack->AddNode(single_stack, l, single_stack_trans);
}
TGeoTranslation* single_glass_back_trans = new TGeoTranslation("", 0., 0., startzpos + ngaps * dzpos);
multi_stack->AddNode(glass_plate_vol, l, single_glass_back_trans);
// Add electronics above and below the glass stack to build a complete counter
TGeoVolume* counter = new TGeoVolumeAssembly("counter");
TGeoTranslation* multi_stack_trans = new TGeoTranslation("", 0., 0., 0.);
counter->AddNode(multi_stack, l, multi_stack_trans);
TGeoBBox* pcb = new TGeoBBox("", dxe / 2., dye / 2., dze / 2.);
TGeoVolume* pcb_vol = new TGeoVolume("pcb", pcb, electronicsVolMed);
pcb_vol->SetLineColor(kCyan); // set line color for the gas gap
pcb_vol->SetTransparency(10); // set transparency for the TOF
for (Int_t l = 0; l < 2; l++) {
yele *= -1.;
TGeoTranslation* pcb_trans = new TGeoTranslation("", 0., yele, 0.);
counter->AddNode(pcb_vol, l, pcb_trans);
}
return counter;
}
TGeoVolume* create_new_counter(Int_t modType)
{
//glass
Float_t gdx = Glass_X[modType];
Float_t gdy = Glass_Y[modType];
Float_t gdz = Glass_Z[modType];
//gas gap
Int_t nstrips = NumberOfReadoutStrips[modType];
Int_t ngaps = NumberOfGaps[modType];
Float_t ggdx = GasGap_X[modType];
Float_t ggdy = GasGap_Y[modType];
Float_t ggdz = GasGap_Z[modType];
Float_t gsdx = ggdx / (Float_t)(nstrips);
// electronics
//pcb dimensions
Float_t dxe = Electronics_X[modType];
Float_t dye = Electronics_Y[modType];
Float_t dze = Electronics_Z[modType];
Float_t yele = gdy / 2. + dye / 2.;
// counter size (calculate from glas, gap and electronics sizes)
Float_t cdx = TMath::Max(gdx, ggdx);
cdx = TMath::Max(cdx, dxe) + 0.2;
Float_t cdy = TMath::Max(gdy, ggdy) + 2 * dye + 0.2;
Float_t cdz = ngaps * ggdz + (ngaps + 1) * gdz + 0.2; // ngaps * (gdz+ggdz) + gdz + 0.2; // ok
//calculate thickness and first position in counter of single stack
Float_t dzpos = gdz + ggdz;
Float_t startzposglas = -ngaps * (gdz + ggdz) / 2.; // -cdz/2.+0.1+gdz/2.; // ok // (-cdz+gdz)/2.; // not ok
Float_t startzposgas = startzposglas + gdz / 2. + ggdz / 2.; // -cdz/2.+0.1+gdz +ggdz/2.; // ok
// needed materials
TGeoMedium* glassPlateVolMed = gGeoMan->GetMedium(GlasMedium);
TGeoMedium* noActiveGasVolMed = gGeoMan->GetMedium(NoActivGasMedium);
TGeoMedium* activeGasVolMed = gGeoMan->GetMedium(ActivGasMedium);
TGeoMedium* electronicsVolMed = gGeoMan->GetMedium(ElectronicsMedium);
// define counter volume
TGeoBBox* counter_box = new TGeoBBox("", cdx / 2., cdy / 2., cdz / 2.);
TGeoVolume* counter = new TGeoVolume("counter", counter_box, noActiveGasVolMed);
counter->SetLineColor(kRed); // set line color for the counter
counter->SetTransparency(70); // set transparency for the TOF
// define single glass plate volume
TGeoBBox* glass_plate = new TGeoBBox("", gdx / 2., gdy / 2., gdz / 2.);
TGeoVolume* glass_plate_vol = new TGeoVolume("tof_glass", glass_plate, glassPlateVolMed);
glass_plate_vol->SetLineColor(kMagenta); // set line color for the glass plate
glass_plate_vol->SetTransparency(20); // set transparency for the TOF
// define single gas gap volume
TGeoBBox* gas_gap = new TGeoBBox("", ggdx / 2., ggdy / 2., ggdz / 2.);
TGeoVolume* gas_gap_vol = new TGeoVolume("Gap", gas_gap, activeGasVolMed);
gas_gap_vol->Divide("Cell", 1, nstrips, -ggdx / 2., 0);
gas_gap_vol->SetLineColor(kRed); // set line color for the gas gap
gas_gap_vol->SetTransparency(99); // set transparency for the TOF
// place 8 gas gaps and 9 glas plates in the counter
for (Int_t igap = 0; igap <= ngaps; igap++) {
// place (ngaps+1) glass plates
Float_t zpos_glas = startzposglas + igap * dzpos;
TGeoTranslation* glass_plate_trans = new TGeoTranslation("", 0., 0., zpos_glas);
counter->AddNode(glass_plate_vol, igap, glass_plate_trans);
// place ngaps gas gaps
if (igap < ngaps) {
Float_t zpos_gas = startzposgas + igap * dzpos;
TGeoTranslation* gas_gap_trans = new TGeoTranslation("", 0., 0., zpos_gas);
counter->AddNode(gas_gap_vol, igap, gas_gap_trans);
}
// cout <<"Zpos(Glas): "<< zpos_glas << endl;
// cout <<"Zpos(Gas): "<< zpos_gas << endl;
}
// create and place the electronics above and below the glas stack
TGeoBBox* pcb = new TGeoBBox("", dxe / 2., dye / 2., dze / 2.);
TGeoVolume* pcb_vol = new TGeoVolume("pcb", pcb, electronicsVolMed);
pcb_vol->SetLineColor(kYellow); // kCyan); // set line color for electronics
pcb_vol->SetTransparency(10); // set transparency for the TOF
for (Int_t l = 0; l < 2; l++) {
yele *= -1.;
TGeoTranslation* pcb_trans = new TGeoTranslation("", 0., yele, 0.);
counter->AddNode(pcb_vol, l, pcb_trans);
}
return counter;
}
TGeoVolume* create_tof_module(Int_t modType)
{
Int_t cType = CounterTypeInModule[modType];
Float_t dx = Module_Size_X[modType];
Float_t dy = Module_Size_Y[modType];
Float_t dz = Module_Size_Z[modType];
Float_t width_aluxl = Module_Thick_Alu_X_left;
Float_t width_aluxr = Module_Thick_Alu_X_right;
Float_t width_aluy = Module_Thick_Alu_Y;
Float_t width_aluz = Module_Thick_Alu_Z;
Float_t shift_gas_box = (Module_Thick_Alu_X_right - Module_Thick_Alu_X_left) / 2;
Float_t dxpos = CounterXDistance[modType];
Float_t startxpos = CounterXStartPosition[modType];
Float_t dzoff = CounterZDistance[modType];
Float_t rotangle = CounterRotationAngle[modType];
TGeoMedium* boxVolMed = gGeoMan->GetMedium(BoxVolumeMedium);
TGeoMedium* noActiveGasVolMed = gGeoMan->GetMedium(NoActivGasMedium);
TString moduleName = Form("module_%d", modType);
TGeoVolume* module = new TGeoVolumeAssembly(moduleName);
TGeoBBox* alu_box = new TGeoBBox("", dx / 2., dy / 2., dz / 2.);
TGeoVolume* alu_box_vol = new TGeoVolume("alu_box", alu_box, boxVolMed);
alu_box_vol->SetLineColor(kGreen); // set line color for the alu box
alu_box_vol->SetTransparency(20); // set transparency for the TOF
TGeoTranslation* alu_box_trans = new TGeoTranslation("", 0., 0., 0.);
module->AddNode(alu_box_vol, 0, alu_box_trans);
TGeoBBox* gas_box =
new TGeoBBox("", (dx - (width_aluxl + width_aluxr)) / 2., (dy - 2 * width_aluy) / 2., (dz - 2 * width_aluz) / 2.);
TGeoVolume* gas_box_vol = new TGeoVolume("gas_box", gas_box, noActiveGasVolMed);
gas_box_vol->SetLineColor(kYellow); // set line color for the gas box
gas_box_vol->SetTransparency(70); // set transparency for the TOF
TGeoTranslation* gas_box_trans = new TGeoTranslation("", shift_gas_box, 0., 0.);
alu_box_vol->AddNode(gas_box_vol, 0, gas_box_trans);
for (Int_t j = 0; j < 5; j++) { //loop over counters (modules)
Float_t zpos;
if (0 == modType) { zpos = dzoff *= -1; }
else {
zpos = 0.;
}
//cout << "counter z position " << zpos << endl;
TGeoTranslation* counter_trans = new TGeoTranslation("", startxpos + j * dxpos, 0.0, zpos);
TGeoRotation* counter_rot = new TGeoRotation();
counter_rot->RotateY(rotangle);
TGeoCombiTrans* counter_combi_trans = new TGeoCombiTrans(*counter_trans, *counter_rot);
gas_box_vol->AddNode(gCounter[cType], j, counter_combi_trans);
}
return module;
}
TGeoVolume* create_new_tof_module(Int_t modType)
{
Int_t cType = CounterTypeInModule[modType];
Float_t dx = Module_Size_X[modType];
Float_t dy = Module_Size_Y[modType];
Float_t dz = Module_Size_Z[modType];
Float_t width_aluxl = Module_Thick_Alu_X_left;
Float_t width_aluxr = Module_Thick_Alu_X_right;
Float_t width_aluy = Module_Thick_Alu_Y;
Float_t width_aluz = Module_Thick_Alu_Z;
Float_t shift_gas_box = (Module_Thick_Alu_X_right - Module_Thick_Alu_X_left) / 2;
Float_t dxpos = CounterXDistance[modType];
Float_t startxpos = CounterXStartPosition[modType];
Float_t dypos = CounterYDistance[modType];
Float_t startypos = CounterYStartPosition[modType];
Float_t dzoff = CounterZDistance[modType];
Float_t rotangle = CounterRotationAngle[modType];
TGeoMedium* boxVolMed = gGeoMan->GetMedium(BoxVolumeMedium);
TGeoMedium* noActiveGasVolMed = gGeoMan->GetMedium(NoActivGasMedium);
TString moduleName = Form("module_%d", modType);
TGeoBBox* module_box = new TGeoBBox("", dx / 2., dy / 2., dz / 2.);
TGeoVolume* module = new TGeoVolume(moduleName, module_box, boxVolMed);
module->SetLineColor(kGreen); // set line color for the alu box
module->SetTransparency(20); // set transparency for the TOF
TGeoBBox* gas_box =
new TGeoBBox("", (dx - (width_aluxl + width_aluxr)) / 2., (dy - 2 * width_aluy) / 2., (dz - 2 * width_aluz) / 2.);
TGeoVolume* gas_box_vol = new TGeoVolume("gas_box", gas_box, noActiveGasVolMed);
gas_box_vol->SetLineColor(kBlue); // set line color for the alu box
gas_box_vol->SetTransparency(50); // set transparency for the TOF
TGeoTranslation* gas_box_trans = new TGeoTranslation("", shift_gas_box, 0., 0.);
module->AddNode(gas_box_vol, 0, gas_box_trans);
for (Int_t j = 0; j < NCounterInModule[modType]; j++) { //loop over counters (modules)
//for (Int_t j=0; j< 1; j++){ //loop over counters (modules)
Float_t xpos, ypos, zpos;
if (0 == modType || 3 == modType || 4 == modType || 5 == modType) { zpos = dzoff *= -1; }
else {
zpos = CounterZStartPosition[modType] + j * dzoff;
}
//cout << "counter z position " << zpos << endl;
xpos = startxpos + j * dxpos;
ypos = startypos + j * dypos;
TGeoTranslation* counter_trans = new TGeoTranslation("", xpos, ypos, zpos);
TGeoRotation* counter_rot = new TGeoRotation();
counter_rot->RotateY(rotangle);
if ( CounterRotationAngleZ[modType] != 0. ) counter_rot->RotateZ(CounterRotationAngleZ[modType]);
TGeoCombiTrans* counter_combi_trans = new TGeoCombiTrans(*counter_trans, *counter_rot);
gas_box_vol->AddNode(gCounter[cType], j, counter_combi_trans);
}
return module;
}
TGeoVolume* create_tof_pole()
{
// needed materials
TGeoMedium* boxVolMed = gGeoMan->GetMedium(BoxVolumeMedium);
TGeoMedium* airVolMed = gGeoMan->GetMedium(KeepingVolumeMedium);
Float_t dx = Pole_Size_X;
Float_t dy = Pole_Size_Y;
Float_t dz = Pole_Size_Z;
Float_t width_alux = Pole_Thick_X;
Float_t width_aluy = Pole_Thick_Y;
Float_t width_aluz = Pole_Thick_Z;
TGeoVolume* pole = new TGeoVolumeAssembly("Pole");
TGeoBBox* pole_alu_box = new TGeoBBox("", dx / 2., dy / 2., dz / 2.);
TGeoVolume* pole_alu_vol = new TGeoVolume("pole_alu", pole_alu_box, boxVolMed);
pole_alu_vol->SetLineColor(kGreen); // set line color for the alu box
pole_alu_vol->SetTransparency(20); // set transparency for the TOF
TGeoTranslation* pole_alu_trans = new TGeoTranslation("", 0., 0., 0.);
pole->AddNode(pole_alu_vol, 0, pole_alu_trans);
Float_t air_dx = dx / 2. - width_alux;
Float_t air_dy = dy / 2. - width_aluy;
Float_t air_dz = dz / 2. - width_aluz;
// cout << "My pole." << endl;
if (air_dx <= 0.) cout << "ERROR - No air volume in pole X, size: " << air_dx << endl;
if (air_dy <= 0.) cout << "ERROR - No air volume in pole Y, size: " << air_dy << endl;
if (air_dz <= 0.) cout << "ERROR - No air volume in pole Z, size: " << air_dz << endl;
if ((air_dx > 0.) && (air_dy > 0.) && (air_dz > 0.)) // crate air volume only, if larger than zero
{
TGeoBBox* pole_air_box = new TGeoBBox("", air_dx, air_dy, air_dz);
// TGeoBBox* pole_air_box = new TGeoBBox("", dx/2.-width_alux, dy/2.-width_aluy, dz/2.-width_aluz);
TGeoVolume* pole_air_vol = new TGeoVolume("pole_air", pole_air_box, airVolMed);
pole_air_vol->SetLineColor(kYellow); // set line color for the alu box
pole_air_vol->SetTransparency(70); // set transparency for the TOF
TGeoTranslation* pole_air_trans = new TGeoTranslation("", 0., 0., 0.);
pole_alu_vol->AddNode(pole_air_vol, 0, pole_air_trans);
}
else
cout << "Skipping pole_air_vol, no thickness: " << air_dx << " " << air_dy << " " << air_dz << endl;
return pole;
}
TGeoVolume* create_tof_bar(Float_t dx, Float_t dy, Float_t dz)
{
// needed materials
TGeoMedium* boxVolMed = gGeoMan->GetMedium(BoxVolumeMedium);
TGeoMedium* airVolMed = gGeoMan->GetMedium(KeepingVolumeMedium);
Float_t width_alux = Pole_Thick_X;
Float_t width_aluy = Pole_Thick_Y;
Float_t width_aluz = Pole_Thick_Z;
TGeoVolume* bar = new TGeoVolumeAssembly("Bar");
TGeoBBox* bar_alu_box = new TGeoBBox("", dx / 2., dy / 2., dz / 2.);
TGeoVolume* bar_alu_vol = new TGeoVolume("bar_alu", bar_alu_box, boxVolMed);
bar_alu_vol->SetLineColor(kGreen); // set line color for the alu box
bar_alu_vol->SetTransparency(20); // set transparency for the TOF
TGeoTranslation* bar_alu_trans = new TGeoTranslation("", 0., 0., 0.);
bar->AddNode(bar_alu_vol, 0, bar_alu_trans);
TGeoBBox* bar_air_box = new TGeoBBox("", dx / 2. - width_alux, dy / 2. - width_aluy, dz / 2. - width_aluz);
TGeoVolume* bar_air_vol = new TGeoVolume("bar_air", bar_air_box, airVolMed);
bar_air_vol->SetLineColor(kYellow); // set line color for the alu box
bar_air_vol->SetTransparency(70); // set transparency for the TOF
TGeoTranslation* bar_air_trans = new TGeoTranslation("", 0., 0., 0.);
bar_alu_vol->AddNode(bar_air_vol, 0, bar_air_trans);
return bar;
}
void position_tof_poles(Int_t modType)
{
TGeoTranslation* pole_trans = NULL;
Int_t numPoles = 0;
for (Int_t i = 0; i < NumberOfPoles; i++) {
if (i < 2) {
pole_trans = new TGeoTranslation("", -Pole_Offset + 2.0, 0., Pole_ZPos[i]);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gPole, numPoles, pole_trans);
numPoles++;
}
else {
Float_t xPos = Pole_Offset + Pole_Size_X / 2. + Pole_Col[i] * DxColl;
Float_t zPos = Pole_ZPos[i];
pole_trans = new TGeoTranslation("", xPos, 0., zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gPole, numPoles, pole_trans);
numPoles++;
pole_trans = new TGeoTranslation("", -xPos, 0., zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gPole, numPoles, pole_trans);
numPoles++;
}
cout << " Position Pole " << numPoles << " at z=" << Pole_ZPos[i] << endl;
}
}
void position_tof_bars(Int_t modType)
{
TGeoTranslation* bar_trans = NULL;
Int_t numBars = 0;
Int_t i;
Float_t xPos;
Float_t yPos;
Float_t zPos;
for (i = 0; i < NumberOfBars; i++) {
xPos = Bar_XPos[i];
zPos = Bar_ZPos[i];
yPos = Pole_Size_Y / 2. + Bar_Size_Y / 2.;
bar_trans = new TGeoTranslation("", xPos, yPos, zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gBar[i], numBars, bar_trans);
numBars++;
bar_trans = new TGeoTranslation("", xPos, -yPos, zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gBar[i], numBars, bar_trans);
numBars++;
bar_trans = new TGeoTranslation("", -xPos, yPos, zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gBar[i], numBars, bar_trans);
numBars++;
bar_trans = new TGeoTranslation("", -xPos, -yPos, zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gBar[i], numBars, bar_trans);
numBars++;
}
cout << " Position Bar " << numBars << " at z=" << Bar_ZPos[i] << endl;
// horizontal frame bars
i = NumberOfBars;
NumberOfBars++;
// no bar
// gBar[i]=create_tof_bar(2.*xPos+Pole_Size_X,Bar_Size_Y,Bar_Size_Y);
zPos = Pole_ZPos[0] + Pole_Size_Z / 2.;
bar_trans = new TGeoTranslation("", 0., yPos, zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gBar[i], numBars, bar_trans);
numBars++;
bar_trans = new TGeoTranslation("", 0., -yPos, zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gBar[i], numBars, bar_trans);
numBars++;
}
void position_inner_tof_modules(Int_t modNType)
{
TGeoTranslation* module_trans = NULL;
// Int_t numModules=(Int_t)( (Inner_Module_Last_Y_Position-Inner_Module_First_Y_Position)/Module_Size_Y[modType])+1;
Float_t yPos = Inner_Module_First_Y_Position;
Int_t ii = 0;
Float_t xPos = Inner_Module_X_Offset;
Float_t zPos = Wall_Z_Position;
Pole_ZPos[NumberOfPoles] = zPos;
Pole_Col[NumberOfPoles] = 0;
NumberOfPoles++;
Float_t DzPos = 0.;
for (Int_t j = 0; j < modNType; j++) {
if (Module_Size_Z[j] > DzPos) { DzPos = Module_Size_Z[j]; }
}
Pole_ZPos[NumberOfPoles] = zPos + DzPos;
Pole_Col[NumberOfPoles] = 0;
NumberOfPoles++;
// Mar2019 setup
Int_t modNum[4] = {4 * 0};
const Int_t NModules = 8;
xPos = 0.;
yPos = 0.;
zPos = TOF_Z_Front;
const Int_t ModType[NModules] = {0, 0, 0, 0, 0, 0, 2, 2};
const Double_t ModDx[NModules] = {0., 0., 0., 0., 0., 0., 0., 0.};
//const Double_t ModDx[NModules]= { 1.5, 0., -1.5, 49.8, 55.8};
const Double_t ModDy[NModules] = {50., 0., -50.0, 27., -27.0, 0., 37.5, -37.5};
const Double_t ModDz[NModules] = {0., 0, 0, 20., 20., 92., 72., 72};
const Double_t ModAng[NModules] = {0., 0., 0., 0., 0., 0., 0., 0.};
TGeoRotation* module_rot = NULL;
TGeoCombiTrans* module_combi_trans = NULL;
/*
for (Int_t iMod = 0; iMod < NModules; iMod++) {
module_trans = new TGeoTranslation("", xPos + ModDx[iMod], yPos + ModDy[iMod], zPos + ModDz[iMod]);
module_rot = new TGeoRotation();
module_rot->RotateZ(ModAng[iMod]);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
if (iMod < 5) { gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[0], modNum, module_combi_trans); }
else {
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[2], modNum, module_combi_trans);
}
modNum++;
}
*/
for (Int_t iMod = 0; iMod < NModules; iMod++) {
module_trans = new TGeoTranslation("", xPos + ModDx[iMod], yPos + ModDy[iMod], zPos + ModDz[iMod]);
module_rot = new TGeoRotation();
module_rot->RotateX(ModAng[iMod]);
//Alex module_rot->RotateZ(ModAng[iMod]);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[ModType[iMod]], modNum[ModType[iMod]], module_combi_trans);
cout << "Placed Module " << modNum[ModType[iMod]] << ", Type " << ModType[iMod] << endl;
modNum[ModType[iMod]]++;
}
/*
module_trans = new TGeoTranslation("", xPos, 0, zPos+16.5);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_trans);
modNum++;
// module_trans = new TGeoTranslation("", xPos, 49+3, zPos);
module_trans = new TGeoTranslation("", xPos, 0, zPos+16.5+17.5);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_trans);
modNum++;
// module_trans = new TGeoTranslation("", xPos,-26, zPos+Module_Size_Z[modType]);
module_trans = new TGeoTranslation("", xPos, -49.8, zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_trans);
modNum++;
// module_trans = new TGeoTranslation("", xPos, 26, zPos+Module_Size_Z[modType]);
module_trans = new TGeoTranslation("", xPos, -49.8, zPos+16.5);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_trans);
modNum++;
*/
}
void position_Dia(Int_t modNType)
{
TGeoTranslation* module_trans = NULL;
TGeoRotation* module_rot = new TGeoRotation();
module_rot->RotateZ(Dia_rotate_Z);
TGeoCombiTrans* module_combi_trans = NULL;
// Int_t numModules=(Int_t)( (Inner_Module_Last_Y_Position-Inner_Module_First_Y_Position)/Module_Size_Y[modType])+1;
Float_t yPos = Dia_First_Y_Position;
Int_t ii = 0;
Float_t xPos = Dia_X_Offset;
Float_t zPos = Dia_Z_Position;
Int_t modNum = 0;
for (Int_t j = 0; j < modNType; j++) {
Int_t modType = Dia_Types[j];
zPos -= Dia_DZ;
for (Int_t i = 0; i < Dia_Number[j]; i++) {
ii++;
module_trans = new TGeoTranslation("", xPos, yPos, zPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_combi_trans);
modNum++;
}
}
}
void position_Star2(Int_t modNType)
{
TGeoTranslation* module_trans = NULL;
TGeoCombiTrans* module_combi_trans = NULL;
TGeoRotation* module_rot = NULL;
Float_t yPos = Star2_First_Y_Position;
Float_t zPos = Star2_First_Z_Position;
Int_t ii = 0;
Int_t modNum = 0;
for (Int_t j = 0; j < modNType; j++) {
Int_t modType = Star2_Types[j];
Float_t xPos = Star2_X_Offset[j];
module_rot = new TGeoRotation();
module_rot->RotateZ(Star2_rotate_Z[j]);
for (Int_t i = 0; i < Star2_Number[j]; i++) {
ii++;
module_trans = new TGeoTranslation("", xPos, yPos, zPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_combi_trans);
modNum++;
yPos += Star2_Delta_Y_Position;
zPos += Star2_Delta_Z_Position;
}
}
}
void position_Buc(Int_t modNType)
{
TGeoTranslation* module_trans = NULL;
TGeoRotation* module_rot = new TGeoRotation();
module_rot->RotateZ(Buc_rotate_Z);
module_rot->RotateY(Buc_rotate_Y);
TGeoCombiTrans* module_combi_trans = NULL;
Float_t yPos = Buc_First_Y_Position;
Float_t zPos = Buc_First_Z_Position;
Int_t ii = 0;
Int_t modNum = 0;
for (Int_t j = 0; j < modNType; j++) {
Int_t modType = Buc_Types[j];
Float_t xPos = Buc_X_Offset[j];
for (Int_t i = 0; i < Buc_Number[j]; i++) {
ii++;
module_trans = new TGeoTranslation("", xPos, yPos, zPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_combi_trans);
modNum++;
yPos += Buc_Delta_Y_Position;
zPos += Buc_Delta_Z_Position;
}
}
}
void position_cer_modules(Int_t modNType)
{
Int_t ii = 0;
Int_t modNum = 0;
for (Int_t j = 1; j < modNType; j++) {
Int_t modType = Cer_Types[j];
Float_t xPos = Cer_X_Position[j];
Float_t yPos = Cer_Y_Position[j];
Float_t zPos = Cer_Z_Position[j];
TGeoTranslation* module_trans = NULL;
TGeoRotation* module_rot = new TGeoRotation(Form("Cer%d", j), Cer_rotate_Z[j], -MeanTheta, 0.);
// module_rot->RotateZ(Cer_rotate_Z[j]);
TGeoCombiTrans* module_combi_trans = NULL;
for (Int_t i = 0; i < Cer_Number[j]; i++) {
ii++;
cout << "Position Ceramic Module " << i << " of " << Cer_Number[j] << " Type " << modType << " at X = " << xPos
<< ", Y = " << yPos << ", Z = " << zPos << endl;
// Front staggered module (Top if pair), top
module_trans = new TGeoTranslation("", xPos, yPos, zPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_combi_trans);
// modNum++;
}
}
}
void position_Testbox_MRPC4(Int_t modNType)
{
TGeoTranslation* module_trans = NULL;
TGeoRotation* module_rot = new TGeoRotation();
module_rot->RotateZ(Testbox_MRPC4_rotate_Z);
TGeoCombiTrans* module_combi_trans = NULL;
// Int_t numModules=(Int_t)( (Inner_Module_Last_Y_Position-Inner_Module_First_Y_Position)/Module_Size_Y[modType])+1;
Float_t yPos = Testbox_MRPC4_First_Y_Position;
Int_t ii = 0;
Float_t xPos = Testbox_MRPC4_X_Offset;
Float_t zPos = Testbox_MRPC4_Z_Position;
for (Int_t j = 0; j < modNType; j++) {
Int_t modType = Testbox_MRPC4_Types[j];
Int_t modNum = 0;
for (Int_t i = 0; i < Testbox_MRPC4_Number[j]; i++) {
ii++;
module_trans = new TGeoTranslation("", xPos, yPos, zPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_combi_trans);
modNum++;
}
}
}
void position_side_tof_modules(Int_t modNType)
{
TGeoTranslation* module_trans = NULL;
TGeoRotation* module_rot = new TGeoRotation();
module_rot->RotateZ(180.);
TGeoCombiTrans* module_combi_trans = NULL;
// Int_t numModules=(Int_t)( (Inner_Module_Last_Y_Position-Inner_Module_First_Y_Position)/Module_Size_Y[modType])+1;
Float_t yPos = 0.; //Inner_Module_First_Y_Position;
Int_t ii = 0;
for (Int_t j = 0; j < modNType; j++) {
Int_t modType = InnerSide_Module_Types[j];
Int_t modNum = 0;
for (Int_t i = 0; i < InnerSide_Module_Number[j]; i++) {
ii++;
cout << "InnerSide ii " << ii << " Last " << Last_Size_Y << "," << Last_Over_Y << endl;
Float_t DeltaY = Module_Size_Y[modType] + Last_Size_Y - 2. * (Module_Over_Y[modType] + Last_Over_Y);
if (ii > 1) { yPos += DeltaY; }
Last_Size_Y = Module_Size_Y[modType];
Last_Over_Y = Module_Over_Y[modType];
Float_t xPos = InnerSide_Module_X_Offset;
Float_t zPos = Wall_Z_Position;
cout << "Position InnerSide Module " << i << " of " << InnerSide_Module_Number[j] << " Type " << modType
<< " at Y = " << yPos << " Ysize = " << Module_Size_Y[modType] << " DeltaY = " << DeltaY << endl;
module_trans = new TGeoTranslation("", xPos, yPos, zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_trans);
modNum++;
module_trans = new TGeoTranslation("", -xPos, yPos, zPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_combi_trans);
modNum++;
if (ii > 1) {
module_trans = new TGeoTranslation("", xPos, -yPos, zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_trans);
modNum++;
module_trans = new TGeoTranslation("", -xPos, -yPos, zPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_combi_trans);
modNum++;
module_trans = new TGeoTranslation("", xPos, yPos - DeltaY / 2, zPos + Module_Size_Z[modType]);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_trans);
modNum++;
module_trans = new TGeoTranslation("", -xPos, yPos - DeltaY / 2, zPos + Module_Size_Z[modType]);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_combi_trans);
modNum++;
module_trans = new TGeoTranslation("", xPos, -(yPos - DeltaY / 2), zPos + Module_Size_Z[modType]);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_trans);
modNum++;
module_trans = new TGeoTranslation("", -xPos, -(yPos - DeltaY / 2), zPos + Module_Size_Z[modType]);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum, module_combi_trans);
modNum++;
}
}
}
}
void position_outer_tof_modules(Int_t nCol) //modType, Int_t col1, Int_t col2)
{
TGeoTranslation* module_trans = NULL;
TGeoRotation* module_rot = new TGeoRotation();
module_rot->RotateZ(180.);
TGeoCombiTrans* module_combi_trans = NULL;
// Int_t numModules=(Int_t)( (Outer_Module_Last_Y_Position-Outer_Module_First_Y_Position)/Module_Size_Y[modType])+1;
Int_t modNum[NofModuleTypes];
for (Int_t k = 0; k < NofModuleTypes; k++) {
modNum[k] = 0;
}
Float_t zPos = Wall_Z_Position;
for (Int_t j = 0; j < nCol; j++) {
Float_t xPos = Outer_Module_X_Offset + ((j + 1) * DxColl);
Last_Size_Y = 0.;
Last_Over_Y = 0.;
Float_t yPos = 0.;
Int_t ii = 0;
Float_t DzPos = 0.;
for (Int_t k = 0; k < Outer_Module_NTypes; k++) {
Int_t modType = Outer_Module_Types[k][j];
if (Module_Size_Z[modType] > DzPos) {
if (Outer_Module_Number[k][j] > 0) { DzPos = Module_Size_Z[modType]; }
}
}
zPos -= 2. * DzPos; //((j+1)*2*Module_Size_Z[modType]);
Pole_ZPos[NumberOfPoles] = zPos;
Pole_Col[NumberOfPoles] = j + 1;
NumberOfPoles++;
Pole_ZPos[NumberOfPoles] = zPos + DzPos;
Pole_Col[NumberOfPoles] = j + 1;
NumberOfPoles++;
//if (j+1==nCol) {
if (1) {
Pole_ZPos[NumberOfPoles] = Pole_ZPos[0];
Pole_Col[NumberOfPoles] = j + 1;
NumberOfPoles++;
Bar_Size_Z = Pole_ZPos[0] - zPos;
gBar[NumberOfBars] = create_tof_bar(Bar_Size_X, Bar_Size_Y, Bar_Size_Z);
Bar_ZPos[NumberOfBars] = zPos + Bar_Size_Z / 2. - Pole_Size_Z / 2.;
Bar_XPos[NumberOfBars] = xPos + Pole_Offset;
NumberOfBars++;
}
for (Int_t k = 0; k < Outer_Module_NTypes; k++) {
Int_t modType = Outer_Module_Types[k][j];
Int_t numModules = Outer_Module_Number[k][j];
cout << " Outer: position " << numModules << " of type " << modType << " in col " << j << " at z = " << zPos
<< ", DzPos = " << DzPos << endl;
for (Int_t i = 0; i < numModules; i++) {
ii++;
cout << "Outer ii " << ii << " Last " << Last_Size_Y << "," << Last_Over_Y << endl;
Float_t DeltaY = Module_Size_Y[modType] + Last_Size_Y - 2. * (Module_Over_Y[modType] + Last_Over_Y);
if (ii > 1) { yPos += DeltaY; }
Last_Size_Y = Module_Size_Y[modType];
Last_Over_Y = Module_Over_Y[modType];
cout << "Position Outer Module " << i << " of " << Outer_Module_Number[k][j] << " Type " << modType << "(#"
<< modNum[modType] << ") "
<< " at Y = " << yPos << " Ysize = " << Module_Size_Y[modType] << " DeltaY = " << DeltaY << endl;
module_trans = new TGeoTranslation("", xPos, yPos, zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum[modType], module_trans);
modNum[modType]++;
module_trans = new TGeoTranslation("", -xPos, yPos, zPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum[modType], module_combi_trans);
modNum[modType]++;
if (ii > 1) {
module_trans = new TGeoTranslation("", xPos, -yPos, zPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum[modType], module_trans);
modNum[modType]++;
module_trans = new TGeoTranslation("", -xPos, -yPos, zPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum[modType], module_combi_trans);
modNum[modType]++;
// second layer
module_trans = new TGeoTranslation("", xPos, yPos - DeltaY / 2., zPos + DzPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum[modType], module_trans);
modNum[modType]++;
module_trans = new TGeoTranslation("", -xPos, yPos - DeltaY / 2., zPos + DzPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum[modType], module_combi_trans);
modNum[modType]++;
module_trans = new TGeoTranslation("", xPos, -(yPos - DeltaY / 2.), zPos + DzPos);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum[modType], module_trans);
modNum[modType]++;
module_trans = new TGeoTranslation("", -xPos, -(yPos - DeltaY / 2.), zPos + DzPos);
module_combi_trans = new TGeoCombiTrans(*module_trans, *module_rot);
gGeoMan->GetVolume(geoVersionStand)->AddNode(gModules[modType], modNum[modType], module_combi_trans);
modNum[modType]++;
}
}
}
}
}
void dump_info_file()
{
TDatime datetime; // used to get timestamp
printf("writing info file: %s\n", FileNameInfo.Data());
FILE* ifile;
ifile = fopen(FileNameInfo.Data(), "w");
if (ifile == NULL) {
printf("error opening %s\n", FileNameInfo.Data());
exit(1);
}
fprintf(ifile, "#\n## %s information file\n#\n\n", geoVersion.Data());
fprintf(ifile, "# created %d\n\n", datetime.GetDate());
fprintf(ifile, "# TOF setup\n");
if (TOF_Z_Front == 450) fprintf(ifile, "SIS 100 hadron setup\n");
if (TOF_Z_Front == 600) fprintf(ifile, "SIS 100 electron\n");
if (TOF_Z_Front == 650) fprintf(ifile, "SIS 100 muon\n");
if (TOF_Z_Front == 880) fprintf(ifile, "SIS 300 electron\n");
if (TOF_Z_Front == 1020) fprintf(ifile, "SIS 300 muon\n");
fprintf(ifile, "\n");
// const Float_t TOF_Z_Back = Wall_Z_Position + 1.5 * Module_Size_Z[0]; // back of TOF wall
//
// fprintf(ifile, "# envelope\n");
// // Show extension of TOF
// fprintf(ifile, "%7.2f cm start of TOF (z)\n", TOF_Z_Front);
// fprintf(ifile, "%7.2f cm end of TOF (z)\n", TOF_Z_Back);
// fprintf(ifile, "\n");
// Layer thickness
fprintf(ifile, "# central tower position\n");
fprintf(ifile, "%7.2f cm center of staggered, front RPC cell at x=0\n", Wall_Z_Position);
fprintf(ifile, "\n");
fclose(ifile);
}