Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:14:40

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : M.Frank
0011 //
0012 //==========================================================================
0013 //
0014 // Specialized generic detector constructor for fiber tube calorimeter.
0015 // See https://github.com/AIDASoft/DD4hep/issues/1173 for details
0016 //
0017 // Detector geometry structure
0018 //                <system>  <layer>  <tube>  <hole> <type>
0019 // /world_volume/FiberCalo/rowtube_1/brass_1/hole_1/quartz_1
0020 //                                  /brass_2/hole_1/scintillator_1    brass_1 == brass_2 == brass....n
0021 //                                  /brass_3/hole_1/quartz_1         
0022 //                                  /brass_4/hole_1/scintillator_1
0023 //                                  /brass_5/hole_1/quartz_1
0024 // brass_1/quartz_1   Volume(brass) / hole
0025 //                    Volume(hole)  / quartz
0026 //              alt:  Volume(hole)  / scintillator
0027 // 
0028 // /world_volume/FiberCalo/rowtube_1/brass/quartz
0029 //
0030 // Dump using:
0031 // $> geoPluginRun -input examples/ClientTests/compact/FiberTubeCalorimeter.xml 
0032 //              -volmgr -print 3 -plugin DD4hep_DetectorCheck 
0033 //              -name FiberTubeCalorimeter -geometry -structure -sensitive -volmgr -ignore
0034 //
0035 // Display using:
0036 // $> geoDisplay examples/ClientTests/compact/FiberTubeCalorimeter.xml
0037 //
0038 //==========================================================================
0039 #include <DD4hep/DetFactoryHelper.h>
0040 #include <DD4hep/Printout.h>
0041 
0042 
0043 #include <iomanip>
0044 
0045 using namespace std;
0046 using namespace dd4hep;
0047 using namespace dd4hep::detail;
0048 
0049 static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector sens)  {
0050   constexpr double tol = 0.0;
0051   xml_det_t     x_det = e;
0052 
0053   // for volume tags in detector
0054   int           det_id    = x_det.id();
0055   string        det_name  = x_det.nameStr();
0056   Material      air       = description.air();
0057 
0058   // pointer to finding dimensins text in xml file
0059   // look in DDCore/include/Parsers/detail/Dimension.h for arguments
0060   xml_comp_t    x_dim     = x_det.dimensions();
0061   double        hthick    = x_dim.thickness();
0062   double        hzlength  = x_dim.z_length()/2.;
0063   
0064   // these refer to different fields in the xml file for this detector
0065   xml_comp_t fX_struct( x_det.child( _Unicode(structure) ) );
0066   xml_comp_t fX_absorb( fX_struct.child( _Unicode(absorb) ) );
0067   xml_comp_t fX_core1(  fX_struct.child( _Unicode(core1) ) );
0068   xml_comp_t fX_core2(  fX_struct.child( _Unicode(core2) ) );
0069   xml_comp_t fX_hole(   fX_struct.child( _Unicode(hole) ) );
0070   xml_comp_t fX_phdet1( fX_struct.child( _Unicode(phdet1) ) );
0071   xml_comp_t fX_phdet2( fX_struct.child( _Unicode(phdet2) ) );
0072 
0073   Material     mat;
0074   Transform3D  trafo;
0075   PlacedVolume pv;
0076   Solid        sol;
0077 
0078   sens.setType("calorimeter");
0079   //
0080   // scint fiber
0081   sol = Tube(0., fX_core1.rmax(), hzlength);
0082   mat = description.material(fX_core1.materialStr());
0083   Volume fiber_scint_vol(fX_core1.nameStr(), sol, mat);
0084   fiber_scint_vol.setAttributes(description, fX_core1.regionStr(), fX_core1.limitsStr(), fX_core1.visStr());
0085   if ( fX_core1.isSensitive() ) {
0086     fiber_scint_vol.setSensitiveDetector(sens);
0087   }
0088   cout << setw(28) << left << fiber_scint_vol.name()
0089        << " mat: "   << setw(15) << left << mat.name()
0090        << " vis: "   << setw(15) << left<< fX_core1.visStr()
0091        << " solid: " << setw(20) << left << sol.type()
0092        << " sensitive: " << yes_no(fX_core1.isSensitive()) << endl;
0093   //
0094   // quartz fiber
0095   sol = Tube(0., fX_core2.rmax(), hzlength);
0096   mat = description.material(fX_core2.materialStr());
0097   Volume  fiber_quartz_vol(fX_core2.nameStr(), sol, mat);
0098   fiber_quartz_vol.setAttributes(description, fX_core2.regionStr(), fX_core2.limitsStr(), fX_core2.visStr());
0099   if ( fX_core2.isSensitive() ) {
0100     fiber_quartz_vol.setSensitiveDetector(sens);
0101   }
0102   cout << setw(28) << left << fiber_quartz_vol.name()
0103        << " mat: " << setw(15) << left << mat.name()
0104        << " vis: " << setw(15) << left << fX_core2.visStr()
0105        << " solid: " << setw(20) << left << sol.type()
0106        << " sensitive: " << yes_no(fX_core2.isSensitive()) << endl;
0107   //
0108   // absorberhole with a scintillating fiber inside
0109   mat = description.material(fX_hole.materialStr());
0110   sol = Tube(0., fX_hole.rmax(), hzlength);
0111   Volume scint_hole_vol( fX_core1.nameStr()+"_hole", sol, mat);
0112   scint_hole_vol.setAttributes(description, fX_hole.regionStr(), fX_hole.limitsStr(), fX_hole.visStr());
0113   trafo = Transform3D(RotationZYX(0.,0.,0.),Position(0.,0.,0.));
0114   pv    = scint_hole_vol.placeVolume(fiber_scint_vol, trafo);
0115   pv.addPhysVolID("type",1);
0116   cout << setw(28) << left << scint_hole_vol.name()
0117        << " mat: " << setw(15) << left << mat.name()
0118        << " vis: " << setw(15) << left << fX_hole.visStr()
0119        << " solid: " << setw(20) << left << sol.type()
0120        << " sensitive: " << yes_no(fX_hole.isSensitive()) << endl;
0121   if ( fX_hole.isSensitive() ) {
0122     scint_hole_vol.setSensitiveDetector(sens);
0123   }
0124   //
0125   // absorberhole with a quartz inside
0126   Volume quartz_hole_vol( fX_core2.nameStr()+"_hole", sol, mat);
0127   quartz_hole_vol.setAttributes(description, fX_hole.regionStr(), fX_hole.limitsStr(), fX_hole.visStr());
0128   pv = quartz_hole_vol.placeVolume(fiber_quartz_vol);
0129   pv.addPhysVolID("type",2);
0130   cout << setw(28) << left << quartz_hole_vol.name()
0131        << " mat: " << setw(15) << left << mat.name()
0132        << " vis: " << setw(15) << left << fX_hole.visStr()
0133        << " solid: " << setw(20) << left << sol.type()
0134        << " sensitive: " << yes_no(fX_hole.isSensitive()) << endl;
0135   if ( fX_hole.isSensitive() ) {
0136     quartz_hole_vol.setSensitiveDetector(sens);
0137   }
0138 
0139   // absorber with scintillator inside
0140   mat = description.material(fX_absorb.materialStr());
0141   sol = Tube(0., hthick, hzlength);
0142   Volume scint_abs_vol( fX_core1.nameStr()+"_absorber", sol, mat);
0143   scint_abs_vol.setAttributes(description, fX_absorb.regionStr(), fX_absorb.limitsStr(), fX_absorb.visStr());
0144   pv = scint_abs_vol.placeVolume(scint_hole_vol);
0145   pv.addPhysVolID("hole",1);
0146   cout << setw(28) << left << scint_abs_vol.name()
0147        << " mat: " << setw(15) << left << mat.name()
0148        << " vis: " << setw(15) << left << fX_absorb.visStr()
0149        << " solid: " << setw(20) << left << sol.type()
0150        << " sensitive: " << yes_no(fX_absorb.isSensitive()) << endl;
0151   if ( fX_absorb.isSensitive() ) {
0152     scint_abs_vol.setSensitiveDetector(sens);
0153   }
0154   //
0155   // absorber with quartz inside
0156   mat = description.material(fX_absorb.materialStr());
0157   Volume quartz_abs_vol(fX_core2.nameStr()+"_absorber", sol, mat);
0158   quartz_abs_vol.setAttributes(description, fX_absorb.regionStr(), fX_absorb.limitsStr(), fX_absorb.visStr());
0159   pv = quartz_abs_vol.placeVolume(quartz_hole_vol, trafo);
0160   pv.addPhysVolID("hole",2);
0161   cout << setw(28) << left << quartz_abs_vol.name()
0162        << " mat: " << setw(15) << left << mat.name()
0163        << " vis: " << setw(15) << left << fX_absorb.visStr()
0164        << " solid: " << setw(20) << left << sol.type()
0165        << " sensitive: " << yes_no(fX_absorb.isSensitive()) << endl;
0166   if ( fX_absorb.isSensitive() ) {
0167     quartz_abs_vol.setSensitiveDetector(sens);
0168   }
0169   //
0170   // Setup the volumes with the shapes and properties in one horixontal layer
0171   int    Ncount = x_dim.numsides();
0172   double hzph   = x_dim.z1();
0173   double agap   = x_dim.gap();
0174   double dx     = 2*(Ncount + Ncount+1)/2e0 * (hthick+agap) + tol;
0175   double dy     = hthick + tol;
0176   double dz     = hzlength+hzph + tol;
0177   Box    tube_row_box(dx, dy, dz);
0178   Volume tube_row_vol("layer", tube_row_box, air);
0179   tube_row_vol.setVisAttributes(description, x_det.visStr());
0180   tube_row_vol.setSensitiveDetector(sens);
0181   cout << tube_row_vol.name()
0182        << " dx: " << tube_row_box.x()
0183        << " dy: " << tube_row_box.y()
0184        << " dz: " << tube_row_box.z() << endl;
0185   tube_row_vol.setVisAttributes(description, "layerVis");
0186 
0187   for (int ijk=-Ncount; ijk<Ncount+1; ijk++) {
0188     double mod_x_off = (ijk) * 2 * (hthick + agap);
0189     int towernum = Ncount + ijk + 1;
0190     pv = tube_row_vol.placeVolume((towernum%2 == 0) ? quartz_abs_vol : scint_abs_vol, Position(mod_x_off,0.,0.));
0191     pv.addPhysVolID("tube", towernum);
0192     cout << "Placing row  "    << setw(5) << right << ijk
0193          << " x-offset: "      << setw(7) << right << mod_x_off
0194          << " volume of type " << pv.volume().name()
0195          << endl;
0196   }
0197 
0198   dy = 2*(Ncount + Ncount+1)/2e0 * (hthick+agap) + tol;
0199   DetElement    sdet(det_name, det_id);
0200   Box           env_box(dx+tol, dy+tol, dz+tol);
0201   Volume        envelopeVol(det_name, env_box, air);
0202   envelopeVol.setAttributes(description, x_det.regionStr(), x_det.limitsStr(), x_det.visStr());
0203   if ( x_dim.isSensitive() )   {
0204     envelopeVol.setSensitiveDetector(sens);
0205   }
0206   //
0207   // Now stack multiple horizontal layers to form the final box
0208   for (int ijk=-Ncount; ijk < Ncount+1; ijk++) {
0209     double mod_y_off = (ijk) * 2 * (tube_row_box.y() + agap);
0210     Transform3D tr(RotationZYX(0.,0.,0.), Position(0.,mod_y_off,0.));
0211     pv = envelopeVol.placeVolume(tube_row_vol, tr);
0212     pv.addPhysVolID("layer", Ncount+ijk+1);
0213 
0214     DetElement de_layer(_toString(Ncount+ijk, "layer_%d"), det_id);
0215     de_layer.setPlacement(pv);
0216     sdet.add(de_layer);
0217     cout << "Placing " << setw(28) << left << de_layer.name()
0218          << " y-offset: "  << setw(7) << right << mod_y_off
0219          << " volume of type " << pv.volume().name()
0220          << endl;
0221   }
0222   //
0223   // detector element for entire detector.
0224   dz = x_dim.zmin()+hzlength+hzph+tol;
0225   Volume motherVol = description.pickMotherVolume(sdet);
0226   pv = motherVol.placeVolume(envelopeVol, Position(0, 0, dz));
0227   pv.addPhysVolID("system", det_id);
0228   sdet.setPlacement(pv);  // associate the placed volume to the detector element
0229   return sdet;
0230 }
0231 
0232 DECLARE_DETELEMENT(DD4hep_FiberTubeCalorimeter,create_detector)