Newer
Older
//==========================================================================
// Specialized generic detector constructor
//==========================================================================
#include "Acts/Plugins/DD4hep/ActsExtension.hpp"
#include "Acts/Plugins/DD4hep/ConvertDD4hepMaterial.hpp"
#include "DD4hep/DetFactoryHelper.h"
#include "DD4hep/Printout.h"
using namespace std;
using namespace dd4hep;
using namespace dd4hep::detail;
Assembly getModule( string m_nam, int n, xml_det_t x_det, double module_rmin, Detector& description, SensitiveDetector sens, map<string, vector<PlacedVolume>> &sensitives);
/** A barrel tracker with a module that is curved (not flat).
*
*
*/
static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector sens)
{
typedef vector<PlacedVolume> Placements;
xml_det_t x_det = e;
Material air = description.air();
int det_id = x_det.id();
string det_name = x_det.nameStr();
DetElement sdet(det_name, det_id);
//Acts::ActsExtension* barrelExtension = new Acts::ActsExtension();
//barrelExtension->addType("barrel", "detector");
//sdet.addExtension<Acts::ActsExtension>(barrelExtension);
Assembly assembly(det_name);
map<string, Volume> mod_volumes;
map<string, Placements> sensitives;
PlacedVolume pv;
sens.setType("tracker");
for (xml_coll_t li(x_det, _U(layer)); li; ++li) {
xml_comp_t x_layer = li;
xml_comp_t x_barrel = x_layer.child(_U(barrel_envelope));
xml_comp_t x_layout = x_layer.child(_U(rphi_layout));
xml_comp_t z_layout = x_layer.child(_U(z_layout)); // Get the <z_layout> element.
int lay_id = x_layer.id();
string m_nam = x_layer.moduleStr();
string lay_nam = _toString(x_layer.id(), "layer%d");
Tube lay_tub(x_barrel.inner_r(), x_barrel.outer_r(), x_barrel.z_length() / 2);
Volume lay_vol(lay_nam, lay_tub, air); // Create the layer envelope volume.
lay_vol.setVisAttributes(description.visAttributes(x_layer.visStr()));
double phi0 = x_layout.phi0(); // Starting phi of first module.
double phi_tilt = x_layout.phi_tilt(); // Phi tilt of a module.
double rc = x_layout.rc(); // Radius of the module center.
int nphi = x_layout.nphi(); // Number of modules in phi.
double rphi_dr = x_layout.dr(); // The delta radius of every other module.
double phi_incr = (M_PI * 2) / nphi; // Phi increment for one module.
double phic = phi0; // Phi of the module center.
double z0 = z_layout.z0(); // Z position of first module in phi.
double nz = z_layout.nz(); // Number of modules to place in z.
double z_dr = z_layout.dr(); // Radial displacement parameter, of every other module.
auto dz = getAttrOrDefault(z_layout, _Unicode(dz), 0.); // z offset
// get the module for this layer from the xml
Volume m_env = getModule( m_nam, lay_id, x_det, x_barrel.inner_r(), description, sens, sensitives ) ;
DetElement lay_elt(sdet, _toString(x_layer.id(), "layer%d"), lay_id);
//Acts::ActsExtension* layerExtension = new Acts::ActsExtension();
//layerExtension->addType("sensitive cylinder", "layer");
//// layerExtension->addValue(10. * Acts::UnitConstants::mm, "r", "envelope");
//lay_elt.addExtension<Acts::ActsExtension>(layerExtension);
Placements& sensVols = sensitives[m_nam];
// Z increment for module placement along Z axis.
// Adjust for z0 at center of module rather than
// the end of cylindrical envelope.
double z_incr = nz > 1 ? (2.0 * z0) / (nz - 1) : 0.0;
// Starting z for module placement along Z axis.
double module_z = -z0;
int module = 1;
// Loop over the number of modules in phi.
for (int ii = 0; ii < nphi; ii++) {
double dx = z_dr * std::cos(phic + phi_tilt); // Delta x of module position.
double dy = z_dr * std::sin(phic + phi_tilt); // Delta y of module position.
double x = rc * std::cos(phic); // Basic x module position.
double y = rc * std::sin(phic); // Basic y module position.
// Loop over the number of modules in z.
for (int j = 0; j < nz; j++) {
string module_name = _toString(module, "module%d");
DetElement mod_elt(lay_elt, module_name, module);
// Module PhysicalVolume.
// Transform3D
// tr(RotationZYX(0,-((M_PI/2)-phic-phi_tilt),M_PI/2),Position(x,y,module_z));
// NOTE (Nikiforos, 26/08 Rotations needed to be fixed so that component1 (silicon) is on the
// outside
Transform3D tr(RotationZYX(phic - phi_tilt, 0, 0), Position(x, y, module_z + dz));
pv = lay_vol.placeVolume(m_env, tr);
pv.addPhysVolID("module", module);
mod_elt.setPlacement(pv);
for (size_t ic = 0; ic < sensVols.size(); ++ic) {
PlacedVolume sens_pv = sensVols[ic];
DetElement comp_elt(mod_elt, sens_pv.volume().name(), module);
comp_elt.setPlacement(sens_pv);
//Acts::ActsExtension* moduleExtension = new Acts::ActsExtension("YZX");
//comp_elt.addExtension<Acts::ActsExtension>(moduleExtension);
}
/// Increase counters etc.
module++;
// Adjust the x and y coordinates of the module.
x += dx;
y += dy;
// Flip sign of x and y adjustments.
dx *= -1;
dy *= -1;
// Add z increment to get next z placement pos.
module_z += z_incr;
}
phic += phi_incr; // Increment the phi placement of module.
rc += rphi_dr; // Increment the center radius according to dr parameter.
rphi_dr *= -1; // Flip sign of dr parameter.
module_z = -z0; // Reset the Z placement parameter for module.
}
// Create the PhysicalVolume for the layer.
pv = assembly.placeVolume(lay_vol); // Place layer in mother
pv.addPhysVolID("layer", lay_id); // Set the layer ID.
lay_elt.setAttributes(description, lay_vol, x_layer.regionStr(), x_layer.limitsStr(), x_layer.visStr());
lay_elt.setPlacement(pv);
}
sdet.setAttributes(description, assembly, x_det.regionStr(), x_det.limitsStr(), x_det.visStr());
// assembly.setVisAttributes(description.invisible());
pv = description.pickMotherVolume(sdet).placeVolume(assembly);
pv.addPhysVolID("system", det_id); // Set the subdetector system ID.
pv.addPhysVolID("barrel", 1); // Flag this as a barrel subdetector.
sdet.setPlacement(pv);
return sdet;
}
// clang-format off
DECLARE_DETELEMENT(refdet_CylinderTrackerBarrel, create_detector)
DECLARE_DETELEMENT(refdet_MMTrackerBarrel, create_detector)
DECLARE_DETELEMENT(refdet_RWellTrackerBarrel, create_detector)
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
Assembly getModule( string m_nam, int n, xml_det_t x_det, double module_rmin, Detector& description, SensitiveDetector sens, map<string, vector<PlacedVolume>> &sensitives){
Material air = description.air();
Assembly module_assembly( _toString(n,"mod_assembly_%d"));
int n_modules = 0;
for (xml_coll_t mi(x_det, _U(module)); mi; ++mi) {
n_modules++;
xml_comp_t x_mod = mi;
if( x_mod.nameStr() == m_nam ) {
xml_comp_t m_env = x_mod.child(_U(module_envelope));
string m_nam = x_mod.nameStr();
// auto module_rmin = m_env.rmin();
auto module_length = m_env.length();
auto module_phi = getAttrOrDefault(m_env, _Unicode(phi), 90.0);
// compute thickness as the sum of all components
double total_thickness = 0.;
xml_coll_t ci(x_mod, _U(module_component));
for (ci.reset(), total_thickness = 0.0; ci; ++ci)
total_thickness += xml_comp_t(ci).thickness();
Volume m_vol(m_nam, Tube(module_rmin, module_rmin + total_thickness, module_length / 2), air);
int ncomponents = 0, sensor_number = 1;
module_assembly.placeVolume(m_vol, Position(-module_rmin, 0, 0));
// mod_volumes[m_nam] = module_assembly;
m_vol.setVisAttributes(description.visAttributes(x_mod.visStr()));
// loop over detector components
auto comp_rmin = module_rmin;
for (ci.reset(); ci; ++ci, ++ncomponents) {
xml_comp_t x_comp = ci;
xml_comp_t x_pos = x_comp.position(false);
xml_comp_t x_rot = x_comp.rotation(false);
string c_nam = _toString(ncomponents, "component%d_") + _toString(n);
auto comp_thickness = x_comp.thickness();
auto comp_phi = getAttrOrDefault(x_comp, _Unicode(phi), module_phi);
auto comp_phi0 = getAttrOrDefault(x_comp, _Unicode(phi0), 0.0);
auto comp_length = getAttrOrDefault(x_comp, _Unicode(length), module_length);
Tube c_tube(comp_rmin, comp_rmin + comp_thickness, comp_length / 2, -comp_phi / 2.0 + comp_phi0,
comp_phi / 2.0 + comp_phi0);
Volume c_vol(c_nam, c_tube, description.material(x_comp.materialStr()));
PlacedVolume c_pv;
if (x_pos && x_rot) {
Position c_pos(x_pos.x(0), x_pos.y(0), x_pos.z(0));
RotationZYX c_rot(x_rot.z(0), x_rot.y(0), x_rot.x(0));
c_pv = m_vol.placeVolume(c_vol, Transform3D(c_rot, c_pos));
} else if (x_rot) {
c_pv = m_vol.placeVolume(c_vol, RotationZYX(x_rot.z(0), x_rot.y(0), x_rot.x(0)));
} else if (x_pos) {
c_pv = m_vol.placeVolume(c_vol, Position(x_pos.x(0), x_pos.y(0), x_pos.z(0)));
} else {
c_pv = m_vol.placeVolume(c_vol);
}
c_vol.setRegion(description, x_comp.regionStr());
c_vol.setLimitSet(description, x_comp.limitsStr());
c_vol.setVisAttributes(description, x_comp.visStr());
if (x_comp.isSensitive()) {
c_pv.addPhysVolID(_U(sensor), sensor_number++);
c_vol.setSensitiveDetector(sens);
sensitives[m_nam].push_back(c_pv);
}
comp_rmin = comp_rmin + comp_thickness;
}
if( x_mod.hasChild("frame")){
// build the carbon fiber frame around the gas volume
// two bars along z and two arches at the two ends
// TODO make the frame hollow
xml_comp_t m_frame = x_mod.child(_U(frame));
auto thickness = m_frame.thickness();
// get sensitive component rmin
auto m_rmin = module_rmin + m_frame.rmin();
// bars
Tube c_tubeL(m_rmin, m_rmin + thickness, module_length / 2, -module_phi / 2.0,
-module_phi / 2.0 + thickness/m_rmin);
Volume c_volL( m_nam + "_barL", c_tubeL, description.material(m_frame.materialStr()));
Tube c_tubeR(m_rmin, m_rmin + thickness, module_length / 2, module_phi / 2.0 - thickness/m_rmin,
module_phi / 2.0 );
Volume c_volR(m_nam + "_barR", c_tubeR, description.material(m_frame.materialStr()));
//arches
Tube c_tubeN(m_rmin, m_rmin + thickness, thickness / 2, - module_phi / 2.0 + thickness/m_rmin,
module_phi / 2.0 - thickness/m_rmin );
Volume c_volN(m_nam + "_archN", c_tubeN, description.material(m_frame.materialStr()));
c_volN.setVisAttributes( description, m_frame.visStr() );
PlacedVolume c_pv;
c_pv = m_vol.placeVolume(c_volL);
c_pv = m_vol.placeVolume(c_volR);
c_pv = m_vol.placeVolume(c_volN, Position(0,0, -module_length / 2 + thickness/2) );
c_pv = m_vol.placeVolume(c_volN, Position(0,0, module_length / 2 - thickness/2) );
}
}
}
return module_assembly;
}