Crystal_geo.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // Crystal Endcap EM Calorimeter Detector implementation
3 //--------------------------------------------------------------------------
4 // J.KIM 2020-07-30
5 //==========================================================================
6 #include "DD4hep/DetFactoryHelper.h"
7 #include "XML/Layering.h"
8 #include <math.h>
9 
10 using namespace std;
11 using namespace dd4hep;
12 using namespace dd4hep::detail;
13 
32 static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector sens) {
33  xml_det_t x_det = e;
34  xml_dim_t dim = x_det.dimensions();
35  int det_id = x_det.id();
36  string det_name = x_det.nameStr();
37  Material PbWO4 = description.material("PbWO4");
38  double rmin = dim.rmin();
39  double rmax = dim.rmax();
40  double pixel_x = dim.x();
41  double pixel_y = dim.y();
42  double pixel_z = dim.z();
43  xml_dim_t pos = x_det.position();
44  double x_pos = dd4hep::getAttrOrDefault(pos, _Unicode(x),0.0);
45  double y_pos = dd4hep::getAttrOrDefault(pos, _Unicode(y),0.0);
46  double z_pos = dd4hep::getAttrOrDefault(pos, _Unicode(z),0.0);
47  double totWidth = pixel_z;
48 
49  Assembly assembly(det_name);
50  DetElement endcap_DE(det_name,det_id);
51 
52  // Fill with box-shaped crystals forming a grid.
53  Assembly box_assembly("box_assembly");
54  PlacedVolume pv_box;
55 
56  // Gap between box-shaped crystals
57  double offset_x = 0.1*mm;
58  double offset_y = 0.1*mm;
59  double offset_diagonal = pixel_x*sqrt(2)/2.0 + offset_x;
60  // Limits
61  double limit_inner = rmin + offset_diagonal;
62  double limit_outer = rmax - offset_diagonal;
63  // Number of crystals in a grid
64  int nx = floor(rmax/pixel_x);
65  int ny = floor(rmax/pixel_y);
66  // X or Y spacing increasement
67  double x_spacing = pixel_x + offset_x;
68  double y_spacing = pixel_y + offset_y;
69  // initial positions in X or Y.
70  double pos_x = 0.0*mm;
71  double pos_y = 0.0*mm;
72 
73  // Create Box and Volume
74  Box box(pixel_x/2.0, pixel_y/2.0, pixel_z/2.0);
75  Volume vol("box_volume", box, PbWO4);
76 
78  // Divide tube into 4 sections; top left, top right, bottom left, and bottom right
80  // Top left
82  int i_module = 0;
83  pos_y = pixel_y/2.0 + offset_y/2.0;
84  for(int iy=0; iy<ny-1; iy++){
85  for(int ix=0; ix<nx; ix++){
86  double x_start = pixel_x/2.0 + offset_x/2.0;
87 
88  if(ix==0)
89  {
90  pos_x = x_start;
91  if(sqrt((pos_x*pos_x) + (pos_y*pos_y)) > limit_inner){
92  pv_box = assembly.placeVolume(vol, Position(pos_x,pos_y,0.0));
93  i_module++;
94  }
95  else{
96  continue;
97  }
98  }
99  else
100  {
101  // Move to +X
102  pos_x += x_spacing;
103  if(sqrt((pos_x*pos_x) + (pos_y*pos_y)) < limit_outer && sqrt((pos_x*pos_x) + (pos_y*pos_y)) > limit_inner)
104  {
105  pv_box = assembly.placeVolume(vol, Position(pos_x,pos_y,0.0));
106  i_module++;
107  }
108  else{
109  continue;
110  }
111  }
112  pv_box.addPhysVolID("sector",1).addPhysVolID("module",i_module);
113  sens.setType("calorimeter");
114  vol.setSensitiveDetector(sens);
115  }
116  // Move to +Y
117  pos_y += y_spacing;
118  }
119 
121  // Top right
123  // Initialize position in Y
124  pos_y = pixel_y/2.0 + offset_y/2.0;
125  i_module=0;
126  for(int iy=0; iy<ny-1; iy++){
127  for(int ix=0; ix<nx; ix++){
128  double x_start = pixel_x/2.0 + offset_x/2.0;
129 
130  if(ix==0)
131  {
132  pos_x = - x_start;
133  if(sqrt((pos_x*pos_x) + (pos_y*pos_y)) > limit_inner){
134  pv_box = assembly.placeVolume(vol, Position(pos_x,pos_y,0.0));
135  i_module++;
136  }
137  else{
138  continue;
139  }
140  }
141  else
142  {
143  // Move to -X
144  pos_x -= x_spacing;
145  if(sqrt((pos_x*pos_x) + (pos_y*pos_y)) < limit_outer && sqrt((pos_x*pos_x) + (pos_y*pos_y)) > limit_inner){
146  pv_box = assembly.placeVolume(vol, Position(pos_x,pos_y,0.0));
147  i_module++;
148  }
149  else{
150  continue;
151  }
152  }
153  pv_box.addPhysVolID("sector",2).addPhysVolID("module",i_module);
154  sens.setType("calorimeter");
155  vol.setSensitiveDetector(sens);
156  }
157  // Move to +Y
158  pos_y += y_spacing;
159  }
160 
162  // Bottom left
164  // It's below the first row of the section of Top left
165  // That's why ny goes up to ny -2 (the first row of Bottom left starts one row less)
166  pos_y = -y_spacing/2.0 - offset_y/2.0;
167  i_module=0;
168  for(int iy=0; iy<ny-1; iy++){
169  for(int ix=0; ix<nx; ix++){
170  double x_start = pixel_x/2.0 + offset_x/2.0;
171 
172  if(ix==0)
173  {
174  pos_x = x_start;
175  if(sqrt((pos_x*pos_x) + (pos_y*pos_y)) > limit_inner){
176  pv_box = assembly.placeVolume(vol, Position(pos_x,pos_y,0.0));
177  i_module++;
178  }
179  else{
180  continue;
181  }
182  }
183  else
184  {
185  // Move to +X
186  pos_x += x_spacing;
187  if(sqrt((pos_x*pos_x) + (pos_y*pos_y)) < limit_outer && sqrt((pos_x*pos_x) + (pos_y*pos_y)) > limit_inner){
188  pv_box = assembly.placeVolume(vol, Position(pos_x,pos_y,0.0));
189  i_module++;
190  }
191  else{
192  continue;
193  }
194  }
195  pv_box.addPhysVolID("sector",3).addPhysVolID("module",i_module);
196  sens.setType("calorimeter");
197  vol.setSensitiveDetector(sens);
198  }
199  // Move to -Y
200  pos_y -= y_spacing;
201  }
202 
204  // Bottom right
206  // Again it's below the first row of the section of Top left
207  // That's why ny goes up to ny -2 (the first row of Bottom left starts one row less)
208  pos_y = -y_spacing/2.0 - offset_y/2.0;
209  i_module=0;
210  for(int iy=0; iy<ny-1; iy++){
211  for(int ix=0; ix<nx; ix++)
212  {
213  double x_start = pixel_x/2.0 + offset_x/2.0;
214 
215  if(ix==0)
216  {
217  pos_x = - x_start;
218  if(sqrt((pos_x*pos_x) + (pos_y*pos_y)) > limit_inner){
219  pv_box = assembly.placeVolume(vol, Position(pos_x,pos_y,0.0));
220  i_module++;
221  }
222  else{
223  continue;
224  }
225  }
226  else
227  {
228  // Move to -X
229  pos_x -= x_spacing;
230  if(sqrt((pos_x*pos_x) + (pos_y*pos_y)) < limit_outer && sqrt((pos_x*pos_x) + (pos_y*pos_y)) > limit_inner){
231  pv_box = assembly.placeVolume(vol, Position(pos_x,pos_y,0.0));
232  i_module++;
233  }
234  else{
235  continue;
236  }
237  }
238  pv_box.addPhysVolID("sector",4).addPhysVolID("module",i_module);
239  sens.setType("calorimeter");
240  vol.setSensitiveDetector(sens);
241  }
242  // Move to -Y
243  pos_y -= y_spacing;
244  }
247 
248  Volume motherVol = description.pickMotherVolume(endcap_DE);
249  auto pv = motherVol.placeVolume(assembly, Position(x_pos,y_pos,z_pos-totWidth/2.0));
250  pv.addPhysVolID("system", det_id);
251  endcap_DE.setPlacement(pv);
252  return endcap_DE;
253 }
255 DECLARE_DETELEMENT(Crystal,create_detector)
static Ref_t create_detector(Detector &description, xml_h e, SensitiveDetector sens)
Definition: Crystal_geo.cpp:32
Detector
Definition: DDG4.py:69
Namespace for the AIDA detector description toolkit.