EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
calorimeter.C
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file calorimeter.C
1 
2 //
3 // Example NxN crystal calorimeter creation script; produces "calorimeter.root"
4 // file with a 7x7 crystal matrix of specified size, at a given location;
5 // can be used as geometry input for simulation.C->digitization.C->reconstruction.C
6 // scripts in this directory; "calorimeter.root" will also contain a mapping table
7 // needed to perform clustering in reconstruction.C;
8 //
9 // Prefer to declare dimensions in [mm]; convert to [cm] when calling ROOT shape
10 // definition routines only;
11 //
12 
14 {
15  // Internals, in particular all the famous FairRoot dances around media interface, are
16  // of no interest for end user here; just hide them all in this class; there are certain naming
17  // conventions inside EicRoot framework; selected here (more or less arbitrary) detector name will
18  // be used in various I/O routines in a "mixed" writing ('Calorimeter' in this particular case);
19  // mapping table block will be called CalorimeterGeoParData (you may want to inspect calorimeter.root
20  // file), raw MC points will be called CalorimeterMoCaPoint, etc.; string ('calorimeter' in this case)
21  // and capital letters ('CALORIMETER' here) writings will be mostly used for printouts;
22  auto calo = new EndcapGeoParData("CALORIMETER");
23 
24  // Create a 7x7 matrix; 25x25mm^2 square cells, 200mm long, enclosed in 200um thick
25  // carbon fiber alveoles;
26  UInt_t cellNum = 7;
27  Double_t cellFaceSize = 25.00;
28  Double_t cellLength = 200.0;
29  Double_t alveoleThickness = 0.2;
30  // Yes, prefer to associate carbon material with its particular cell;
31  Double_t cellEnvelopeWidth = cellFaceSize + 2*alveoleThickness;
32  // Assume wrapper volume thickness is the same on all sides;
33  Double_t cellEnvelopeLength = cellLength + 2*alveoleThickness;
34 
35  // Choose whatever distance from the IP; calorimeter matrix will be
36  // "ortogonal" to Z (beam) direction;
37  Double_t beamLineOffset = 2000.0;
38 
39  calo->SetTopVolumeTransformation(new TGeoTranslation(0.0, 0.0, 0.1 * beamLineOffset));
40 
41  // Let mapper know overall (logical 2D) matrix size; these lines are required
42  // for proper clustering in reconstruction.C;
43  unsigned lgroup = calo->AddLogicalVolumeGroup(cellNum, cellNum);
44 
45  // Declare single cell pack volume; volume names are arbitrary, but should be
46  // consistent here and through simulation/digitization/reconstruction sequence;
47  auto alveole = new TGeoBBox("CaloCellAlveole",
48  0.1 * cellEnvelopeWidth/2,
49  0.1 * cellEnvelopeWidth/2,
50  0.1 * cellEnvelopeLength/2);
51  // Make sure media names are listed in geometry/media.geo;
52  auto valveole = new TGeoVolume("CaloCellAlveole", alveole, calo->GetMedium("CarbonFiber"));
53 
54  // Crystal volume inside this pack;
55  auto crystal = new TGeoBBox("CaloCrystal",
56  0.1 * cellFaceSize/2,
57  0.1 * cellFaceSize/2,
58  0.1 * cellLength/2);
59  auto vcrystal = new TGeoVolume("CaloCrystal", crystal, calo->GetMedium("pwo"));
60 
61  // Place crystal into the alveole;
62  valveole->AddNode(vcrystal, 0, new TGeoCombiTrans(0.0, 0.0, 0.0, new TGeoRotation()));
63 
64  //
65  // Mapping table will contain 2 separate sections: crystals and their respective alveoles;
66  // it hardcodes one-to-one correspondence between GEANT crystal nodes in the geometry
67  // volume hierarchy and XY-indices of a given crystal in calorimeter matrix;
68  //
69 
70  // Crystal (sensitive volume) map; 2 levels deep (crystal itself and its alveole);
71  auto gmapCr = calo->CreateNewMap();
72  // At most 1 crystal per alveole and N*N alveole packs;
73  gmapCr->AddGeantVolumeLevel("CaloCrystal", 1);
74  gmapCr->AddGeantVolumeLevel("CaloCellAlveole", cellNum * cellNum);
75  gmapCr->SetSingleSensorContainerVolume("CaloCellAlveole");
76 
77  // Perhaps want to make alveoles GEANT sensitive volumes as well (say, to check
78  // energy losses there) -> create a separate map;
79  auto gmapAl = calo->CreateNewMap();
80  // N*N alveole packs;
81  gmapAl->AddGeantVolumeLevel("CaloCellAlveole", cellNum * cellNum);
82  gmapAl->SetSingleSensorContainerVolume("CaloCellAlveole");
83 
84  // Now place all N*N alveole packs into the calorimeter volume and create mapping tables;
85  // this variable will serve as a running node counter;
86  unsigned tcounter = 0;
87  for(unsigned ix=0; ix<cellNum; ix++)
88  {
89  double xx = cellEnvelopeWidth*(ix - (cellNum-1)/2.);
90 
91  for(unsigned iy=0; iy<cellNum; iy++)
92  {
93  double yy = cellEnvelopeWidth*(iy - (cellNum-1)/2.);
94 
95  // Fill both crystal and alveole mapping table entries; geometry is very simple
96  // in this case (just a single NxN matrix) -> linear indices are {ix,iy};
97  UInt_t id[2] = {0, tcounter}, logical[2] = {ix, iy};
98  if (calo->SetMappingTableEntry(gmapCr, id+0, lgroup, logical) ||
99  calo->SetMappingTableEntry(gmapAl, id+1, lgroup, logical)) {
100  cout << "Failed to set mapping table entry!" << endl;
101  exit(0);
102  } //if
103 
104  // Well, in this easy case (a single NxN matrix) one could probably use XY-index
105  // as node ID in the below call and be happy; the problem is that this simple
106  // scheme does not work for real-life configurations (for instance if calorimeter
107  // was composed of one 2x5 and one 3x5 matrix); then one has to go through a nasty
108  // excercise of associating logical node IDs and XY-indices on the calorimeter matrix
109  // anyway, and the best place to do the job is right here, during GEANT geometry
110  // creation (so logical mapping will be always available together with the GEANT volume
111  // scheme); see geometry/BEMC/bemc.C, which cooks such a file for EIC backward electromagnetic
112  // calorimeter (4 quadrants filled with 2x2 crystal packs, mapped onto a single
113  // "flat" XY per-crystal matrix);
114  calo->GetTopVolume()->AddNode(valveole, tcounter++,
115  new TGeoCombiTrans(0.1 * xx, 0.1 * yy, 0.0, new TGeoRotation()));
116  } //for iy
117  } //for ix
118 
119  calo->GetColorTable()->AddExactMatch ("CaloCrystal", kBlue);
120  calo->GetTransparencyTable()->AddExactMatch("CaloCrystal", 50);
121 
122  // A unified user call which places assembled detector volume in a proper place in MASTER (top)
123  // coordinate system, puts this MASTER (top) volume into ROOT TGeo volume tree, and dumps this tree
124  // together with EicRoot mapping table in one file;
125  calo->FinalizeOutput();
126 
127  // Yes, always exit;
128  exit(0);
129 } // calorimeter()
130