@@ -41,6 +41,108 @@ TRKLayer::TRKLayer(int layerNumber, std::string layerName, float rInn, float zLe
4141 LOGP (info, " Creating layer: id: {} rInner: {} rOuter: {} zLength: {} x2X0: {}" , mLayerNumber , mInnerRadius , mOuterRadius , mZ , mX2X0 );
4242}
4343
44+ TGeoVolume* TRKLayer::createSensor (std::string type, double width)
45+ {
46+ TGeoMedium* medSi = gGeoManager ->GetMedium (" TRK_SILICON$" );
47+ std::string sensName = Form (" %s%d" , GeometryTGeo::getTRKSensorPattern (), this ->mLayerNumber );
48+
49+ TGeoShape* sensor;
50+
51+ if (type == " cylinder" ) {
52+ sensor = new TGeoTube (mInnerRadius , mInnerRadius + mChipThickness , mZ / 2 );
53+ } else if (type == " flat" ) {
54+ if (width < 0 ) {
55+ LOGP (fatal, " Attempting to create sensor with invalid width" );
56+ }
57+ sensor = new TGeoBBox (width / 2 , mChipThickness / 2 , mZ / 2 );
58+ } else {
59+ LOGP (fatal, " Sensor of type '{}' is not implemented" , type);
60+ }
61+
62+ TGeoVolume* sensVol = new TGeoVolume (sensName.c_str (), sensor, medSi);
63+ sensVol->SetLineColor (kYellow );
64+
65+ return sensVol;
66+ };
67+
68+ TGeoVolume* TRKLayer::createChip (std::string type, double width)
69+ {
70+ TGeoMedium* medSi = gGeoManager ->GetMedium (" TRK_SILICON$" );
71+ std::string chipName = o2::trk::GeometryTGeo::getTRKChipPattern () + std::to_string (mLayerNumber );
72+
73+ TGeoShape* chip;
74+ TGeoVolume* sensVol;
75+
76+ if (type == " cylinder" ) {
77+ chip = new TGeoTube (mInnerRadius , mInnerRadius + mChipThickness , mZ / 2 );
78+ sensVol = createSensor (" cylinder" );
79+ } else if (type == " flat" ) {
80+ if (width < 0 ) {
81+ LOGP (fatal, " Attempting to create chip with invalid width" );
82+ }
83+ chip = new TGeoBBox (width / 2 , mChipThickness / 2 , mZ / 2 );
84+ sensVol = createSensor (" flat" , width);
85+ } else {
86+ LOGP (fatal, " Sensor of type '{}' is not implemented" , type);
87+ }
88+
89+ TGeoVolume* chipVol = new TGeoVolume (chipName.c_str (), chip, medSi);
90+ LOGP (info, " Inserting {} in {} " , sensVol->GetName (), chipVol->GetName ());
91+ chipVol->AddNode (sensVol, 1 , nullptr );
92+ chipVol->SetLineColor (kYellow );
93+
94+ return chipVol;
95+ }
96+
97+ TGeoVolume* TRKLayer::createStave (std::string type, double width)
98+ {
99+ TGeoMedium* medAir = gGeoManager ->GetMedium (" TRK_AIR$" );
100+ std::string staveName = o2::trk::GeometryTGeo::getTRKStavePattern () + std::to_string (mLayerNumber );
101+
102+ TGeoShape* stave;
103+ TGeoVolume* staveVol;
104+ TGeoVolume* chipVol;
105+
106+ if (type == " cylinder" ) {
107+ stave = new TGeoTube (mInnerRadius , mInnerRadius + mChipThickness , mZ / 2 );
108+ chipVol = createChip (" cylinder" );
109+ staveVol = new TGeoVolume (staveName.c_str (), stave, medAir);
110+ LOGP (info, " Inserting {} in {} " , chipVol->GetName (), staveVol->GetName ());
111+ staveVol->AddNode (chipVol, 1 , nullptr );
112+ } else if (type == " flat" ) {
113+ if (width < 0 ) {
114+ LOGP (fatal, " Attempting to create stave with invalid width" );
115+ }
116+ stave = new TGeoBBox (width / 2 , mChipThickness / 2 , mZ / 2 );
117+ chipVol = createChip (" flat" , width);
118+ staveVol = new TGeoVolume (staveName.c_str (), stave, medAir);
119+ LOGP (info, " Inserting {} in {} " , chipVol->GetName (), staveVol->GetName ());
120+ staveVol->AddNode (chipVol, 1 , nullptr );
121+ } else if (type == " staggered" ) {
122+ double width = mModuleWidth * 2 ; // Each stave has two modules (based on the LOI design)
123+ stave = new TGeoBBox (width / 2 , mChipThickness / 2 , mZ / 2 );
124+ TGeoVolume* chipVolLeft = createChip (" flat" , mModuleWidth );
125+ TGeoVolume* chipVolRight = createChip (" flat" , mModuleWidth );
126+ staveVol = new TGeoVolume (staveName.c_str (), stave, medAir);
127+
128+ TGeoCombiTrans* transLeft = new TGeoCombiTrans ();
129+ transLeft->SetTranslation (-mModuleWidth / 2 + 0.05 , 0 , 0 ); // 1mm overlap between the modules
130+ LOGP (info, " Inserting {} in {} " , chipVolLeft->GetName (), staveVol->GetName ());
131+ staveVol->AddNode (chipVolLeft, 0 , transLeft);
132+
133+ TGeoCombiTrans* transRight = new TGeoCombiTrans ();
134+ transRight->SetTranslation (mModuleWidth / 2 - 0.05 , 0.2 , 0 );
135+ LOGP (info, " Inserting {} in {} " , chipVolRight->GetName (), staveVol->GetName ());
136+ staveVol->AddNode (chipVolRight, 1 , transRight);
137+ } else {
138+ LOGP (fatal, " Chip of type '{}' is not implemented" , type);
139+ }
140+
141+ staveVol->SetLineColor (kYellow );
142+
143+ return staveVol;
144+ }
145+
44146void TRKLayer::createLayer (TGeoVolume* motherVolume)
45147{
46148 TGeoMedium* medSi = gGeoManager ->GetMedium (" TRK_SILICON$" );
@@ -56,28 +158,16 @@ void TRKLayer::createLayer(TGeoVolume* motherVolume)
56158 layerVol->SetLineColor (kYellow );
57159
58160 if (mLayout == eLayout::kCylinder ) {
59- TGeoTube* stave = new TGeoTube (mInnerRadius , mInnerRadius + mChipThickness , mZ / 2 );
60- TGeoTube* chip = new TGeoTube (mInnerRadius , mInnerRadius + mChipThickness , mZ / 2 );
61- TGeoTube* sensor = new TGeoTube (mInnerRadius , mInnerRadius + mChipThickness , mZ / 2 );
62-
63- TGeoVolume* sensVol = new TGeoVolume (sensName.c_str (), sensor, medSi);
64- sensVol->SetLineColor (kYellow );
65- TGeoVolume* chipVol = new TGeoVolume (chipName.c_str (), chip, medSi);
66- chipVol->SetLineColor (kYellow );
67- TGeoVolume* staveVol = new TGeoVolume (staveName.c_str (), stave, medSi);
68- staveVol->SetLineColor (kYellow );
69-
70- LOGP (info, " Inserting {} in {} " , sensVol->GetName (), chipVol->GetName ());
71- chipVol->AddNode (sensVol, 1 , nullptr );
72-
73- LOGP (info, " Inserting {} in {} " , chipVol->GetName (), staveVol->GetName ());
74- staveVol->AddNode (chipVol, 1 , nullptr );
75-
161+ auto staveVol = createStave (" cylinder" );
76162 LOGP (info, " Inserting {} in {} " , staveVol->GetName (), layerVol->GetName ());
77163 layerVol->AddNode (staveVol, 1 , nullptr );
78164 } else if (mLayout == eLayout::kTurboStaves ) {
79165 // Compute the number of staves
80- double width = mModuleWidth * 2 ; // Each stave has two modules (based on the LOI design)
166+ double width = mModuleWidth ; // Each stave has two modules (based on the LOI design)
167+ if (mInnerRadius > 25 ) {
168+ width *= 2 ; // Outer layers have two modules per stave
169+ }
170+
81171 int nStaves = (int )std::ceil (mInnerRadius * 2 * TMath::Pi () / width);
82172 nStaves += nStaves % 2 ; // Require an even number of staves
83173
@@ -91,29 +181,42 @@ void TRKLayer::createLayer(TGeoVolume* motherVolume)
91181 LOGP (info, " Creating a layer with {} staves and {} mm overlap" , nStaves, overlap * 10 );
92182
93183 for (int iStave = 0 ; iStave < nStaves; iStave++) {
94- TGeoBBox* sensor = new TGeoBBox (width / 2 , mChipThickness / 2 , mZ / 2 );
95- TGeoBBox* chip = new TGeoBBox (width / 2 , mChipThickness / 2 , mZ / 2 );
96- TGeoBBox* stave = new TGeoBBox (width / 2 , mChipThickness / 2 , mZ / 2 );
97-
98- TGeoVolume* sensVol = new TGeoVolume (sensName.c_str (), sensor, medSi);
99- sensVol->SetLineColor (kYellow );
100- TGeoVolume* chipVol = new TGeoVolume (chipName.c_str (), chip, medSi);
101- chipVol->SetLineColor (kYellow );
102- TGeoVolume* staveVol = new TGeoVolume (staveName.c_str (), stave, medSi);
103- staveVol->SetLineColor (kYellow );
184+ TGeoVolume* staveVol = createStave (" flat" , width);
104185
105186 // Put the staves in the correct position and orientation
106187 TGeoCombiTrans* trans = new TGeoCombiTrans ();
107188 double theta = 360 . * iStave / nStaves;
108- TGeoRotation* rot = new TGeoRotation (" rot" , theta + 90 + 2 , 0 , 0 );
189+ TGeoRotation* rot = new TGeoRotation (" rot" , theta + 90 + 3 , 0 , 0 );
109190 trans->SetRotation (rot);
110191 trans->SetTranslation (mInnerRadius * std::cos (2 . * TMath::Pi () * iStave / nStaves), mInnerRadius * std::sin (2 * TMath::Pi () * iStave / nStaves), 0 );
111192
112- LOGP (info, " Inserting {} in {} " , sensVol->GetName (), chipVol->GetName ());
113- chipVol->AddNode (sensVol, 1 , nullptr );
193+ LOGP (info, " Inserting {} in {} " , staveVol->GetName (), layerVol->GetName ());
194+ layerVol->AddNode (staveVol, iStave, trans);
195+ }
196+ } else if (mLayout == kStaggered ) {
197+ // Compute the number of staves
198+ double width = mModuleWidth * 2 ; // Each stave has two modules (based on the LOI design)
199+ int nStaves = (int )std::ceil (mInnerRadius * 2 * TMath::Pi () / width);
200+ nStaves += nStaves % 2 ; // Require an even number of staves
114201
115- LOGP (info, " Inserting {} in {} " , chipVol->GetName (), staveVol->GetName ());
116- staveVol->AddNode (chipVol, 1 , nullptr );
202+ // Compute the size of the overlap region
203+ double theta = 2 * TMath::Pi () / nStaves;
204+ double theta1 = std::atan (width / 2 / mInnerRadius );
205+ double st = std::sin (theta);
206+ double ct = std::cos (theta);
207+ double theta2 = std::atan ((mInnerRadius * st - width / 2 * ct) / (mInnerRadius * ct + width / 2 * st));
208+ double overlap = (theta1 - theta2) * mInnerRadius ;
209+ LOGP (info, " Creating a layer with {} staves and {} mm overlap" , nStaves, overlap * 10 );
210+
211+ for (int iStave = 0 ; iStave < nStaves; iStave++) {
212+ TGeoVolume* staveVol = createStave (" staggered" );
213+
214+ // Put the staves in the correct position and orientation
215+ TGeoCombiTrans* trans = new TGeoCombiTrans ();
216+ double theta = 360 . * iStave / nStaves;
217+ TGeoRotation* rot = new TGeoRotation (" rot" , theta + 90 , 0 , 0 );
218+ trans->SetRotation (rot);
219+ trans->SetTranslation (mInnerRadius * std::cos (2 . * TMath::Pi () * iStave / nStaves), mInnerRadius * std::sin (2 * TMath::Pi () * iStave / nStaves), 0 );
117220
118221 LOGP (info, " Inserting {} in {} " , staveVol->GetName (), layerVol->GetName ());
119222 layerVol->AddNode (staveVol, iStave, trans);
0 commit comments