Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:17:07

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 //==========================================================================
0011 #include "DDDetectors/OtherDetectorHelpers.h"
0012 
0013 #include "DD4hep/DetFactoryHelper.h"
0014 #include "DD4hep/Printout.h"
0015 #include "DD4hep/DD4hepUnits.h"
0016 #include "DD4hep/DetType.h"
0017 #include "DDRec/DetectorData.h"
0018 #include "XML/Utilities.h"
0019 
0020 #include <cmath>
0021 #include <string>
0022 
0023 using dd4hep::Transform3D;
0024 using dd4hep::Position;
0025 using dd4hep::RotationX;
0026 using dd4hep::RotationY;
0027 using dd4hep::RotateY;
0028 using dd4hep::RotateX;
0029 using dd4hep::ConeSegment;
0030 using dd4hep::SubtractionSolid;
0031 using dd4hep::Material;
0032 using dd4hep::Volume;
0033 using dd4hep::Solid;
0034 using dd4hep::Tube;
0035 using dd4hep::PlacedVolume;
0036 using dd4hep::Assembly;
0037 using dd4hep::Detector;
0038 using dd4hep::SensitiveDetector;
0039 using dd4hep::Ref_t;
0040 
0041 namespace units = dd4hep;
0042 
0043 
0044 static Ref_t create_detector(Detector& description,
0045                  xml_h xmlHandle,
0046                  SensitiveDetector sens) {
0047 
0048   printout(dd4hep::DEBUG,"DD4hep_Mask", "Creating Mask" ) ;
0049 
0050   //Access to the XML File
0051   xml_det_t xmlMask = xmlHandle;
0052   const std::string name = xmlMask.nameStr();
0053 
0054   //--------------------------------
0055   Assembly envelope( name + "_assembly"  ) ;
0056   //--------------------------------
0057 
0058   dd4hep::DetElement tube(  name, xmlMask.id()  ) ;
0059 
0060   bool rotationX= false;
0061 
0062   //Parameters we have to know about
0063   dd4hep::xml::Component xmlParameter = xmlMask.child(_Unicode(parameter));
0064   const double crossingAngle  = xmlParameter.attr< double >(_Unicode(crossingangle))*0.5; //  only half the angle
0065 
0066   if (xmlParameter.hasAttr(_Unicode(rotationX)))
0067     rotationX = xmlParameter.attr< bool >(_Unicode(rotationX));
0068 
0069   int counter = 0; 
0070   for(xml_coll_t c( xmlMask ,Unicode("section")); c; ++c, counter++) {
0071 
0072     xml_comp_t xmlSection( c );
0073     bool isSensitive = false;
0074     ODH::ECrossType crossType = ODH::getCrossType(xmlSection.attr< std::string >(_Unicode(type)));
0075     const double zStart       = xmlSection.attr< double > (_Unicode(start));
0076     const double zEnd         = xmlSection.attr< double > (_Unicode(end));
0077     const double rInnerStart  = xmlSection.attr< double > (_Unicode(rMin1));
0078     const double rInnerEnd    = xmlSection.attr< double > (_Unicode(rMin2));
0079     const double rOuterStart  = xmlSection.attr< double > (_Unicode(rMax1));
0080     const double rOuterEnd    = xmlSection.attr< double > (_Unicode(rMax2));
0081     const double thickness    = rOuterStart - rInnerStart;
0082     Material sectionMat  = description.material(xmlSection.materialStr());
0083     const std::string volName      = "tube_" + xmlSection.nameStr();
0084 
0085     double phi1 = 0 ;
0086     double phi2 = 360.0*units::degree;
0087     if (xmlSection.hasAttr(_U(phi1)))
0088       phi1 = xmlSection.attr< double > (_U(phi1));
0089     if (xmlSection.hasAttr(_U(phi2)))
0090       phi2 = xmlSection.attr< double > (_U(phi2));
0091 
0092     std::string ssensitive = "none";
0093     if (xmlSection.hasAttr(_U(sensitive))){
0094       isSensitive = true;
0095       ssensitive = xmlSection.attr< std::string > (_U(sensitive));
0096       sens.setType( xmlSection.attr< std::string > (_U(sensitive))  );  //decide the type of SD (tracker / calorimeter) check for k4run
0097       printout(dd4hep::DEBUG, "sensitive in sens ", ssensitive);
0098     }
0099 
0100 
0101     std::stringstream pipeInfo;
0102     pipeInfo << std::setw(8) << zStart      /units::mm
0103          << std::setw(8) << zEnd        /units::mm
0104          << std::setw(8) << rInnerStart /units::mm
0105          << std::setw(8) << rInnerEnd   /units::mm
0106          << std::setw(8) << rOuterStart /units::mm
0107          << std::setw(8) << rOuterEnd   /units::mm
0108          << std::setw(8) << thickness   /units::mm
0109          << std::setw(8) << crossType
0110          << std::setw(35) << volName
0111          << std::setw(15) << sectionMat.name()
0112          << std::setw(8) << phi1
0113          << std::setw(8) << phi2
0114          << std::setw(8) << ssensitive;
0115 
0116     printout(dd4hep::INFO, "DD4hep_Mask", pipeInfo.str() );
0117 
0118     // things which can be calculated immediately
0119     const double zHalf       = fabs(zEnd - zStart) * 0.5; // half z length of the cone
0120     const double zPosition   = fabs(zEnd + zStart) * 0.5; // middle z position
0121     Material material    = sectionMat;
0122 
0123     // this could mess up your geometry, so better check it
0124     if (not ODH::checkForSensibleGeometry(crossingAngle, crossType)){
0125       throw std::runtime_error( " Mask_o1_v01_geo.cpp : checkForSensibleGeometry() failed " ) ;
0126     }
0127 
0128     const double rotateAngle = getCurrentAngle(crossingAngle, crossType); // for the placement at +z (better make it const now)
0129     const double mirrorAngle = M_PI - rotateAngle; // for the "mirrored" placement at -z
0130     // the "mirroring" in fact is done by a rotation of (almost) 180 degrees around the y-axis
0131 
0132     
0133     switch (crossType) {
0134     case ODH::kCenter:
0135     case ODH::kUpstream:
0136     case ODH::kDnstream: {
0137       // a volume on the z-axis, on the upstream branch, or on the downstream branch
0138       Transform3D transformer, transmirror;
0139 
0140       if( rotationX == true) {
0141         // absolute transformations for the placement in the world, rotate over X
0142         transformer = Transform3D(RotationX(rotateAngle), RotateX( Position(0, 0, zPosition), rotateAngle) );
0143         transmirror = Transform3D(RotationX(mirrorAngle), RotateX( Position(0, 0, zPosition), mirrorAngle) );
0144       } else{
0145     // absolute transformations for the placement in the world
0146     transformer = Transform3D(RotationY(rotateAngle), RotateY( Position(0, 0, zPosition), rotateAngle) );
0147     transmirror = Transform3D(RotationY(mirrorAngle), RotateY( Position(0, 0, zPosition), mirrorAngle) );
0148       }
0149       
0150       // solid for the tube (including vacuum and wall): a solid cone
0151       ConeSegment tubeSolid( zHalf, rInnerStart, rOuterStart, rInnerEnd, rOuterEnd , phi1, phi2);
0152 
0153       // tube consists of vacuum
0154       Volume tubeLog0( volName, tubeSolid, material ) ;
0155       Volume tubeLog1( volName, tubeSolid, material ) ;
0156       if (isSensitive) {
0157         tubeLog0.setSensitiveDetector(sens);
0158         tubeLog1.setSensitiveDetector(sens);
0159       }
0160       tubeLog0.setVisAttributes(description, xmlMask.visStr() );
0161       tubeLog1.setVisAttributes(description, xmlMask.visStr() );
0162 
0163       // placement of the tube in the world, both at +z and -z
0164       PlacedVolume placed0 = envelope.placeVolume( tubeLog0,  transformer );
0165       PlacedVolume placed1 = envelope.placeVolume( tubeLog1,  transmirror );
0166 
0167       placed0.addPhysVolID("side",1);
0168       placed0.addPhysVolID("layer",counter);
0169       placed1.addPhysVolID("side",-1);
0170       placed1.addPhysVolID("layer",counter);
0171       
0172     }
0173       break;
0174 
0175     case ODH::kPunchedCenter: {
0176       // a cone with one or two inner holes (two tubes are punched out)
0177 
0178       const double rUpstreamPunch = rInnerStart; // just alias names denoting what is meant here
0179       const double rDnstreamPunch = rInnerEnd; // (the database entries are "abused" in this case)
0180 
0181       // relative transformations for the composition of the SubtractionVolumes
0182       Transform3D upstreamTransformer(RotationY(-crossingAngle), Position(zPosition * tan(-crossingAngle), 0, 0));
0183       Transform3D dnstreamTransformer(RotationY(+crossingAngle), Position(zPosition * tan(+crossingAngle), 0, 0));
0184 
0185       // absolute transformations for the final placement in the world (angles always equal zero and 180 deg)
0186       Transform3D placementTransformer(RotationY(rotateAngle), RotateY( Position(0, 0, zPosition) , rotateAngle) );
0187       Transform3D placementTransmirror(RotationY(mirrorAngle), RotateY( Position(0, 0, zPosition) , mirrorAngle) );
0188 
0189       // the main solid and the two pieces (only tubes, for the moment) which will be punched out
0190       ConeSegment wholeSolid(  zHalf, 0, rOuterStart, 0, rOuterEnd, phi1, phi2 );
0191       Solid tmpSolid0, tmpSolid1, finalSolid0, finalSolid1;
0192 
0193       // the punched subtraction solids can be asymmetric and therefore have to be created twice:
0194       // one time in the "right" way, another time in the "reverse" way, because the "mirroring"
0195       // rotation around the y-axis will not only exchange +z and -z, but also +x and -x
0196 
0197       if ( rUpstreamPunch > 1e-6 ) { // do we need a hole on the upstream branch?
0198     Tube upstreamPunch( 0, rUpstreamPunch, 5 * zHalf, phi1, phi2); // a bit longer
0199     tmpSolid0 = SubtractionSolid( wholeSolid, upstreamPunch, upstreamTransformer);
0200     tmpSolid1 = SubtractionSolid( wholeSolid, upstreamPunch, dnstreamTransformer); // [sic]
0201       } else { // dont't do anything, just pass on the unmodified shape
0202     tmpSolid0 = wholeSolid;
0203     tmpSolid1 = wholeSolid;
0204       }
0205 
0206       if (rDnstreamPunch > 1e-6 ) { // do we need a hole on the downstream branch?
0207     Tube dnstreamPunch( 0, rDnstreamPunch, 5 * zHalf, phi1, phi2); // a bit longer
0208     finalSolid0 = SubtractionSolid( tmpSolid0, dnstreamPunch, dnstreamTransformer);
0209     finalSolid1 = SubtractionSolid( tmpSolid1, dnstreamPunch, upstreamTransformer); // [sic]
0210       } else { // dont't do anything, just pass on the unmodified shape
0211     finalSolid0 = tmpSolid0;
0212     finalSolid1 = tmpSolid1;
0213       }
0214 
0215       // tube consists of vacuum (will later have two different daughters)
0216       Volume tubeLog0( volName + "_0", finalSolid0, material );
0217       Volume tubeLog1( volName + "_1", finalSolid1, material );
0218       if (isSensitive) {
0219         tubeLog0.setSensitiveDetector(sens);
0220         tubeLog1.setSensitiveDetector(sens);
0221       }
0222       tubeLog0.setVisAttributes(description, xmlMask.visStr() );
0223       tubeLog1.setVisAttributes(description, xmlMask.visStr() );
0224 
0225       // placement of the tube in the world, both at +z and -z
0226       PlacedVolume placed0 = envelope.placeVolume( tubeLog0, placementTransformer );
0227       PlacedVolume placed1 = envelope.placeVolume( tubeLog1, placementTransmirror );
0228       
0229       placed0.addPhysVolID("side",  1);
0230       placed1.addPhysVolID("side", -1);
0231       placed0.addPhysVolID("layer", counter);
0232       placed1.addPhysVolID("layer", counter);
0233 
0234       break;
0235     }
0236 
0237     case ODH::kPunchedUpstream:
0238     case ODH::kPunchedDnstream: {
0239       // a volume on the upstream or downstream branch with two inner holes
0240       // (implemented as a cone from which another tube is punched out)
0241 
0242       const double rCenterPunch = (crossType == ODH::kPunchedUpstream) ? (rInnerStart) : (rInnerEnd); // just alias names denoting what is meant here
0243       const double rOffsetPunch = (crossType == ODH::kPunchedDnstream) ? (rInnerStart) : (rInnerEnd); // (the database entries are "abused" in this case)
0244 
0245       // relative transformations for the composition of the SubtractionVolumes
0246       Transform3D punchTransformer(RotationY(-2 * rotateAngle), Position(zPosition * tan(-2 * rotateAngle), 0, 0));
0247       Transform3D punchTransmirror(RotationY(+2 * rotateAngle), Position(zPosition * tan(+2 * rotateAngle), 0, 0));
0248 
0249       // absolute transformations for the final placement in the world
0250       Transform3D placementTransformer(RotationY(rotateAngle), RotateY( Position(0, 0, zPosition) , rotateAngle) );
0251       Transform3D placementTransmirror(RotationY(mirrorAngle), RotateY( Position(0, 0, zPosition) , mirrorAngle) );
0252 
0253       // the main solid and the piece (only a tube, for the moment) which will be punched out
0254       ConeSegment wholeSolid( zHalf, rCenterPunch , rOuterStart, rCenterPunch, rOuterEnd, phi1, phi2);
0255       Tube punchSolid( 0, rOffsetPunch, 5 * zHalf, phi1, phi2); // a bit longer
0256 
0257       // the punched subtraction solids can be asymmetric and therefore have to be created twice:
0258       // one time in the "right" way, another time in the "reverse" way, because the "mirroring"
0259       // rotation around the y-axis will not only exchange +z and -z, but also +x and -x
0260       SubtractionSolid finalSolid0( wholeSolid, punchSolid, punchTransformer);
0261       SubtractionSolid finalSolid1( wholeSolid, punchSolid, punchTransmirror);
0262 
0263       // tube consists of vacuum (will later have two different daughters)
0264       Volume tubeLog0( volName + "_0", finalSolid0, material );
0265       Volume tubeLog1( volName + "_1", finalSolid1, material );
0266       if (isSensitive) {
0267         tubeLog0.setSensitiveDetector(sens);
0268         tubeLog1.setSensitiveDetector(sens);
0269       }
0270       tubeLog0.setVisAttributes(description, xmlMask.visStr() );
0271       tubeLog1.setVisAttributes(description, xmlMask.visStr() );
0272 
0273       // placement of the tube in the world, both at +z and -z
0274       PlacedVolume placed0 = envelope.placeVolume( tubeLog0, placementTransformer );
0275       PlacedVolume placed1 = envelope.placeVolume( tubeLog1, placementTransmirror );
0276 
0277       placed0.addPhysVolID("side",  1);
0278       placed1.addPhysVolID("side", -1);
0279       placed0.addPhysVolID("layer", counter);
0280       placed1.addPhysVolID("layer", counter);
0281 
0282       break;
0283     }
0284     default: {
0285       throw std::runtime_error( " Mask_o1_v01_geo.cpp : fatal failure !! ??  " ) ;
0286     }
0287 
0288     }//end switch
0289     
0290   }//for all xmlSections
0291 
0292   //--------------------------------------
0293   Volume mother =  description.pickMotherVolume( tube ) ;
0294   PlacedVolume pv(mother.placeVolume(envelope));
0295   pv.addPhysVolID( "system", xmlMask.id() ) ; //.addPhysVolID("side", 0 ) ;
0296 
0297   tube.setVisAttributes( description, xmlMask.visStr(), envelope );
0298 
0299   tube.setPlacement(pv);
0300 
0301   return tube;
0302 }
0303 DECLARE_DETELEMENT(DD4hep_Mask_o1_v01,create_detector)