BmnRoot 26.10.0-18-g4e3414f9
Software framework of the BM@N experiment
Loading...
Searching...
No Matches
create_rootgeom_SSD_v17a.C
Go to the documentation of this file.
1/******************************************************************************
2 ** Creation of STS geometry in ROOT format (TGeo).
3 **
4 ** @file create_stsgeo_v17a.C
5 ** @author Volker Friese <v.friese@gsi.de>
6 ** @since 15 June 2012
7 ** @date 09.05.2014
8 ** @author Tomas Balog <T.Balog@gsi.de>
9 **
10 ** v16c: like v16b, but senors of ladders beampipe next to beampipe
11 ** shifted closer to the pipe, like in the CAD model
12 ** v16b: like v16a, but yellow sensors removed
13 ** v16a: derived from v15c (no cones), but with sensor types renamed:
14 ** 2 -> 1, 3 -> 2, 4 -> 3, 5 -> 4, 1 -> 5
15 **
16 ** v15c: as v15b without cones
17 ** v15b: introduce modified carbon ladders from v13z
18 ** v15a: with flipped ladder orientation for stations 0,2,4,6 to match CAD design
19 **
20 ** TODO:
21 **
22 ** DONE:
23 ** v15b - use carbon macaroni as ladder support
24 ** v15b - introduce a small gap between lowest sensor and carbon ladder
25 ** v15b - build small cones for the first 2 stations
26 ** v15b - within a station the ladders of adjacent units should not touch eachother - set gkLadderGapZ to 10 mm
27 ** v15b - for all ladders set an even number of ladder elements
28 ** v15b - z offset of cones to ladders should not be 0.3 by default, but 0.26
29 ** v15b - within a station the ladders should be aligned in z, defined either by the unit or the ladder with most
30 * sensors
31 ** v15b - get rid of cone overlap in stations 7 and 8 - done by adapting rHole size
32 **
33 ** The geometry hierarachy is:
34 **
35 ** 1. Sensors (see function CreateSensors)
36 ** The sensors are the active volumes and the lowest geometry level.
37 ** They are built as TGeoVolumes, shape box, material silicon.
38 ** x size is determined by strip pitch 58 mu and 1024 strips
39 ** plus guard ring of 1.3 mm at each border -> 6.1992 cm.
40 ** Sensor type 1 is half of that (3.0792 cm).
41 ** y size is determined by strip length (2.2 / 4.2 / 6.3 cm) plus
42 ** guard ring of 1.3 mm at top and bottom -> 2.46 / 4.46 / 6.46 cm.
43 ** z size is a parameter, to be set by gkSensorThickness.
44 **
45 ** 2. Sectors (see function CreateSectors)
46 ** Sectors consist of several chained sensors. These are arranged
47 ** vertically on top of each other with a gap to be set by
48 ** gkChainGapY. Sectors are constructed as TGeoVolumeAssembly.
49 ** The sectors are auxiliary volumes used for proper placement
50 ** of the sensor(s) in the module. They do not show up in the
51 ** final geometry.
52 **
53 ** 3. Modules (see function ConstructModule)
54 ** A module is a readout unit, consisting of one sensor or
55 ** a chain of sensors (see sector) and a cable.
56 ** The cable extends from the top of the sector vertically to the
57 ** top of the halfladder the module is placed in. The cable and module
58 ** volume thus depend on the vertical position of the sector in
59 ** the halfladder. The cables consist of silicon with a thickness to be
60 ** set by gkCableThickness.
61 ** Modules are constructed as TGeoVolume, shape box, medium gStsMedium.
62 ** The module construction can be switched off (gkConstructCables)
63 ** to reproduce older geometries.
64 **
65 ** 4. Halfladders (see function ConstructHalfLadder)
66 ** A halfladder is a vertical assembly of several modules. The modules
67 ** are placed vertically such that their sectors overlap by
68 ** gkSectorOverlapY. They are displaced in z direction to allow for the
69 ** overlap in y by gkSectorGapZ.
70 ** The horizontal placement of modules in the halfladder can be choosen
71 ** to left aligned or right aligned, which only matters if sensors of
72 ** different x size are involved.
73 ** Halfladders are constructed as TGeoVolumeAssembly.
74 **
75 ** 5. Ladders (see function CreateLadders and ConstructLadder)
76 ** A ladder is a vertical assembly of two halfladders, and is such the
77 ** vertical building block of a station. The second (bottom) half ladder
78 ** is rotated upside down. The vertical arrangement is such that the
79 ** inner sectors of the two halfladders have the overlap gkSectorOverlapY
80 ** (function CreateLadder) or that there is a vertical gap for the beam
81 ** hole (function CreateLadderWithGap).
82 ** Ladders are constructed as TGeoVolumeAssembly.
83 **
84 ** 6. Stations (see function ConstructStation)
85 ** A station represents one layer of the STS geometry: one measurement
86 ** at (approximately) a given z position. It consist of several ladders
87 ** arranged horizontally to cover the acceptance.
88 ** The ladders are arranged such that there is a horizontal overlap
89 ** between neighbouring ladders (gkLadderOverLapX) and a vertical gap
90 ** to allow for this overlap (gkLadderGapZ). Each second ladder is
91 ** rotated around its y axis to face away from or into the beam.
92 ** Stations are constructed as TGeoVolumes, shape box minus tube (for
93 ** the beam hole), material gStsMedium.
94 **
95 ** 7. STS
96 ** The STS is a volume hosting the entire detectors system. It consists
97 ** of several stations located at different z positions.
98 ** The STS is constructed as TGeoVolume, shape box minus cone (for the
99 ** beam pipe), material gStsMedium. The size of the box is computed to
100 ** enclose all stations.
101 *****************************************************************************/
102
103// Remark: With the proper steering variables, this should exactly reproduce
104// the geometry version v11b of A. Kotynia's described in the ASCII format.
105// The only exception is a minimal difference in the z position of the
106// sectors/sensors. This is because of ladder types 2 and 4 containing the half
107// sensors around the beam hole (stations 1,2 and 3). In v11b, the two ladders
108// covering the beam hole cannot be transformed into each other by rotations,
109// but only by a reflection. This means they are constructionally different.
110// To avoid introducing another two ladder types, the difference in z position
111// was accepted.
112
113// Differences to v12:
114// gkChainGap reduced from 1 mm to 0
115// gkCableThickness increased from 100 mum to 200 mum (2 cables per module)
116// gkSectorOverlapY reduced from 3 mm to 2.4 mm
117// New sensor types 05 and 06
118// New sector types 07 and 08
119// Re-definiton of ladders (17 types instead of 8)
120// Re-definiton of station from new ladders
121
122#include "TGeoCompositeShape.h"
123#include "TGeoCone.h"
124#include "TGeoManager.h"
125#include "TGeoPara.h"
126#include "TGeoTrd2.h"
127#include "TGeoTube.h"
128
129#include <iomanip>
130#include <iostream>
131
132// forward declarations
136TGeoVolume* ConstructModule(const char* name, TGeoVolume* sector, Double_t cableLength);
137TGeoVolume* ConstructHalfLadder(const TString& name, Int_t nSectors, Int_t* sectorTypes, char align);
138TGeoVolume* ConstructLadder(Int_t LadderIndex,
139 TGeoVolume* halfLadderU,
140 TGeoVolume* halfLadderD,
141 Double_t gapY,
142 Double_t shiftZ);
143TGeoVolume* ConstructStation(Int_t iStation, Int_t nLadders, Int_t* ladderTypes, Double_t rHole);
144void CheckVolume(TGeoVolume* volume);
145void CheckVolume(TGeoVolume* volume, fstream& file);
147TGeoVolume* ConstructFrameElement(const TString& name, TGeoVolume* frameBoxVol, Double_t x);
150
151// ------------- Steering variables -----------------------------------
152
153// ---> Thickness of sensors [cm]
155
156// ---> Vertical gap between chained sensors [cm]
158
159// ---> Thickness of cables [cm]
161
162// ---> Vertical overlap of neighbouring sectors in a ladder [cm]
164
165// ---> Gap in z between neighbouring sectors in a ladder [cm]
167
168// ---> Horizontal overlap of neighbouring ladders [cm]
170
171// ---> Gap in z between neighbouring ladders [cm]
172const Double_t gkLadderGapZ = 1.00; // 0.00;
173
174// ---> Gap in z between lowest sector to carbon support structure [cm]
176
177// ---> Switch to construct / not to construct readout cables
179
180// ---> Switch to construct / not to construct frames
181const Bool_t gkConstructCones = kFALSE; // kTRUE; // switch this false by default for v15c and v16x
182const Bool_t gkConstructFrames = kTRUE; // kFALSE; // switch this true by default for v15c and v16x
185
186// ---> Size of the frame
189const Double_t gkFrameStep = 4.0; // size of frame cell along y direction
190
192 0.07; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015)
194 0.15; // properties of cylindrical carbon supports, see CBM-STS Integration Meeting (10 Jul 2015)
195
196// ----------------------------------------------------------------------------
197
198// -------------- Parameters of beam pipe in the STS region --------------
199// ---> Needed to compute stations and STS such as to avoid overlaps
200const Double_t gkPipeZ1 = 22.0;
201const Double_t gkPipeR1 = 1.8;
202const Double_t gkPipeZ2 = 50.0;
203const Double_t gkPipeR2 = 1.8;
204const Double_t gkPipeZ3 = 125.0;
205const Double_t gkPipeR3 = 5.5;
206
207// DE const Double_t gkPipeZ1 = 27.0;
208// DE const Double_t gkPipeR1 = 1.05;
209// DE const Double_t gkPipeZ2 = 160.0;
210// DE const Double_t gkPipeR2 = 3.25;
211// ----------------------------------------------------------------------------
212
213// ------------- Other global variables -----------------------------------
214// ---> STS medium (for every volume except silicon)
215TGeoMedium* gStsMedium = NULL; // will be set later
216// ---> TGeoManager (too lazy to write out 'Manager' all the time
217TGeoManager* gGeoMan = NULL; // will be set later
218// ----------------------------------------------------------------------------
219
220// ============================================================================
221// ====== Main function =====
222// ============================================================================
223
224void create_rootgeom_SSD_v17a(const char* geoTag = "v17a")
225{
226
227 // ------- Geometry file name (output) ----------------------------------
228 // TString geoFileName = "sts_";
229 // geoFileName = geoFileName + geoTag + ".geo.root";
230 // --------------------------------------------------------------------------
231
232 // ---- set working directory --------------------------------------------
233 TString gPath = gSystem->Getenv("VMCWORKDIR");
234
235 // ------- Geometry file name (output) ----------------------------------
236 const TString geoDetectorName = "SSD";
237 const TString geoDetectorVersion = geoTag;
238 const TString geoFileName = gPath + "/geometry/" + geoDetectorName + "_" + geoDetectorVersion + ".root";
239
240 // ------- Open info file -----------------------------------------------
241 TString infoFileName = geoFileName;
242 infoFileName.ReplaceAll("root", "info");
243 fstream infoFile;
244 infoFile.open(infoFileName.Data(), fstream::out);
245 infoFile << "SSD geometry created with create_rootgeom_SSD_v17a.C" << endl << endl;
246 infoFile << "Global variables: " << endl;
247 infoFile << "Sensor thickness = " << gkSensorThickness << " cm" << endl;
248 infoFile << "Vertical gap in sensor chain = " << gkChainGapY << " cm" << endl;
249 infoFile << "Vertical overlap of sensors = " << gkSectorOverlapY << " cm" << endl;
250 infoFile << "Gap in z between neighbour sensors = " << gkSectorGapZ << " cm" << endl;
251 infoFile << "Horizontal overlap of sensors = " << gkLadderOverlapX << " cm" << endl;
252 infoFile << "Gap in z between neighbour ladders = " << gkLadderGapZ << " cm" << endl;
254 infoFile << "Cable thickness = " << gkCableThickness << " cm" << endl;
255 else
256 infoFile << "No cables" << endl;
257 infoFile << endl;
258 infoFile << "Beam pipe: R1 = " << gkPipeR1 << " cm at z = " << gkPipeZ1 << " cm" << endl;
259 infoFile << "Beam pipe: R2 = " << gkPipeR2 << " cm at z = " << gkPipeZ2 << " cm" << endl;
260 infoFile << "Beam pipe: R3 = " << gkPipeR3 << " cm at z = " << gkPipeZ3 << " cm" << endl;
261 // --------------------------------------------------------------------------
262
263 // ------- Load media from media file -----------------------------------
264 FairGeoLoader* geoLoad = new FairGeoLoader("TGeo", "FairGeoLoader");
265 FairGeoInterface* geoFace = geoLoad->getGeoInterface();
266 TString geoPath = gSystem->Getenv("VMCWORKDIR");
267 TString medFile = geoPath + "/geometry/media.geo";
268 geoFace->setMediaFile(medFile);
269 geoFace->readMedia();
271 // --------------------------------------------------------------------------
272
273 // ----------------- Get and create the required media -----------------
274 FairGeoMedia* geoMedia = geoFace->getMedia();
275 FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder();
276
277 // ---> air
278 FairGeoMedium* mAir = geoMedia->getMedium("air");
279 if (!mAir)
280 Fatal("Main", "FairMedium air not found");
281 geoBuild->createMedium(mAir);
282 TGeoMedium* air = gGeoMan->GetMedium("air");
283 if (!air)
284 Fatal("Main", "Medium air not found");
285
286 // ---> silicon
287 FairGeoMedium* mSilicon = geoMedia->getMedium("silicon");
288 if (!mSilicon)
289 Fatal("Main", "FairMedium silicon not found");
290 geoBuild->createMedium(mSilicon);
291 TGeoMedium* silicon = gGeoMan->GetMedium("silicon");
292 if (!silicon)
293 Fatal("Main", "Medium silicon not found");
294
295 // ---> carbon
296 FairGeoMedium* mCarbon = geoMedia->getMedium("carbon");
297 if (!mCarbon)
298 Fatal("Main", "FairMedium carbon not found");
299 geoBuild->createMedium(mCarbon);
300 TGeoMedium* carbon = gGeoMan->GetMedium("carbon");
301 if (!carbon)
302 Fatal("Main", "Medium carbon not found");
303
304 // ---> STScable
305 FairGeoMedium* mSTScable = geoMedia->getMedium("STScable");
306 if (!mSTScable)
307 Fatal("Main", "FairMedium STScable not found");
308 geoBuild->createMedium(mSTScable);
309 TGeoMedium* STScable = gGeoMan->GetMedium("STScable");
310 if (!STScable)
311 Fatal("Main", "Medium STScable not found");
312
313 // ---
314 gStsMedium = air;
315 // --------------------------------------------------------------------------
316
317 // -------------- Create geometry and top volume -------------------------
318 gGeoMan = (TGeoManager*)gROOT->FindObject("FAIRGeom");
319 gGeoMan->SetName("STSgeom");
320 TGeoVolume* top = new TGeoVolumeAssembly("TOP");
321 gGeoMan->SetTopVolume(top);
322 // --------------------------------------------------------------------------
323
324 // -------------- Create media ------------------------------------------
325 /*
326 cout << endl;
327 cout << "===> Creating media....";
328 cout << CreateMedia();
329 cout << " media created" << endl;
330 TList* media = gGeoMan->GetListOfMedia();
331 for (Int_t iMedium = 0; iMedium < media->GetSize(); iMedium++ ) {
332 cout << "Medium " << iMedium << ": "
333 << ((TGeoMedium*) media->At(iMedium))->GetName() << endl;
334 }
335 gStsMedium = gGeoMan->GetMedium("air");
336 if ( ! gStsMedium ) Fatal("Main", "medium sts_air not found");
337 */
338 // --------------------------------------------------------------------------
339
340 // --------------- Create sensors ---------------------------------------
341 cout << endl << endl;
342 cout << "===> Creating sensors...." << endl << endl;
343 infoFile << endl << "Sensors: " << endl;
344 Int_t nSensors = CreateSensors();
345 for (Int_t iSensor = 1; iSensor <= nSensors; iSensor++) {
346 TString name = Form("Sensor%02d", iSensor);
347 TGeoVolume* sensor = gGeoMan->GetVolume(name);
348
349 // add color to sensors
350 if (iSensor == 1)
351 sensor->SetLineColor(kRed);
352 if (iSensor == 2)
353 sensor->SetLineColor(kGreen);
354 if (iSensor == 3)
355 sensor->SetLineColor(kBlue);
356 if (iSensor == 4)
357 sensor->SetLineColor(kAzure);
358 if (iSensor == 5)
359 sensor->SetLineColor(kYellow);
360 if (iSensor == 6)
361 sensor->SetLineColor(kYellow);
362 if (iSensor == 7)
363 sensor->SetLineColor(kYellow);
364
365 CheckVolume(sensor);
366 CheckVolume(sensor, infoFile);
367 }
368 // --------------------------------------------------------------------------
369
370 // ---------------- Create sectors --------------------------------------
371 cout << endl << endl;
372 cout << "===> Creating sectors...." << endl;
373 infoFile << endl << "Sectors: " << endl;
374 Int_t nSectors = CreateSectors();
375 for (Int_t iSector = 1; iSector <= nSectors; iSector++) {
376 cout << endl;
377 TString name = Form("Sector%02d", iSector);
378 TGeoVolume* sector = gGeoMan->GetVolume(name);
379 CheckVolume(sector);
380 CheckVolume(sector, infoFile);
381 }
382 // --------------------------------------------------------------------------
383
384 // ---------------- Create ladders --------------------------------------
385 cout << endl << endl;
386 cout << "===> Creating ladders...." << endl;
387 infoFile << endl << "Ladders:" << endl;
388 Int_t nLadders = CreateLadders();
389 for (Int_t iLadder = 1; iLadder <= nLadders; iLadder++) {
390 cout << endl;
391 TString name = Form("Ladder%02d", iLadder);
392 TGeoVolume* ladder = gGeoMan->GetVolume(name);
393 CheckVolume(ladder);
394 CheckVolume(ladder, infoFile);
395 CheckVolume(ladder->GetNode(0)->GetVolume(), infoFile);
396 }
397 // --------------------------------------------------------------------------
398
399 // ---------------- Create cones ----------------------------------------
400 Double_t coneDz = 1.64;
401 TGeoVolume* coneSmallVolum = ConstructSmallCone(coneDz);
402 if (!coneSmallVolum)
403 Fatal("ConstructSmallCone", "Volume Cone not found");
404 TGeoVolume* coneBigVolum = ConstructBigCone(coneDz);
405 if (!coneBigVolum)
406 Fatal("ConstructBigCone", "Volume Cone not found");
407 // --------------------------------------------------------------------------
408
409 // ---------------- Create stations -------------------------------------
410 cout << endl << endl;
411 cout << "===> Creating stations...." << endl;
412 infoFile << endl << "Stations: ";
413 Int_t angle = 0;
414 nLadders = 0;
415 Int_t ladderTypes[16];
416 TGeoBBox* statShape = NULL;
417 TGeoTranslation* statTrans = NULL;
418
419 TGeoVolume* mystation[8];
420
421 // Int_t statPos[8] = { 30, 40, 50, 60, 70, 80, 90, 100 }; // z positions of stations
422 Int_t statPos[8] = {5, 15, 25, 40, 50, 60, 70, 80}; // z positions of stations
423
424 Double_t rHole[8] = {2.0, 2.0, 2.0, 2.9, 3.7, 3.7, 4.2, 4.2}; // size of cutouts in stations
425
426 Int_t cone_size[8] = {0, 0, 0, 1, 1, 1, 1, 1}; // size of cones: 0 = small, 1 = large
427
428 Double_t cone_offset[2] = {0.305, 0.285};
429
430 Int_t allLadderTypes[8][16] = {
431 {0, 0, 0, 0, 10, 109, 9, 101, 1, 109, 9, 110, 0, 0, 0, 0}, // station 1
432 {0, 0, 111, 10, 110, 9, 109, 2, 102, 9, 109, 10, 110, 11, 0, 0}, // station 2
433 {0, 0, 14, 113, 12, 112, 12, 103, 3, 112, 12, 112, 13, 114, 0, 0}, // station 3
434 {0, 15, 114, 13, 112, 12, 112, 4, 104, 12, 112, 12, 113, 14, 115, 0}, // station 4
435 {0, 119, 18, 117, 17, 116, 16, 105, 5, 116, 16, 117, 17, 118, 19, 0}, // station 5
436 {0, 19, 118, 17, 117, 16, 116, 6, 106, 16, 116, 17, 117, 18, 119, 0}, // station 6
437 {21, 119, 18, 120, 20, 120, 20, 107, 7, 120, 20, 120, 20, 118, 19, 121}, // station 7
438 {119, 17, 123, 22, 122, 22, 122, 8, 108, 22, 122, 22, 122, 23, 117, 19}}; // station 8
439
440 Int_t allUnitTypes[16][16];
441
442 // unitTypes[0] = { 0, 0, 0, 0, 10, 0, 9, 0, 1, 0, 9, 0, 0, 0, 0, 0 }; // unit 0D
443 // unitTypes[1] = { 0, 0, 0, 0, 0, 109, 0, 101, 0, 109, 0, 110, 0, 0, 0, 0 }; // unit 1U
444 // unitTypes[2] = { 0, 0, 0, 10, 0, 9, 0, 2, 0, 9, 0, 10, 0, 11, 0, 0 }; // unit 1D
445 // unitTypes[3] = { 0, 0, 111, 0, 110, 0, 109, 0, 102, 0, 109, 0, 110, 0, 0, 0 }; // unit 2U
446 // unitTypes[4] = { 0, 0, 14, 0, 12, 0, 12, 0, 3, 0, 12, 0, 13, 0, 0, 0 }; // unit 2D
447 // unitTypes[5] = { 0, 0, 0, 113, 0, 112, 0, 103, 0, 112, 0, 112, 0, 114, 0, 0 }; // unit 3U
448 // unitTypes[6] = { 0, 15, 0, 13, 0, 12, 0, 4, 0, 12, 0, 12, 0, 14, 0, 0 }; // unit 3D
449 // unitTypes[7] = { 0, 0, 114, 0, 112, 0, 112, 0, 104, 0, 112, 0, 113, 0, 115, 0 }; // unit 4U
450 // unitTypes[8] = { 0, 0, 18, 0, 17, 0, 16, 0, 5, 0, 16, 0, 17, 0, 19, 0 }; // unit 4D
451 // unitTypes[9] = { 0, 119, 0, 117, 0, 116, 0, 105, 0, 116, 0, 117, 0, 118, 0, 0 }; // unit 5U
452 // unitTypes[10] = { 0, 19, 0, 17, 0, 16, 0, 6, 0, 16, 0, 17, 0, 18, 0, 0 }; // unit 5D
453 // unitTypes[11] = { 0, 0, 118, 0, 117, 0, 116, 0, 106, 0, 116, 0, 117, 0, 119, 0 }; // unit 6U
454 // unitTypes[12] = { 21, 0, 18, 0, 20, 0, 20, 0, 7, 0, 20, 0, 20, 0, 19, 0 }; // unit 6D
455 // unitTypes[13] = { 0, 119, 0, 120, 0, 120, 0, 107, 0, 120, 0, 120, 0, 118, 0, 121 }; // unit 7U
456 // unitTypes[14] = { 0, 17, 0, 22, 0, 22, 0, 8, 0, 22, 0, 22, 0, 23, 0, 19 }; // unit 7D
457 // unitTypes[15] = { 119, 0, 123, 0, 122, 0, 122, 0, 108, 0, 122, 0, 122, 0, 117, 0 }; // unit 8U
458
459 // generate unit
460 for (Int_t iUnit = 0; iUnit < 16; iUnit++)
461 for (Int_t iLadder = 0; iLadder < 16; iLadder++) {
462 allUnitTypes[iUnit][iLadder] = 0;
463 if ((iUnit % 2 == 0)
464 && (allLadderTypes[iUnit / 2][iLadder] < 100)) // if carbon structure is oriented upstream
465 allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit / 2][iLadder];
466 if ((iUnit % 2 == 1)
467 && (allLadderTypes[iUnit / 2][iLadder] >= 100)) // if carbon structure is oriented downstream
468 allUnitTypes[iUnit][iLadder] = allLadderTypes[iUnit / 2][iLadder];
469 }
470
471 // dump unit
472 for (Int_t iUnit = 0; iUnit < 16; iUnit++) {
473 cout << "DE unitTypes[" << iUnit << "] = { ";
474 for (Int_t iLadder = 0; iLadder < 16; iLadder++) {
475 cout << allUnitTypes[iUnit][iLadder];
476 if (iLadder < 15)
477 cout << ", ";
478 else
479 cout << " };";
480 }
481 cout << endl;
482 }
483
484 // --- Stations 01 - 08
485 for (Int_t iStation = 0; iStation < 8; iStation++) {
486 cout << endl;
487
488 nLadders = 0;
489 for (Int_t i = 0; i < 16; i++)
490 if (allLadderTypes[iStation][i] != 0) {
491 ladderTypes[nLadders] = allLadderTypes[iStation][i];
492 cout << "DE ladderTypes[" << nLadders << "] = " << allLadderTypes[iStation][i] << ";" << endl;
493 nLadders++;
494 }
495 mystation[iStation] = ConstructStation(iStation, nLadders, ladderTypes, rHole[iStation]);
496
497 if (gkConstructCones) {
498 if (iStation % 2 == 0)
499 angle = 90;
500 else
501 angle = -90;
502
503 // upstream
504 TGeoRotation* coneRot11 = new TGeoRotation;
505 coneRot11->RotateZ(angle);
506 coneRot11->RotateY(180);
507 // TGeoCombiTrans* conePosRot11 = new TGeoCombiTrans(name+"conePosRot2", 0., 0.,
508 // -coneDz-cone_offset[cone_size[iStation]]-gkLadderGapZ/2., coneRot11);
509 TGeoCombiTrans* conePosRot11 = new TGeoCombiTrans(
510 "conePosRot2", 0., 0., -coneDz - cone_offset[cone_size[iStation]] - gkLadderGapZ / 2., coneRot11);
511 if (cone_size[iStation] == 0)
512 mystation[iStation]->AddNode(coneSmallVolum, 1, conePosRot11);
513 else
514 mystation[iStation]->AddNode(coneBigVolum, 1, conePosRot11);
515
516 // downstream
517 TGeoRotation* coneRot12 = new TGeoRotation;
518 coneRot12->RotateZ(angle);
519 // TGeoCombiTrans* conePosRot12 = new TGeoCombiTrans(name+"conePosRot1", 0., 0.,
520 // coneDz+cone_offset[cone_size[iStation]]+gkLadderGapZ/2., coneRot12);
521 TGeoCombiTrans* conePosRot12 = new TGeoCombiTrans(
522 "conePosRot1", 0., 0., coneDz + cone_offset[cone_size[iStation]] + gkLadderGapZ / 2., coneRot12);
523 if (cone_size[iStation] == 0)
524 mystation[iStation]->AddNode(coneSmallVolum, 2, conePosRot12);
525 else
526 mystation[iStation]->AddNode(coneBigVolum, 2, conePosRot12);
527
528 mystation[iStation]->GetShape()->ComputeBBox();
529 }
530
531 CheckVolume(mystation[iStation]);
532 CheckVolume(mystation[iStation], infoFile);
533 infoFile << "Position z = " << statPos[iStation] << endl;
534 }
535
536 // --------------------------------------------------------------------------
537
538 // --------------- Create STS volume ------------------------------------
539 cout << endl << endl;
540 cout << "===> Creating STS...." << endl;
541
542 // --- Determine size of STS box
543 Double_t stsX = 0.;
544 Double_t stsY = 0.;
545 Double_t stsZ = 0.;
546 Double_t stsBorder = 2 * 5.; // 5 cm space for carbon ladders on each side
547 for (Int_t iStation = 1; iStation <= 8; iStation++) {
548 TString statName = Form("Station%02d", iStation);
549 TGeoVolume* station = gGeoMan->GetVolume(statName);
550 TGeoBBox* shape = (TGeoBBox*)station->GetShape();
551 stsX = TMath::Max(stsX, 2. * shape->GetDX());
552 stsY = TMath::Max(stsY, 2. * shape->GetDY());
553 cout << "Station " << iStation << ": Y " << stsY << endl;
554 }
555 // --- Some border around the stations
556 stsX += stsBorder;
557 stsY += stsBorder;
558 stsZ = (statPos[7] - statPos[0]) + stsBorder;
559 Double_t stsPosZ = 0.5 * (statPos[7] + statPos[0]);
560
561 // --- Create box around the stations
562 new TGeoBBox("stsBox", stsX / 2., stsY / 2., stsZ / 2.);
563 cout << "size of STS box: x " << stsX << " - y " << stsY << " - z " << stsZ << endl;
564
565 // --- Create cone hosting the beam pipe
566 // --- One straight section with constant radius followed by a cone
567 Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box
568 Double_t z2 = gkPipeZ2;
569 Double_t z3 = statPos[7] + 0.5 * stsBorder; // end of STS box
570 Double_t r1 = BeamPipeRadius(z1);
571 Double_t r2 = BeamPipeRadius(z2);
572 Double_t r3 = BeamPipeRadius(z3);
573 r1 += 0.01; // safety margin
574 r2 += 0.01; // safety margin
575 r3 += 0.01; // safety margin
576
577 cout << endl;
578 cout << z1 << " " << r1 << endl;
579 cout << z2 << " " << r2 << endl;
580 cout << z3 << " " << r3 << endl;
581
582 cout << endl;
583 cout << "station1 : " << BeamPipeRadius(statPos[0]) << endl;
584 cout << "station2 : " << BeamPipeRadius(statPos[1]) << endl;
585 cout << "station3 : " << BeamPipeRadius(statPos[2]) << endl;
586 cout << "station4 : " << BeamPipeRadius(statPos[3]) << endl;
587 cout << "station5 : " << BeamPipeRadius(statPos[4]) << endl;
588 cout << "station6 : " << BeamPipeRadius(statPos[5]) << endl;
589 cout << "station7 : " << BeamPipeRadius(statPos[6]) << endl;
590 cout << "station8 : " << BeamPipeRadius(statPos[7]) << endl;
591
592 // TGeoPcon* cutout = new TGeoPcon("stsCone", 0., 360., 3); // 2.*TMath::Pi(), 3);
593 // cutout->DefineSection(0, z1, 0., r1);
594 // cutout->DefineSection(1, z2, 0., r2);
595 // cutout->DefineSection(2, z3, 0., r3);
596 new TGeoTrd2("stsCone1", r1, r2, r1, r2, (z2 - z1) / 2. + .1); // add .1 in z length for a clean cutout
597 TGeoTranslation* trans1 = new TGeoTranslation("trans1", 0., 0., -(z3 - z1) / 2. + (z2 - z1) / 2.);
598 trans1->RegisterYourself();
599 new TGeoTrd2("stsCone2", r2, r3, r2, r3, (z3 - z2) / 2. + .1); // add .1 in z length for a clean cutout
600 TGeoTranslation* trans2 = new TGeoTranslation("trans2", 0., 0., +(z3 - z1) / 2. - (z3 - z2) / 2.);
601 trans2->RegisterYourself();
602
603 // DE Double_t z1 = statPos[0] - 0.5 * stsBorder; // start of STS box
604 // DE Double_t z2 = statPos[7] + 0.5 * stsBorder; // end of STS box
605 // DE Double_t slope = (gkPipeR2 - gkPipeR1) / (gkPipeZ2 - gkPipeZ1);
606 // DE Double_t r1 = gkPipeR1 + slope * (z1 - gkPipeZ1); // at start of STS
607 // DE Double_t r2 = gkPipeR1 + slope * (z2 - gkPipeZ1); // at end of STS
608 // DE r1 += 0.1; // safety margin
609 // DE r2 += 0.1; // safety margin
610 // DE // new TGeoCone("stsCone", stsZ/2., 0., r1, 0., r2);
611 // DE new TGeoTrd2("stsCone", r1, r2, r1, r2, stsZ/2.);
612
613 // --- Create STS volume
614 TString stsName = "sts_";
615 stsName += geoTag;
616 TGeoShape* stsShape = new TGeoCompositeShape("stsShape", "stsBox-stsCone1:trans1-stsCone2:trans2");
617 TGeoVolume* sts = new TGeoVolume(stsName.Data(), stsShape, gStsMedium);
618
619 // --- Place stations in the STS
620 for (Int_t iStation = 1; iStation <= 3; iStation++) {
621 TString statName = Form("Station%02d", iStation);
622 TGeoVolume* station = gGeoMan->GetVolume(statName);
623 Double_t posZ = statPos[iStation - 1] - stsPosZ;
624 // Double_t posZ = statPos[iStation-1];
625 TGeoTranslation* trans = new TGeoTranslation(0., 0., posZ);
626 sts->AddNode(station, 1, trans);
627 sts->GetShape()->ComputeBBox();
628 }
629 cout << endl;
630 CheckVolume(sts);
631 // --------------------------------------------------------------------------
632
633 // --------------- Finish -----------------------------------------------
634 TGeoTranslation* stsTrans = new TGeoTranslation(0., 0., stsPosZ);
635 // TGeoTranslation* stsTrans = new TGeoTranslation(0., 0., 0.);
636 top->AddNode(sts, 1, stsTrans);
637 top->GetShape()->ComputeBBox();
638 cout << endl << endl;
639 CheckVolume(top);
640 cout << endl << endl;
641 gGeoMan->CloseGeometry();
642 gGeoMan->CheckOverlaps(0.0001);
643 gGeoMan->PrintOverlaps();
644 gGeoMan->Test();
645
646 top->Export(geoFileName); // an alternative way of writing the sts volume
647
648 TFile* geoFile = new TFile(geoFileName, "UPDATE");
649 TGeoTranslation* sts_placement = new TGeoTranslation("ssd_trans", 0., 0., stsPosZ);
650 sts_placement->Write();
651
652 cout << endl;
653 cout << "Geometry " << top->GetName() << " written to " << geoFileName << endl;
654 geoFile->Close();
655
656 /*
657 TString geoFileName_ = geoFileName;
658 geoFileName_ = geoFileName_ + "_geo.root";
659
660 geoFile = new TFile(geoFileName_, "RECREATE");
661 gGeoMan->Write(); // use this is you want GeoManager format in the output
662 geoFile->Close();
663
664 TString geoFileName__ = geoFileName;
665 geoFileName_ = geoFileName__ + "-geo.root";
666 sts->Export(geoFileName_);
667
668 geoFile = new TFile(geoFileName_, "UPDATE");
669 stsTrans->Write();
670 geoFile->Close();
671 */
672
673 top->Draw("ogl");
674 gGeoManager->SetVisLevel(6);
675
676 infoFile.close();
677}
678// ============================================================================
679// ====== End of main function =====
680// ============================================================================
681
682// ****************************************************************************
683// ***** Definition of media, sensors, sectors and ladders *****
684// ***** *****
685// ***** Decoupled from main function for better readability *****
686// ****************************************************************************
687
688/** ===========================================================================
689 ** Create media
690 **
691 ** Currently created: air, active silicon, passive silion
692 **
693 ** Not used for the time being
694 **/
696{
697
698 Int_t nMedia = 0;
699 Double_t density = 0.;
700
701 // --- Material air
702 density = 1.205e-3; // [g/cm^3]
703 TGeoMixture* matAir = new TGeoMixture("sts_air", 3, density);
704 matAir->AddElement(14.0067, 7, 0.755); // Nitrogen
705 matAir->AddElement(15.999, 8, 0.231); // Oxygen
706 matAir->AddElement(39.948, 18, 0.014); // Argon
707
708 // --- Material silicon
709 density = 2.33; // [g/cm^3]
710 TGeoElement* elSi = gGeoMan->GetElementTable()->GetElement(14);
711 TGeoMaterial* matSi = new TGeoMaterial("matSi", elSi, density);
712
713 // --- Air (passive)
714 TGeoMedium* medAir = new TGeoMedium("air", nMedia++, matAir);
715 medAir->SetParam(0, 0.); // is passive
716 medAir->SetParam(1, 1.); // is in magnetic field
717 medAir->SetParam(2, 20.); // max. field [kG]
718 medAir->SetParam(6, 0.001); // boundary crossing precision [cm]
719
720 // --- Active silicon for sensors
721 TGeoMedium* medSiAct = new TGeoMedium("silicon", nMedia++, matSi);
722 medSiAct->SetParam(0, 1.); // is active
723 medSiAct->SetParam(1, 1.); // is in magnetic field
724 medSiAct->SetParam(2, 20.); // max. field [kG]
725 medSiAct->SetParam(6, 0.001); // boundary crossing precisison [cm]
726
727 // --- Passive silicon for cables
728 TGeoMedium* medSiPas = new TGeoMedium("carbon", nMedia++, matSi);
729 medSiPas->SetParam(0, 0.); // is passive
730 medSiPas->SetParam(1, 1.); // is in magnetic field
731 medSiPas->SetParam(2, 20.); // max. field [kG]
732 medSiPas->SetParam(6, 0.001); // boundary crossing precisison [cm]
733
734 return nMedia;
735}
736/** ======================================================================= **/
737
738/** ===========================================================================
739 ** Create sensors
740 **
741 ** Sensors are created as volumes with box shape and active silicon as medium.
742 ** Four kinds of sensors: 3.2x2.2, 6.2x2.2, 6.2x4.2, 6.2x6.2
743 **/
745{
746
747 Int_t nSensors = 0;
748
749 Double_t xSize = 0.;
750 Double_t ySize = 0.;
752 TGeoMedium* silicon = gGeoMan->GetMedium("silicon");
753
754 // --- Sensor type 01: Small sensor (6.2 cm x 2.2 cm)
755 xSize = 6.2092;
756 ySize = 2.2;
757 TGeoBBox* shape_sensor01 = new TGeoBBox("sensor01", xSize / 2., ySize / 2., zSize / 2.);
758 new TGeoVolume("Sensor01", shape_sensor01, silicon);
759 nSensors++;
760
761 // --- Sensor type 02: Medium sensor (6.2 cm x 4.2 cm)
762 xSize = 6.2092;
763 ySize = 4.2;
764 TGeoBBox* shape_sensor02 = new TGeoBBox("sensor02", xSize / 2., ySize / 2., zSize / 2.);
765 new TGeoVolume("Sensor02", shape_sensor02, silicon);
766 nSensors++;
767
768 // --- Sensor type 03: Big sensor (6.2 cm x 6.2 cm)
769 xSize = 6.2092;
770 ySize = 6.2;
771 TGeoBBox* shape_sensor03 = new TGeoBBox("sensor03", xSize / 2., ySize / 2., zSize / 2.);
772 new TGeoVolume("Sensor03", shape_sensor03, silicon);
773 nSensors++;
774
775 // --- Sensor type 04: Big sensor (6.2 cm x 12.4 cm)
776 xSize = 6.2092;
777 ySize = 12.4;
778 TGeoBBox* shape_sensor04 = new TGeoBBox("sensor04", xSize / 2., ySize / 2., zSize / 2.);
779 new TGeoVolume("Sensor04", shape_sensor04, silicon);
780 nSensors++;
781
782 // below are extra small sensors, those are not available in the CAD model
783
784 // --- Sensor Type 05: Half small sensor (4 cm x 2.5 cm)
785 xSize = 4.0;
786 ySize = 2.5;
787 TGeoBBox* shape_sensor05 = new TGeoBBox("sensor05", xSize / 2., ySize / 2., zSize / 2.);
788 new TGeoVolume("Sensor05", shape_sensor05, silicon);
789 nSensors++;
790
791 // --- Sensor type 06: Additional "in hole" sensor (3.1 cm x 4.2 cm)
792 xSize = 3.1;
793 ySize = 4.2;
794 TGeoBBox* shape_sensor06 = new TGeoBBox("sensor06", xSize / 2., ySize / 2., zSize / 2.);
795 new TGeoVolume("Sensor06", shape_sensor06, silicon);
796 nSensors++;
797
798 // --- Sensor type 07: Mini Medium sensor (1.5 cm x 4.2 cm)
799 xSize = 1.5;
800 ySize = 4.2;
801 TGeoBBox* shape_sensor07 = new TGeoBBox("sensor07", xSize / 2., ySize / 2., zSize / 2.);
802 new TGeoVolume("Sensor07", shape_sensor07, silicon);
803 nSensors++;
804
805 return nSensors;
806}
807/** ======================================================================= **/
808
809/** ===========================================================================
810 ** Create sectors
811 **
812 ** A sector is either a single sensor or several chained sensors.
813 ** It is implemented as TGeoVolumeAssembly.
814 ** Currently available:
815 ** - single sensors of type 1 - 4
816 ** - two chained sensors of type 4
817 ** - three chained sensors of type 4
818 **/
820{
821
822 Int_t nSectors = 0;
823
824 TGeoVolume* sensor01 = gGeoMan->GetVolume("Sensor01");
825 TGeoVolume* sensor02 = gGeoMan->GetVolume("Sensor02");
826 TGeoVolume* sensor03 = gGeoMan->GetVolume("Sensor03");
827 TGeoVolume* sensor04 = gGeoMan->GetVolume("Sensor04");
828 TGeoVolume* sensor05 = gGeoMan->GetVolume("Sensor05");
829 TGeoVolume* sensor06 = gGeoMan->GetVolume("Sensor06");
830 TGeoVolume* sensor07 = gGeoMan->GetVolume("Sensor07");
831 // TGeoBBox* box4 = (TGeoBBox*) sensor04->GetShape();
832
833 // --- Sector type 1: single sensor of type 1
834 TGeoVolumeAssembly* sector01 = new TGeoVolumeAssembly("Sector01");
835 sector01->AddNode(sensor01, 1);
836 sector01->GetShape()->ComputeBBox();
837 nSectors++;
838
839 // --- Sector type 2: single sensor of type 2
840 TGeoVolumeAssembly* sector02 = new TGeoVolumeAssembly("Sector02");
841 sector02->AddNode(sensor02, 1);
842 sector02->GetShape()->ComputeBBox();
843 nSectors++;
844
845 // --- Sector type 3: single sensor of type 3
846 TGeoVolumeAssembly* sector03 = new TGeoVolumeAssembly("Sector03");
847 sector03->AddNode(sensor03, 1);
848 sector03->GetShape()->ComputeBBox();
849 nSectors++;
850
851 // --- Sector type 4: single sensor of type 4
852 TGeoVolumeAssembly* sector04 = new TGeoVolumeAssembly("Sector04");
853 sector04->AddNode(sensor04, 1);
854 sector04->GetShape()->ComputeBBox();
855 nSectors++;
856
857 // --- Sector type 5: single sensor of type 5
858 TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05");
859 sector05->AddNode(sensor05, 1);
860 sector05->GetShape()->ComputeBBox();
861 nSectors++;
862
863 // --- Sector type 6: single sensor of type 6
864 TGeoVolumeAssembly* sector06 = new TGeoVolumeAssembly("Sector06");
865 sector06->AddNode(sensor06, 1);
866 sector06->GetShape()->ComputeBBox();
867 nSectors++;
868
869 // --- Sector type 7: single sensor of type 7
870 TGeoVolumeAssembly* sector07 = new TGeoVolumeAssembly("Sector07");
871 sector07->AddNode(sensor07, 1);
872 sector07->GetShape()->ComputeBBox();
873 nSectors++;
874
875 // // --- Sector type 5: two sensors of type 4
876 // TGeoVolumeAssembly* sector05 = new TGeoVolumeAssembly("Sector05");
877 // Double_t shift5 = 0.5 * gkChainGapY + box4->GetDY();
878 // TGeoTranslation* transD5 =
879 // new TGeoTranslation("td", 0., -1. * shift5, 0.);
880 // TGeoTranslation* transU5 =
881 // new TGeoTranslation("tu", 0., shift5, 0.);
882 // sector05->AddNode(sensor04, 1, transD5);
883 // sector05->AddNode(sensor04, 2, transU5);
884 // sector05->GetShape()->ComputeBBox();
885 // nSectors++;
886
887 return nSectors;
888}
889/** ======================================================================= **/
890
891/** ===========================================================================
892 ** Create ladders
893 **
894 ** Ladders are the building blocks of the stations. They contain
895 ** several modules placed one after the other along the z axis
896 ** such that the sectors are arranged vertically (with overlap).
897 **
898 ** A ladder is constructed out of two half ladders, the second of which
899 ** is rotated in the x-y plane by 180 degrees and displaced
900 ** in z direction.
901 **/
903{
904
905 Int_t nLadders = 0;
906
907 // --- Some variables
908 Int_t nSectors = 0;
909 Int_t sectorTypes[10];
910 TGeoBBox* shape = NULL;
911 TString s0name;
912 TString hlname;
913 char align;
914 TGeoVolume* s0vol = NULL;
915 TGeoVolume* halfLadderU = NULL;
916 TGeoVolume* halfLadderD = NULL;
917
918 // --- Ladders 01-23
919 Int_t allSectorTypes[23][6] = {{5, 1, 2, 3, 3, -1}, // ladder 01 - last column defines alignment of small sensors
920 {5, 1, 2, 3, 3, 0}, // ladder 02 - last column defines alignment of small sensors
921 {6, 2, 2, 3, 4, -1}, // ladder 03 - last column defines alignment of small sensors
922 {6, 2, 2, 3, 4, 0}, // ladder 04 - last column defines alignment of small sensors
923 {7, 2, 3, 4, 4, -1}, // ladder 05 - last column defines alignment of small sensors
924 {7, 2, 3, 4, 4, 0}, // ladder 06 - last column defines alignment of small sensors
925 {2, 2, 3, 4, 4, 0}, // ladder 07 - last column defines alignment of small sensors
926 {3, 4, 4, 4, 0, 0}, // ladder 08 - last column defines alignment of small sensors
927 {1, 1, 2, 3, 3, 0}, // ladder 09 - last column defines alignment of small sensors
928 {1, 1, 2, 2, 3, 0}, // ladder 10 - last column defines alignment of small sensors
929 {2, 2, 0, 0, 0, 0}, // ladder 11 - last column defines alignment of small sensors
930 {2, 2, 2, 3, 4, 0}, // ladder 12 - last column defines alignment of small sensors
931 {2, 2, 3, 4, 0, 0}, // ladder 13 - last column defines alignment of small sensors
932 {2, 3, 4, 0, 0, 0}, // ladder 14 - last column defines alignment of small sensors
933 {3, 3, 0, 0, 0, 0}, // ladder 15 - last column defines alignment of small sensors
934 {2, 2, 3, 4, 4, 0}, // ladder 16 - last column defines alignment of small sensors
935 {2, 3, 4, 4, 0, 0}, // ladder 17 - last column defines alignment of small sensors
936 {3, 4, 4, 0, 0, 0}, // ladder 18 - last column defines alignment of small sensors
937 {4, 4, 0, 0, 0, 0}, // ladder 19 - last column defines alignment of small sensors
938 {1, 2, 4, 4, 4, 0}, // ladder 20 - last column defines alignment of small sensors
939 {4, 0, 0, 0, 0, 0}, // ladder 21 - last column defines alignment of small sensors
940 {2, 3, 4, 4, 4, 0}, // ladder 22 - last column defines alignment of small sensors
941 {2, 3, 3, 4, 4, 0}}; // ladder 23 - last column defines alignment of small sensors
942
943 Double_t gapXYZ[23][3] = {{0., -gkSectorOverlapY, 0.}, // ladder 01
944 {0., -gkSectorOverlapY, 0.}, // ladder 02
945 {0., -gkSectorOverlapY, 0.}, // ladder 03
946 {0., -gkSectorOverlapY, 0.}, // ladder 04
947 {0., -gkSectorOverlapY, 0.}, // ladder 05
948 {0., -gkSectorOverlapY, 0.}, // ladder 06
949 {0., 8.80, 0.}, // ladder 07 - gapY = 2 * 4.40
950 {0., 9.14, 0.}, // ladder 08 - gapY = 2 * 4.57
951 {0., -gkSectorOverlapY, 0.}, // ladder 09
952 {0., -gkSectorOverlapY, 0.}, // ladder 10
953 {0., -gkSectorOverlapY, 0.}, // ladder 11
954 {0., -gkSectorOverlapY, 0.}, // ladder 12
955 {0., -gkSectorOverlapY, 0.}, // ladder 13
956 {0., -gkSectorOverlapY, 0.}, // ladder 14
957 {0., -gkSectorOverlapY, 0.}, // ladder 15
958 {0., -gkSectorOverlapY, 0.}, // ladder 16
959 {0., -gkSectorOverlapY, 0.}, // ladder 17
960 {0., -gkSectorOverlapY, 0.}, // ladder 18
961 {0., -gkSectorOverlapY, 0.}, // ladder 19
962 {0., -gkSectorOverlapY, 0.}, // ladder 20
963 {0., -gkSectorOverlapY, 0.}, // ladder 21
964 {0., -gkSectorOverlapY, 0.}, // ladder 22
965 {0., -gkSectorOverlapY, 0.}}; // ladder 23
966
967 // ========================================================================
968
969 // calculate Z shift for ladders with and without gaps in the center
970 s0name = Form("Sector%02d", allSectorTypes[0][0]);
971 s0vol = gGeoMan->GetVolume(s0name);
972 shape = (TGeoBBox*)s0vol->GetShape();
973
974 for (Int_t iLadder = 0; iLadder < 23; iLadder++) {
975 // if (iLadder <= 7)
976 if ((iLadder + 1 == 7) || (iLadder + 1 == 8)) // not for ladders with gap
977 gapXYZ[iLadder][2] = 0;
978 else
979 gapXYZ[iLadder][2] =
980 2. * shape->GetDZ() + gkSectorGapZ; // set displacement in z for overlapping half ladders
981 }
982
983 // ========================================================================
984
985 for (Int_t iLadder = 0; iLadder < 23; iLadder++) {
986 cout << endl;
987 nSectors = 0;
988 for (Int_t i = 0; i < 5; i++)
989 if (allSectorTypes[iLadder][i] != 0) {
990 sectorTypes[nSectors] = allSectorTypes[iLadder][i];
991 cout << "DE sectorTypes[" << nSectors << "] = " << allSectorTypes[iLadder][i] << ";" << endl;
992 nSectors++;
993 }
994
995 if (allSectorTypes[iLadder][5] == 0)
996 align = 'l';
997 else
998 align = 'r';
999 hlname = Form("HalfLadder%02du", iLadder + 1);
1000 halfLadderU = ConstructHalfLadder(hlname, nSectors, sectorTypes, align); // mirrored
1001
1002 if (allSectorTypes[iLadder][5] == 0)
1003 align = 'r';
1004 else
1005 align = 'l';
1006 hlname = Form("HalfLadder%02dd", iLadder + 1);
1007 halfLadderD = ConstructHalfLadder(hlname, nSectors, sectorTypes, align); // mirrored
1008
1009 ConstructLadder(iLadder + 1, halfLadderU, halfLadderD, gapXYZ[iLadder][1], gapXYZ[iLadder][2]);
1010 nLadders++;
1011 }
1012
1013 return nLadders;
1014}
1015/** ======================================================================= **/
1016
1017// ****************************************************************************
1018// ***** *****
1019// ***** Generic functions for the construction of STS elements *****
1020// ***** *****
1021// ***** module: volume (made of a sector and a cable) *****
1022// ***** haf ladder: assembly (made of modules) *****
1023// ***** ladder: assembly (made of two half ladders) *****
1024// ***** station: volume (made of ladders) *****
1025// ***** *****
1026// ****************************************************************************
1027
1028/** ===========================================================================
1029 ** Construct a module
1030 **
1031 ** A module is a sector plus the readout cable extending from the
1032 ** top of the sector. The cable is made from passive silicon.
1033 ** The cable has the same x size as the sector.
1034 ** Its thickness is given by the global variable gkCableThickness.
1035 ** The cable length is a parameter.
1036 ** The sensor(s) of the sector is/are placed directly in the module;
1037 ** the sector is just auxiliary for the proper placement.
1038 **
1039 ** Arguments:
1040 ** name volume name
1041 ** sector pointer to sector volume
1042 ** cableLength length of cable
1043 **/
1044TGeoVolume* ConstructModule(const char* name, TGeoVolume* sector, Double_t cableLength)
1045{
1046
1047 // --- Check sector volume
1048 if (!sector)
1049 Fatal("CreateModule", "Sector volume not found!");
1050
1051 // --- Get size of sector
1052 TGeoBBox* box = (TGeoBBox*)sector->GetShape();
1053 Double_t sectorX = 2. * box->GetDX();
1054 Double_t sectorY = 2. * box->GetDY();
1055 Double_t sectorZ = 2. * box->GetDZ();
1056
1057 // --- Get size of cable
1058 Double_t cableX = sectorX;
1059 Double_t cableY = cableLength;
1060 Double_t cableZ = gkCableThickness;
1061
1062 // --- Create module volume
1063 Double_t moduleX = TMath::Max(sectorX, cableX);
1064 Double_t moduleY = sectorY + cableLength;
1065 Double_t moduleZ = TMath::Max(sectorZ, cableZ);
1066 TGeoVolume* module = gGeoManager->MakeBox(name, gStsMedium, moduleX / 2., moduleY / 2., moduleZ / 2.);
1067
1068 // --- Position of sector in module
1069 // --- Sector is centred in x and z and aligned to the bottom
1070 Double_t sectorXpos = 0.;
1071 Double_t sectorYpos = 0.5 * (sectorY - moduleY);
1072 Double_t sectorZpos = 0.;
1073
1074 // --- Get sensor(s) from sector
1075 Int_t nSensors = sector->GetNdaughters();
1076 for (Int_t iSensor = 0; iSensor < nSensors; iSensor++) {
1077 TGeoNode* sensor = sector->GetNode(iSensor);
1078
1079 // --- Calculate position of sensor in module
1080 const Double_t* xSensTrans = sensor->GetMatrix()->GetTranslation();
1081 Double_t sensorXpos = 0.;
1082 Double_t sensorYpos = sectorYpos + xSensTrans[1];
1083 Double_t sensorZpos = 0.;
1084 TGeoTranslation* sensTrans = new TGeoTranslation("sensTrans", sensorXpos, sensorYpos, sensorZpos);
1085
1086 // --- Add sensor volume to module
1087 TGeoVolume* sensVol = sensor->GetVolume();
1088 module->AddNode(sensor->GetVolume(), iSensor + 1, sensTrans);
1089 module->GetShape()->ComputeBBox();
1090 }
1091
1092 // --- Create cable volume, if necessary, and place it in module
1093 // --- Cable is centred in x and z and aligned to the top
1094 if (gkConstructCables && cableLength > 0.0001) {
1095 TString cableName = TString(name) + "_cable";
1096 TGeoMedium* cableMedium = gGeoMan->GetMedium("STScable");
1097 if (!cableMedium)
1098 Fatal("CreateModule", "Medium STScable not found!");
1099 TGeoVolume* cable = gGeoManager->MakeBox(cableName.Data(), cableMedium, cableX / 2., cableY / 2., cableZ / 2.);
1100 // add color to cables
1101 cable->SetLineColor(kOrange);
1102 cable->SetTransparency(60);
1103 Double_t cableXpos = 0.;
1104 Double_t cableYpos = sectorY + 0.5 * cableY - 0.5 * moduleY;
1105 Double_t cableZpos = 0.;
1106 TGeoTranslation* cableTrans = new TGeoTranslation("cableTrans", cableXpos, cableYpos, cableZpos);
1107 module->AddNode(cable, 1, cableTrans);
1108 module->GetShape()->ComputeBBox();
1109 }
1110
1111 return module;
1112}
1113/** ======================================================================= **/
1114
1115/** ===========================================================================
1116 ** Construct a half ladder
1117 **
1118 ** A half ladder is a virtual volume (TGeoVolumeAssembly) consisting
1119 ** of several modules arranged on top of each other. The modules
1120 ** have a given overlap in y and a displacement in z to allow for the
1121 ** overlap.
1122 **
1123 ** The typ of sectors / modules to be placed must be specified:
1124 ** 1 = sensor01
1125 ** 2 = sensor02
1126 ** 3 = sensor03
1127 ** 4 = sensor04
1128 ** 5 = 2 x sensor04 (chained)
1129 ** 6 = 3 x sensor04 (chained)
1130 ** The cable is added automatically from the top of each sensor to
1131 ** the top of the half ladder.
1132 ** The alignment can be left (l) or right (r), which matters in the
1133 ** case of different x sizes of sensors (e.g. SensorType01).
1134 **
1135 ** Arguments:
1136 ** name volume name
1137 ** nSectors number of sectors
1138 ** sectorTypes array with sector types
1139 ** align horizontal alignment of sectors
1140 **/
1141TGeoVolume* ConstructHalfLadder(const TString& name, Int_t nSectors, Int_t* sectorTypes, char align)
1142{
1143
1144 // --- Create half ladder volume assembly
1145 TGeoVolumeAssembly* halfLadder = new TGeoVolumeAssembly(name);
1146
1147 // --- Determine size of ladder
1148 Double_t ladderX = 0.;
1149 Double_t ladderY = 0.;
1150 Double_t ladderZ = 0.;
1151 for (Int_t iSector = 0; iSector < nSectors; iSector++) {
1152 TString sectorName = Form("Sector%02d", sectorTypes[iSector]);
1153 TGeoVolume* sector = gGeoMan->GetVolume(sectorName);
1154 if (!sector)
1155 Fatal("ConstructHalfLadder", Form("Volume %s not found", sectorName.Data()));
1156 TGeoBBox* box = (TGeoBBox*)sector->GetShape();
1157 // --- Ladder x size equals largest sector x size
1158 ladderX = TMath::Max(ladderX, 2. * box->GetDX());
1159 // --- Ladder y size is sum of sector ysizes
1160 ladderY += 2. * box->GetDY();
1161 // --- Ladder z size is sum of sector z sizes
1162 ladderZ += 2. * box->GetDZ();
1163 }
1164 // --- Subtract overlaps in y
1165 ladderY -= Double_t(nSectors - 1) * gkSectorOverlapY;
1166 // --- Add gaps in z direction
1167 ladderZ += Double_t(nSectors - 1) * gkSectorGapZ;
1168
1169 // --- Create and place modules
1170 Double_t yPosSect = -0.5 * ladderY;
1171 Double_t zPosMod = -0.5 * ladderZ;
1172 for (Int_t iSector = 0; iSector < nSectors; iSector++) {
1173 TString sectorName = Form("Sector%02d", sectorTypes[iSector]);
1174 TGeoVolume* sector = gGeoMan->GetVolume(sectorName);
1175 TGeoBBox* box = (TGeoBBox*)sector->GetShape();
1176 Double_t sectorX = 2. * box->GetDX();
1177 Double_t sectorY = 2. * box->GetDY();
1178 Double_t sectorZ = 2. * box->GetDZ();
1179 yPosSect += 0.5 * sectorY; // Position of sector in ladder
1180 Double_t cableLength = 0.5 * ladderY - yPosSect - 0.5 * sectorY;
1181 TString moduleName = name + "_" + Form("Module%02d", sectorTypes[iSector]);
1182 TGeoVolume* module = ConstructModule(moduleName.Data(), sector, cableLength);
1183
1184 TGeoBBox* shapeMod = (TGeoBBox*)module->GetShape();
1185 Double_t moduleX = 2. * shapeMod->GetDX();
1186 Double_t moduleY = 2. * shapeMod->GetDY();
1187 Double_t moduleZ = 2. * shapeMod->GetDZ();
1188 Double_t xPosMod = 0.;
1189 if (align == 'l')
1190 xPosMod = 0.5 * (moduleX - ladderX); // left aligned
1191 else if (align == 'r')
1192 xPosMod = 0.5 * (ladderX - moduleX); // right aligned
1193 else
1194 xPosMod = 0.; // centred in x
1195 Double_t yPosMod = 0.5 * (ladderY - moduleY); // top aligned
1196 zPosMod += 0.5 * moduleZ;
1197 TGeoTranslation* trans = new TGeoTranslation("t", xPosMod, yPosMod, zPosMod);
1198 halfLadder->AddNode(module, iSector + 1, trans);
1199 halfLadder->GetShape()->ComputeBBox();
1200 yPosSect += 0.5 * sectorY - gkSectorOverlapY;
1201 zPosMod += 0.5 * moduleZ + gkSectorGapZ;
1202 }
1203
1204 CheckVolume(halfLadder);
1205 cout << endl;
1206
1207 return halfLadder;
1208}
1209/** ======================================================================= **/
1210
1211/** ===========================================================================
1212 ** Add a carbon support to a ladder
1213 **
1214 ** Arguments:
1215 ** LadderIndex ladder number
1216 ** ladder pointer to ladder
1217 ** xu size of halfladder
1218 ** ladderY height of ladder along y
1219 ** ladderZ thickness of ladder along z
1220 **/
1221void AddCarbonLadder(Int_t LadderIndex, TGeoVolume* ladder, Double_t xu, Double_t ladderY, Double_t ladderZ)
1222{
1223
1224 Int_t carbon_elem[23] = {11, 11, 16, 16, 20, 20, 22, 24, 11, 10, 6, 16,
1225 14, 12, 7, 20, 18, 16, 13, 22, 7, 24, 21}; // number of carbon elements in ladder types
1226
1227 // --- Some variables
1228 TString name = Form("Ladder%02d", LadderIndex);
1229 Int_t i;
1230 Double_t j;
1231
1232 // guess Int_t YnumOfFrameBoxes = (Int_t)(ladderY / gkFrameStep)+1; // calculate number of elements
1233 // guess if (LadderIndex == 1 || LadderIndex == 2) // set even number of ladder elements for these ladders in
1234 // station 1 and 2 guess YnumOfFrameBoxes--; guess// if (LadderIndex == 3 || LadderIndex == 4) // set even
1235 // number of ladder elements for these ladders in station 3 and 4 guess// YnumOfFrameBoxes++; guess
1236 // YnumOfFrameBoxes += YnumOfFrameBoxes % 2; // use even number of frame elements for all
1237 // ladders
1238
1239 Int_t YnumOfFrameBoxes = carbon_elem[LadderIndex - 1];
1240
1241 // cout << "DE: lad " << LadderIndex << " inum " << YnumOfFrameBoxes << endl;
1242
1243 // DEDE
1244 TGeoBBox* fullFrameShp = new TGeoBBox(name + "_FullFrameBox_shp", xu / 2., gkFrameStep / 2.,
1245 (xu / 2. + sqrt(2.) * gkFrameThickness / 2.) / 2.);
1246 // TGeoBBox* fullFrameShp = new TGeoBBox (name+"_FullFrameBox_shp", xu/2., gkFrameStep/2.,
1247 // (gkSectorGapZFrame+xu/2.+sqrt(2.)*gkFrameThickness/2.)/2.);
1248 TGeoVolume* fullFrameBoxVol = new TGeoVolume(name + "_FullFrameBox", fullFrameShp, gStsMedium);
1249
1250 // cout << "DE: frame Z size " << (xu/2.+sqrt(2.)*gkFrameThickness/2.) << " cm" << endl;
1251
1252 ConstructFrameElement("FrameBox", fullFrameBoxVol, xu / 2.);
1253 TGeoRotation* fullFrameRot = new TGeoRotation;
1254 fullFrameRot->RotateY(180);
1255
1256 Int_t inum = YnumOfFrameBoxes; // 6; // 9;
1257 for (i = 1; i <= inum; i++) {
1258 j = -(inum - 1) / 2. + (i - 1);
1259 // -(10-1)/2. +0 +10-1 -> -4.5 .. +4.5 -> -0.5, +0.5 (= 2)
1260 // -(11-1)/2. +0 +11-1 -> -5.0 .. +5.0 -> -1, 0, 1 (= 3)
1261 // cout << "DE: i " << i << " j " << j << endl;
1262
1263 if (LadderIndex <= 3) // central ladders in stations 1 to 3
1264 {
1265 if ((j >= -1) && (j <= 1)) // keep the inner 2 (even) or 3 (odd) elements free for the cone
1266 continue;
1267 } else if (LadderIndex <= 8) // central ladders in stations 4 to 8
1268 {
1269 if ((j >= -2) && (j <= 2)) // keep the inner 4 elements free for the cone
1270 continue;
1271 }
1272
1273 // DEDE
1274 ladder->AddNode(fullFrameBoxVol, i,
1275 new TGeoCombiTrans(name + "_FullFrameBox_posrot", 0., j * gkFrameStep,
1276 -ladderZ / 2. - (xu / 2. + sqrt(2.) * gkFrameThickness / 2.) / 2.,
1277 fullFrameRot));
1278 // ladder->AddNode(fullFrameBoxVol, i, new TGeoCombiTrans(name+"_FullFrameBox_posrot", 0., j*gkFrameStep,
1279 // -ladderZ/2.-(gkSectorGapZFrame+xu/2.+sqrt(2.)*gkFrameThickness/2.)/2., fullFrameRot));
1280 }
1281 // cout << endl;
1282 ladder->GetShape()->ComputeBBox();
1283}
1284/** ======================================================================= **/
1285
1286/** ===========================================================================
1287 ** Construct a ladder out of two half ladders with vertical gap
1288 **
1289 ** The second half ladder will be rotated by 180 degrees
1290 ** in the x-y plane. The two half ladders will be put on top of each
1291 ** other with a vertical gap.
1292 **
1293 ** Arguments:
1294 ** name volume name
1295 ** halfLadderU pointer to upper half ladder
1296 ** halfLadderD pointer to lower half ladder
1297 ** gapY vertical gap
1298 ** shiftZ relative displacement along the z axis
1299 **/
1300
1302 TGeoVolume* halfLadderU,
1303 TGeoVolume* halfLadderD,
1304 Double_t gapY,
1305 Double_t shiftZ)
1306{
1307
1308 // --- Some variables
1309 TGeoBBox* shape = NULL;
1310
1311 // --- Dimensions of half ladders
1312 shape = (TGeoBBox*)halfLadderU->GetShape();
1313 Double_t xu = 2. * shape->GetDX();
1314 Double_t yu = 2. * shape->GetDY();
1315 Double_t zu = 2. * shape->GetDZ();
1316
1317 shape = (TGeoBBox*)halfLadderD->GetShape();
1318 Double_t xd = 2. * shape->GetDX();
1319 Double_t yd = 2. * shape->GetDY();
1320 Double_t zd = 2. * shape->GetDZ();
1321
1322 // --- Create ladder volume assembly
1323 TString name = Form("Ladder%02d", LadderIndex);
1324 TGeoVolumeAssembly* ladder = new TGeoVolumeAssembly(name);
1325 Double_t ladderX = TMath::Max(xu, xd);
1326 Double_t ladderY = yu + yd + gapY;
1327 Double_t ladderZ = TMath::Max(zu, zd + shiftZ);
1328
1329 // --- Place half ladders
1330 Double_t xPosU = 0.; // centred in x
1331 Double_t yPosU = 0.5 * (ladderY - yu); // top aligned
1332 Double_t zPosU = 0.5 * (ladderZ - zu); // front aligned
1333 TGeoTranslation* tu = new TGeoTranslation("tu", xPosU, yPosU, zPosU);
1334 ladder->AddNode(halfLadderU, 1, tu);
1335
1336 Double_t xPosD = 0.; // centred in x
1337 Double_t yPosD = 0.5 * (yd - ladderY); // bottom aligned
1338 Double_t zPosD = 0.5 * (zd - ladderZ); // back aligned
1339 TGeoRotation* rd = new TGeoRotation();
1340 rd->RotateZ(180.);
1341 TGeoCombiTrans* cd = new TGeoCombiTrans(xPosD, yPosD, zPosD, rd);
1342 ladder->AddNode(halfLadderD, 2, cd);
1343 ladder->GetShape()->ComputeBBox();
1344
1345 // ---------------- Create and place frame boxes ------------------------
1346
1348 AddCarbonLadder(LadderIndex, ladder, xu, ladderY, ladderZ);
1349
1350 // --------------------------------------------------------------------------
1351
1352 return ladder;
1353}
1354/** ======================================================================= **/
1355
1356/** ===========================================================================
1357 ** Construct a station
1358 **
1359 ** The station volume is the minimal box comprising all ladders
1360 ** minus a tube accomodating the beam pipe.
1361 **
1362 ** The ladders are arranged horizontally from left to right with
1363 ** a given overlap in x.
1364 ** Every second ladder is slightly displaced upstream from the centre
1365 ** z plane and facing downstream, the others are slightly displaced
1366 ** downstream and facing upstream (rotated around the y axis).
1367 **
1368 ** Arguments:
1369 ** name volume name
1370 ** nLadders number of ladders
1371 ** ladderTypes array of ladder types
1372 ** rHole radius of inner hole
1373 **/
1374
1375TGeoVolume* ConstructStation(Int_t iStation, Int_t nLadders, Int_t* ladderTypes, Double_t rHole)
1376{
1377
1378 TString name;
1379 name = Form("Station%02d", iStation + 1); // 1,2,3,4,5,6,7,8
1380 // name = Form("Station%02d", iStation); // 0,1,2,3,4,5,6,7 - Station00 missing in output
1381
1382 // --- Some local variables
1383 TGeoShape* statShape = NULL;
1384 TGeoBBox* ladderShape = NULL;
1385 TGeoVolume* ladder = NULL;
1386 TString ladderName;
1387
1388 // --- Determine size of station from ladders
1389 Double_t statX = 0.;
1390 Double_t statY = 0.;
1391 Double_t statZeven = 0.;
1392 Double_t statZodd = 0.;
1393 Double_t statZ = 0.;
1394 for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) {
1395 Int_t ladderType = ladderTypes[iLadder] % 100;
1396 ladderName = Form("Ladder%02d", ladderType);
1397 ladder = gGeoManager->GetVolume(ladderName);
1398 if (!ladder)
1399 Fatal("ConstructStation", Form("Volume %s not found", ladderName.Data()));
1400 TGeoBBox* shape = (TGeoBBox*)ladder->GetShape();
1401 statX += 2. * shape->GetDX();
1402 statY = TMath::Max(statY, 2. * shape->GetDY());
1403 if (iLadder % 2)
1404 statZeven = TMath::Max(statZeven, 2. * shape->GetDZ());
1405 else
1406 statZodd = TMath::Max(statZodd, 2. * shape->GetDZ());
1407 }
1408 statX -= Double_t(nLadders - 1) * gkLadderOverlapX;
1409 statZ = statZeven + gkLadderGapZ + statZodd;
1410
1411 // --- Create station volume
1412 TString boxName(name);
1413 boxName += "_box";
1414
1415 cout << "before statZ/2.: " << statZ / 2. << endl;
1416 statZ = 2 * 4.5; // changed Z size of the station for cone and gkLadderGapZ
1417 cout << "fixed to statZ/2.: " << statZ / 2. << endl;
1418 TGeoBBox* statBox = new TGeoBBox(boxName, statX / 2., statY / 2., statZ / 2.);
1419
1420 TString tubName(name);
1421 tubName += "_tub";
1422 TString expression = boxName + "-" + tubName;
1423 // TGeoTube* statTub = new TGeoTube(tubName, 0., rHole, statZ/2.);
1424 // TGeoBBox* statTub = new TGeoBBox(tubName, rHole, rHole, statZ/2.);
1425 TGeoBBox* statTub = new TGeoBBox(tubName, rHole, rHole, statZ / 2. + .1); // .1 opens the hole in z direction
1426
1427 statShape = new TGeoCompositeShape(name, expression.Data());
1428 TGeoVolume* station = new TGeoVolume(name, statShape, gStsMedium);
1429
1430 Double_t subtractedVal;
1431
1432 // --- Place ladders in station
1433 cout << "xPos0: " << statX << endl;
1434 Double_t xPos = -0.5 * statX;
1435 cout << "xPos1: " << xPos << endl;
1436 Double_t yPos = 0.;
1437 Double_t zPos = 0.;
1438
1439 Double_t maxdz = 0.;
1440 for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) { // find maximum dz in this station
1441 Int_t ladderType = ladderTypes[iLadder] % 100;
1442 ladderName = Form("Ladder%02d", ladderType);
1443 ladder = gGeoManager->GetVolume(ladderName);
1444 TGeoBBox* shape = (TGeoBBox*)ladder->GetShape();
1445 if (maxdz < shape->GetDZ())
1446 maxdz = shape->GetDZ();
1447 }
1448
1449 for (Int_t iLadder = 0; iLadder < nLadders; iLadder++) {
1450 Int_t ladderType = ladderTypes[iLadder] % 100;
1451 ladderName = Form("Ladder%02d", ladderType);
1452 ladder = gGeoManager->GetVolume(ladderName);
1453 TGeoBBox* shape = (TGeoBBox*)ladder->GetShape();
1454 xPos += shape->GetDX();
1455 cout << "xPos2: " << xPos << endl;
1456 yPos = 0.; // vertically centred
1457 TGeoRotation* rot = new TGeoRotation();
1458
1460 // DEDE
1461 subtractedVal = sqrt(2.) * gkFrameThickness / 2. + shape->GetDX();
1462 // subtractedVal = 2*gkSectorGapZFrame + sqrt(2.)*gkFrameThickness/2. + shape->GetDX();
1463 else
1464 subtractedVal = 0.;
1465
1466 // zPos = 0.5 * gkLadderGapZ + (shape->GetDZ()-subtractedVal/2.); // non z-aligned ladders
1467 zPos = 0.5 * gkLadderGapZ + (2 * maxdz - shape->GetDZ() - subtractedVal / 2.); // z-aligned ladders
1468
1469 cout << "DE ladder" << ladderTypes[iLadder] % 100 << " dx: " << shape->GetDX() << " dy: " << shape->GetDY()
1470 << " dz: " << shape->GetDZ() << " max dz: " << maxdz << endl;
1471
1472 cout << "DE ladder" << ladderTypes[iLadder] % 100 << " fra: " << gkFrameThickness / 2.
1473 << " sub: " << subtractedVal << " zpo: " << zPos << endl
1474 << endl;
1475
1476 if (ladderTypes[iLadder] / 100 == 1) // flip some of the ladders to reproduce the CAD layout
1477 rot->RotateY(180.);
1478 else
1479 zPos = -zPos;
1480
1481 TGeoCombiTrans* trans = new TGeoCombiTrans(xPos, yPos, zPos, rot);
1482 station->AddNode(ladder, iLadder + 1, trans);
1483 station->GetShape()->ComputeBBox();
1484 xPos += shape->GetDX() - gkLadderOverlapX;
1485 cout << "xPos3: " << xPos << endl;
1486 }
1487
1488 return station;
1489}
1490/** ======================================================================= **/
1491
1492/** ===========================================================================
1493 ** Volume information for debugging
1494 **/
1496{
1497
1498 TGeoBBox* shape = (TGeoBBox*)volume->GetShape();
1499 cout << volume->GetName() << ": size " << fixed << setprecision(4) << setw(7) << 2. * shape->GetDX() << " x "
1500 << setw(7) << 2. * shape->GetDY() << " x " << setw(7) << 2. * shape->GetDZ();
1501 if (volume->IsAssembly())
1502 cout << ", assembly";
1503 else {
1504 if (volume->GetMedium())
1505 cout << ", medium " << volume->GetMedium()->GetName();
1506 else
1507 cout << ", " << "\033[31m" << " no medium" << "\033[0m";
1508 }
1509 cout << endl;
1510 if (volume->GetNdaughters()) {
1511 cout << "Daughters: " << endl;
1512 for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++) {
1513 TGeoNode* node = volume->GetNode(iNode);
1514 TGeoBBox* shape = (TGeoBBox*)node->GetVolume()->GetShape();
1515 cout << setw(15) << node->GetName() << ", size " << fixed << setprecision(3) << setw(6)
1516 << 2. * shape->GetDX() << " x " << setw(6) << 2. * shape->GetDY() << " x " << setw(6)
1517 << 2. * shape->GetDZ() << ", position ( ";
1518 TGeoMatrix* matrix = node->GetMatrix();
1519 const Double_t* pos = matrix->GetTranslation();
1520 cout << setfill(' ');
1521 cout << fixed << setw(8) << pos[0] << ", " << setw(8) << pos[1] << ", " << setw(8) << pos[2] << " )"
1522 << endl;
1523 }
1524 }
1525}
1526/** ======================================================================= **/
1527
1528/** ===========================================================================
1529 ** Volume information for output to file
1530 **/
1531void CheckVolume(TGeoVolume* volume, fstream& file)
1532{
1533
1534 if (!file)
1535 return;
1536
1537 TGeoBBox* shape = (TGeoBBox*)volume->GetShape();
1538 file << volume->GetName() << ": size " << fixed << setprecision(4) << setw(7) << 2. * shape->GetDX() << " x "
1539 << setw(7) << 2. * shape->GetDY() << " x " << setw(7) << 2. * shape->GetDZ();
1540 if (volume->IsAssembly())
1541 file << ", assembly";
1542 else {
1543 if (volume->GetMedium())
1544 file << ", medium " << volume->GetMedium()->GetName();
1545 else
1546 file << ", " << "\033[31m" << " no medium" << "\033[0m";
1547 }
1548 file << endl;
1549 if (volume->GetNdaughters()) {
1550 file << "Contains: ";
1551 for (Int_t iNode = 0; iNode < volume->GetNdaughters(); iNode++)
1552 file << volume->GetNode(iNode)->GetVolume()->GetName() << " ";
1553 file << endl;
1554 }
1555}
1556/** ======================================================================= **/
1557
1558/** ===========================================================================
1559 ** Calculate beam pipe outer radius for a given z
1560 **/
1562{
1563 if (z < gkPipeZ2)
1564 return gkPipeR1;
1565 Double_t slope = (gkPipeR3 - gkPipeR2) / (gkPipeZ3 - gkPipeZ2);
1566 return gkPipeR2 + slope * (z - gkPipeZ2);
1567}
1568/** ======================================================================= **/
1569
1570/** ======================================================================= **/
1572{
1573 // --- Material of the frames
1574 TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon");
1575
1576 TGeoBBox* frameVertPillarShp;
1577
1578 Double_t t = gkFrameThickness / 2.;
1579
1580 // --- Main vertical pillars
1581 // TGeoBBox* frameVertPillarShp = new TGeoBBox(name + "_vertpillar_shape", t, gkFrameStep/2., t); // square
1582 // crossection, along y
1583 // TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial);
1584 // frameVertPillarVol->SetLineColor(kGreen);
1585 // frameBoxVol->AddNode(frameVertPillarVol, 1, new TGeoTranslation(name + "_vertpillar_pos_1", x-t, 0.,
1586 //-(x+sqrt(2.)*t-2.*t)/2.)); frameBoxVol->AddNode(frameVertPillarVol, 2, new TGeoTranslation(name +
1587 //"_vertpillar_pos_2", -(x-t), 0., -(x+sqrt(2.)*t-2.*t)/2.));
1588
1590 // TGeoBBox* frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", 0, t, gkFrameStep/2.); //
1591 // circle crossection, along z
1592 frameVertPillarShp = new TGeoTube(name + "_vertpillar_shape", gkCylinderDiaInner / 2., gkCylinderDiaOuter / 2.,
1593 gkFrameStep / 2.); // circle crossection, along z
1594 else
1595 frameVertPillarShp =
1596 new TGeoBBox(name + "_vertpillar_shape", t, t, gkFrameStep / 2.); // square crossection, along z
1597 TGeoVolume* frameVertPillarVol = new TGeoVolume(name + "_vertpillar", frameVertPillarShp, framesMaterial);
1598 frameVertPillarVol->SetLineColor(kGreen);
1599
1600 TGeoRotation* xRot90 = new TGeoRotation;
1601 xRot90->RotateX(90.);
1602 frameBoxVol->AddNode(
1603 frameVertPillarVol, 1,
1604 new TGeoCombiTrans(name + "_vertpillar_pos_1", x - t, 0., -(x + sqrt(2.) * t - 2. * t) / 2., xRot90));
1605 frameBoxVol->AddNode(
1606 frameVertPillarVol, 2,
1607 new TGeoCombiTrans(name + "_vertpillar_pos_2", -(x - t), 0., -(x + sqrt(2.) * t - 2. * t) / 2., xRot90));
1608
1609 // TGeoRotation* vertRot = new TGeoRotation(name + "_vertpillar_rot_1", 90., 45., -90.);
1610 TGeoRotation* vertRot = new TGeoRotation;
1611 vertRot->RotateX(90.);
1612 vertRot->RotateY(45.);
1613 frameBoxVol->AddNode(frameVertPillarVol, 3,
1614 new TGeoCombiTrans(name + "_vertpillar_pos_3", 0., 0., (x - sqrt(2.) * t) / 2., vertRot));
1615
1616 // --- Small horizontal pillar
1617 TGeoBBox* frameHorPillarShp =
1618 new TGeoBBox(name + "_horpillar_shape", x - 2. * t, gkThinFrameThickness / 2., gkThinFrameThickness / 2.);
1619 TGeoVolume* frameHorPillarVol = new TGeoVolume(name + "_horpillar", frameHorPillarShp, framesMaterial);
1620 frameHorPillarVol->SetLineColor(kCyan);
1621 frameBoxVol->AddNode(frameHorPillarVol, 1,
1622 new TGeoTranslation(name + "_horpillar_pos_1", 0.,
1623 -gkFrameStep / 2. + gkThinFrameThickness / 2.,
1624 -(x + sqrt(2.) * t - 2. * t) / 2.));
1625
1627
1628 // --- Small sloping pillar
1629 TGeoPara* frameSlopePillarShp =
1630 new TGeoPara(name + "_slopepillar_shape", (x - 2. * t) / TMath::Cos(31.4 / 180. * TMath::Pi()),
1631 gkThinFrameThickness / 2., gkThinFrameThickness / 2., 31.4, 0., 90.);
1632 TGeoVolume* frameSlopePillarVol = new TGeoVolume(name + "_slopepillar", frameSlopePillarShp, framesMaterial);
1633 frameSlopePillarVol->SetLineColor(kCyan);
1634 TGeoRotation* slopeRot = new TGeoRotation(name + "_slopepillar_rot_1", 0., 0., 31.4);
1635 TGeoCombiTrans* slopeTrRot =
1636 new TGeoCombiTrans(name + "_slopepillar_posrot_1", 0., 0., -(x + sqrt(2.) * t - 2. * t) / 2., slopeRot);
1637
1638 frameBoxVol->AddNode(frameSlopePillarVol, 1, slopeTrRot);
1639
1640 Double_t angl = 23.;
1641 // --- Small sub pillar
1642 TGeoPara* frameSubPillarShp = new TGeoPara(
1643 name + "_subpillar_shape", (sqrt(2) * (x / 2. - t) - t / 2.) / TMath::Cos(angl / 180. * TMath::Pi()),
1644 gkThinFrameThickness / 2., gkThinFrameThickness / 2., angl, 0., 90.);
1645 TGeoVolume* frameSubPillarVol = new TGeoVolume(name + "_subpillar", frameSubPillarShp, framesMaterial);
1646 frameSubPillarVol->SetLineColor(kMagenta);
1647
1648 Double_t posZ = t * (1. - 3. / (2. * sqrt(2.)));
1649
1650 // one side of X direction
1651 TGeoRotation* subRot1 = new TGeoRotation(name + "_subpillar_rot_1", 90., 45., -90. + angl);
1652 TGeoCombiTrans* subTrRot1 =
1653 new TGeoCombiTrans(name + "_subpillar_posrot_1", -(-x / 2. + t - t / (2. * sqrt(2.))), 1., posZ, subRot1);
1654
1655 TGeoRotation* subRot2 = new TGeoRotation(name + "_subpillar_rot_2", 90., -90. - 45., -90. + angl);
1656 TGeoCombiTrans* subTrRot2 =
1657 new TGeoCombiTrans(name + "_subpillar_posrot_2", -(-x / 2. + t - t / (2. * sqrt(2.))), -1., posZ, subRot2);
1658
1659 // other side of X direction
1660 TGeoRotation* subRot3 = new TGeoRotation(name + "_subpillar_rot_3", 90., 90. + 45., -90. + angl);
1661 TGeoCombiTrans* subTrRot3 =
1662 new TGeoCombiTrans(name + "_subpillar_posrot_3", -x / 2. + t - t / (2. * sqrt(2.)), 1., posZ, subRot3);
1663
1664 TGeoRotation* subRot4 = new TGeoRotation(name + "_subpillar_rot_4", 90., -45., -90. + angl);
1665 TGeoCombiTrans* subTrRot4 =
1666 new TGeoCombiTrans(name + "_subpillar_posrot_4", -x / 2. + t - t / (2. * sqrt(2.)), -1., posZ, subRot4);
1667
1668 frameBoxVol->AddNode(frameSubPillarVol, 1, subTrRot1);
1669 frameBoxVol->AddNode(frameSubPillarVol, 2, subTrRot2);
1670 frameBoxVol->AddNode(frameSubPillarVol, 3, subTrRot3);
1671 frameBoxVol->AddNode(frameSubPillarVol, 4, subTrRot4);
1672 // frameBoxVol->GetShape()->ComputeBBox();
1673 }
1674
1675 return frameBoxVol;
1676}
1677/** ======================================================================= **/
1678
1679/** ======================================================================= **/
1681{
1682 // --- Material of the frames
1683 TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon");
1684
1685 // --- Outer cone
1686 // TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 6., 7.6, 6., 6.04, 0., 180.);
1687 // TGeoBBox* B = new TGeoBBox ("B", 8., 6., 10.);
1688
1689 Double_t radius = 3.0;
1690 Double_t thickness = 0.04; // 0.4 mm
1691 // TGeoConeSeg* A = new TGeoConeSeg ("A", coneDz, 3., 3.2, 3., 3.2, 0., 180.);
1692 TGeoConeSeg* A = new TGeoConeSeg("A", coneDz, radius, radius + thickness, radius, radius + thickness, 0., 180.);
1693 TGeoBBox* B = new TGeoBBox("B", 8., 6., 10.);
1694
1695 TGeoCombiTrans* M = new TGeoCombiTrans("M");
1696 M->RotateX(45.);
1697 M->SetDy(-5.575);
1698 M->SetDz(6.935);
1699 M->RegisterYourself();
1700
1701 TGeoShape* coneShp = new TGeoCompositeShape("Cone_shp", "A-B:M");
1702 TGeoVolume* coneVol = new TGeoVolume("Cone", coneShp, framesMaterial);
1703 coneVol->SetLineColor(kGreen);
1704 // coneVol->RegisterYourself();
1705
1706 // // --- Inner cone
1707 // Double_t thickness = 0.02;
1708 // Double_t thickness2 = 0.022;
1709 // // TGeoConeSeg* A2 = new TGeoConeSeg ("A2",
1710 // coneDz-thickness, 6.+thickness, 7.6-thickness2, 5.99+thickness, 6.05-thickness2, 0., 180.); TGeoConeSeg* A2 =
1711 // new TGeoConeSeg ("A2", coneDz-thickness, 3.+thickness, 4.6-thickness2, 2.99+thickness, 3.05-thickness2, 0.,
1712 // 180.);
1713 //
1714 // TGeoCombiTrans* M2 = new TGeoCombiTrans ("M2");
1715 // M2->RotateX (45.);
1716 // M2->SetDy (-5.575+thickness*sqrt(2.));
1717 // M2->SetDz (6.935);
1718 // M2->RegisterYourself();
1719 //
1720 // TGeoShape* coneShp2 = new TGeoCompositeShape ("Cone2_shp", "A2-B:M2");
1721 // TGeoVolume* coneVol2 = new TGeoVolume ("Cone2", coneShp2, gStsMedium);
1722 // coneVol2->SetLineColor(kGreen);
1723 //// coneVol2->RegisterYourself();
1724 //
1725 // coneVol->AddNode(coneVol2, 1);
1726
1727 return coneVol;
1728}
1729/** ======================================================================= **/
1730
1731/** ======================================================================= **/
1733{
1734 // --- Material of the frames
1735 TGeoMedium* framesMaterial = gGeoMan->GetMedium("carbon");
1736
1737 // --- Outer cone
1738 TGeoConeSeg* bA = new TGeoConeSeg("bA", coneDz, 6., 7.6, 6., 6.04, 0., 180.);
1739 TGeoBBox* bB = new TGeoBBox("bB", 8., 6., 10.);
1740
1741 TGeoCombiTrans* bM = new TGeoCombiTrans("bM");
1742 bM->RotateX(45.);
1743 bM->SetDy(-5.575);
1744 bM->SetDz(6.935);
1745 bM->RegisterYourself();
1746
1747 TGeoShape* coneBigShp = new TGeoCompositeShape("ConeBig_shp", "bA-bB:bM");
1748 TGeoVolume* coneBigVol = new TGeoVolume("ConeBig", coneBigShp, framesMaterial);
1749 coneBigVol->SetLineColor(kGreen);
1750 // coneBigVol->RegisterYourself();
1751
1752 // --- Inner cone
1753 Double_t thickness = 0.02;
1754 Double_t thickness2 = 0.022;
1755 TGeoConeSeg* bA2 = new TGeoConeSeg("bA2", coneDz - thickness, 6. + thickness, 7.6 - thickness2, 5.99 + thickness,
1756 6.05 - thickness2, 0., 180.);
1757
1758 TGeoCombiTrans* bM2 = new TGeoCombiTrans("bM2");
1759 bM2->RotateX(45.);
1760 bM2->SetDy(-5.575 + thickness * sqrt(2.));
1761 bM2->SetDz(6.935);
1762 bM2->RegisterYourself();
1763
1764 TGeoShape* coneBigShp2 = new TGeoCompositeShape("ConeBig2_shp", "bA2-bB:bM2");
1765 TGeoVolume* coneBigVol2 = new TGeoVolume("ConeBig2", coneBigShp2, gStsMedium);
1766 coneBigVol2->SetLineColor(kGreen);
1767 // coneBigVol2->RegisterYourself();
1768
1769 coneBigVol->AddNode(coneBigVol2, 1);
1770
1771 return coneBigVol;
1772}
1773/** ======================================================================= **/
int i
Definition P4_F32vec4.h:22
bool Bool_t
int Int_t
constexpr Bool_t kFALSE
double Double_t
constexpr Bool_t kTRUE
kRed
kOrange
kGreen
kMagenta
kCyan
kBlue
kAzure
kYellow
void Fatal(const char *location, const char *msgfmt,...)
R__EXTERN TGeoManager * gGeoManager
#define gROOT
char * Form(const char *fmt,...)
R__EXTERN TSystem * gSystem
void Close(Option_t *option="") override
virtual Double_t GetDX() const
virtual Double_t GetDZ() const
virtual Double_t GetDY() const
void SetDz(Double_t dz) override
void RegisterYourself() override
void SetDy(Double_t dy) override
void RotateX(Double_t angle) override
virtual const Double_t * GetTranslation() const=0
virtual void RegisterYourself()
void SetParam(Int_t i, Double_t val)
void AddElement(Double_t a, Double_t z, Double_t weight)
TGeoVolume * GetVolume() const
virtual TGeoMatrix * GetMatrix() const=0
void RotateX(Double_t angle) override
void RotateY(Double_t angle) override
void RotateZ(Double_t angle) override
virtual void ComputeBBox()=0
TGeoNode * AddNode(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat=nullptr, Option_t *option="") override
TGeoMedium * GetMedium() const
virtual TGeoNode * AddNode(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat=nullptr, Option_t *option="")
void Draw(Option_t *option="") override
Int_t GetNdaughters() const
void SetTransparency(Char_t transparency=0)
TGeoNode * GetNode(const char *name) const
void SetLineColor(Color_t lcolor) override
TGeoShape * GetShape() const
Int_t Export(const char *filename, const char *name="", Option_t *option="")
virtual Bool_t IsAssembly() const
const char * GetName() const override
virtual Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0)
const char * Data() const
TString & ReplaceAll(const char *s1, const char *s2)
RVec< PromoteType< T > > sqrt(const RVec< T > &v)
TGeoManager * gGeoMan
const Double_t gkFrameStep
const Double_t gkThinFrameThickness
TGeoVolume * ConstructSmallCone(Double_t coneDz)
=======================================================================
const Bool_t gkCylindricalFrames
const Double_t gkLadderOverlapX
void CheckVolume(TGeoVolume *volume)
=======================================================================
const Double_t gkPipeR2
const Bool_t gkConstructFrames
const Bool_t gkConstructSmallFrames
const Double_t gkPipeZ2
const Double_t gkSectorGapZFrame
const Double_t gkPipeR1
TGeoVolume * ConstructFrameElement(const TString &name, TGeoVolume *frameBoxVol, Double_t x)
=======================================================================
TGeoVolume * ConstructModule(const char *name, TGeoVolume *sector, Double_t cableLength)
=======================================================================
const Double_t gkCylinderDiaOuter
Int_t CreateSectors()
=======================================================================
const Double_t gkPipeZ3
TGeoVolume * ConstructStation(Int_t iStation, Int_t nLadders, Int_t *ladderTypes, Double_t rHole)
=======================================================================
const Double_t gkPipeZ1
const Double_t gkFrameThickness
Int_t CreateSensors()
=======================================================================
const Double_t gkCableThickness
const Double_t gkLadderGapZ
const Double_t gkPipeR3
Int_t CreateLadders()
=======================================================================
const Double_t gkSectorGapZ
void AddCarbonLadder(Int_t LadderIndex, TGeoVolume *ladder, Double_t xu, Double_t ladderY, Double_t ladderZ)
=======================================================================
const Double_t gkCylinderDiaInner
TGeoVolume * ConstructLadder(Int_t LadderIndex, TGeoVolume *halfLadderU, TGeoVolume *halfLadderD, Double_t gapY, Double_t shiftZ)
=======================================================================
const Double_t gkSectorOverlapY
TGeoMedium * gStsMedium
void create_rootgeom_SSD_v17a(const char *geoTag="v17a")
const Bool_t gkConstructCones
TGeoVolume * ConstructBigCone(Double_t coneDz)
=======================================================================
Int_t CreateMedia()
=========================================================================== Create media
const Double_t gkChainGapY
const Bool_t gkConstructCables
const Double_t gkSensorThickness
TGeoVolume * ConstructHalfLadder(const TString &name, Int_t nSectors, Int_t *sectorTypes, char align)
=======================================================================
Double_t Cos(Double_t)
constexpr Double_t Pi()
Double_t Max(Double_t a, Double_t b)