diff --git a/DDDetectors/src/GenericSurfaceInstaller.cpp b/DDDetectors/src/GenericSurfaceInstaller.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2807dd769b7cd4767cfccd0123ed0ff64fcc5446 --- /dev/null +++ b/DDDetectors/src/GenericSurfaceInstaller.cpp @@ -0,0 +1,168 @@ +//========================================================================== +// Surface installer plugin for generic sliced detector drivers +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : N. Nikiforou, adapted from DD4hep/SiTrackerBarrel_surfaces.cpp +// by M. Frank. Originally part of the lcgeo package +//========================================================================== + +/** \addtogroup SurfacePlugin + * @{ + * \package DD4hep_GenericSurfaceInstallerPlugin + * \brief Plugin to install measurement surfaces on a generic sliced detector + * + * Takes up to 13 arguments: + * - dimension: A property of the surface that determines whether the resulting + * measurement is 1-D, e.g. strips (dimension=1) or 2-D, e.g. pixels (dimension=2) + * - u_x, u_y, and u_z The x,y, and z components of the u vector, usually associated + * with the "good" (i.e. best resolution) measurement direction + * - v_x, v_y, and v_z The x,y, and z components of the v vector, usually associated + * with the "bad" (i.e. worst resolution) measurement direction + * - n_x, n_y, and n_z The x,y, and z components of the vector perpendicular to the surface + * plane and usually pointing outwards of the detector. + * - o_x, o_y, and o_z The x,y, and z components of the origin vector, used to shift the origin + * of the surface from where it is placed within the volume (usually in the center + * of a sensitive volume. + * + * All the arguments are conveniently initialized to zero by default, + * therefore only the non-zero components need to be provided. + * + * The plugin assumes boxes are stacked along one of the primary axes, x,y or z + * The normal vector (n) must be along one of the axes (i.e. only one non-zero + * component). The inner/outer thicknesses are calculated according to n. + * + * Note: Assumes module and component volumes are boxes. For Trapezoids, + * a fitting box is built around the trapezoid which means dx1=dx2=dx1 and + * dy1=dy2=dy. This is in principle fine, since we only access the thicknesses + * (DY in the TrackerEncapSurfacePlugin example) which is supposed to be the same + * @} + */ + +namespace { + struct UserData { + int dimension ; + double uvector[3]; + double vvector[3]; + double nvector[3]; + double ovector[3]; + + }; + +} + +// Framework include files +#define SURFACEINSTALLER_DATA UserData +#define DD4HEP_USE_SURFACEINSTALL_HELPER DD4hep_GenericSurfaceInstallerPlugin +#include "DD4hep/SurfaceInstaller.h" + +namespace{ + template <> void Installer<UserData>::handle_arguments(int argc, char** argv) { + + //Initialize defaults to zero + data.dimension=0; + data.uvector[0]=0.; + data.uvector[1]=0.; + data.uvector[2]=0.; + data.vvector[0]=0.; + data.vvector[1]=0.; + data.vvector[2]=0.; + data.nvector[0]=0.; + data.nvector[1]=0.; + data.nvector[2]=0.; + data.ovector[0]=0.; + data.ovector[1]=0.; + data.ovector[2]=0.; + + for(int i=0; i<argc; ++i) { + double value = -1; + char* ptr = ::strchr(argv[i],'='); + if ( ptr ) { + std::string name( argv[i] , ptr ) ; + value = DD4hep::Geometry::_toDouble(++ptr); + std::cout << "DD4hep_GenericSurfaceInstallerPlugin: argument[" << i << "] = " << name + << " = " << value << std::endl; + if( name=="dimension" ) data.dimension = value ; + if( name=="u_x" ) data.uvector[0]=value ; + if( name=="u_y" ) data.uvector[1]=value ; + if( name=="u_z" ) data.uvector[2]=value ; + if( name=="v_x" ) data.vvector[0]=value ; + if( name=="v_y" ) data.vvector[1]=value ; + if( name=="v_z" ) data.vvector[2]=value ; + if( name=="n_x" ) data.nvector[0]=value ; + if( name=="n_y" ) data.nvector[1]=value ; + if( name=="n_z" ) data.nvector[2]=value ; + if( name=="o_x" ) data.ovector[0]=value ; + if( name=="o_y" ) data.ovector[1]=value ; + if( name=="o_z" ) data.ovector[2]=value ; + } + } + + std::cout <<"DD4hep_GenericSurfaceInstallerPlugin: vectors: "; + std::cout <<"u( "<<data.uvector[0]<<" , "<<data.uvector[1]<<" , "<<data.uvector[2]<<") "; + std::cout <<"v( "<<data.vvector[0]<<" , "<<data.vvector[1]<<" , "<<data.vvector[2]<<") "; + std::cout <<"n( "<<data.nvector[0]<<" , "<<data.nvector[1]<<" , "<<data.nvector[2]<<") "; + std::cout <<"o( "<<data.ovector[0]<<" , "<<data.ovector[1]<<" , "<<data.ovector[2]<<") "<<std::endl; + + } + + /// Install measurement surfaces + template <typename UserData> + void Installer<UserData>::install(DetElement component, PlacedVolume pv) { + Volume comp_vol = pv.volume(); + if ( comp_vol.isSensitive() ) { + Volume mod_vol = parentVolume(component); + //FIXME: WHAT IF TRAPEZOID? Should work if trapezoid since it will fit minimal box and dy1=dy2=dy + DD4hep::Geometry::Box mod_shape(mod_vol.solid()), comp_shape(comp_vol.solid()); + + if ( !comp_shape.isValid() || !mod_shape.isValid() ) { + invalidInstaller("DD4hep_GenericSurfaceInstallerPlugin: Components and/or modules are not boxes -- invalid shapes"); + + }else if ( !handleUsingCache(component,comp_vol) ) { + const double* trans = placementTranslation(component); + double half_module_thickness = 0.; + double sensitive_z_position = 0.; + + if (data.nvector[0] !=0 && data.nvector[1] ==0 && data.nvector[2] ==0){ + half_module_thickness = mod_shape->GetDX(); + sensitive_z_position = data.nvector[0]>0 ? trans[0] : -trans[0]; + }else if (data.nvector[1] !=0 && data.nvector[0] ==0 && data.nvector[2] ==0){ + half_module_thickness = mod_shape->GetDY(); + sensitive_z_position = data.nvector[1]>0 ? trans[1] : -trans[1]; + + }else if (data.nvector[2] !=0 && data.nvector[0] ==0 && data.nvector[1] ==0){ + half_module_thickness = mod_shape->GetDZ(); + sensitive_z_position = data.nvector[2]>0 ? trans[2] : -trans[2]; + + } else { + throw std::runtime_error("**** DD4hep_GenericSurfaceInstallerPlugin: normal vector unsupported! It has to be " + "perpenidcular to one of the box sides, i.e. only one non-zero component.") ; + } + + double inner_thickness = half_module_thickness + sensitive_z_position; + double outer_thickness = half_module_thickness - sensitive_z_position; + + //Surface is placed at the center of the volume, no need to shift origin + //Make sure u,v,n form a right-handed coordinate system, v along the final z + Vector3D u(data.uvector[0],data.uvector[1],data.uvector[2]); + Vector3D v(data.vvector[0],data.vvector[1],data.vvector[2]); + Vector3D n(data.nvector[0],data.nvector[1],data.nvector[2]); + Vector3D o(data.ovector[0],data.ovector[1],data.ovector[2]); + Type type( Type::Sensitive ) ; + + if( data.dimension == 1 ) { + type.setProperty( Type::Measurement1D , true ) ; + } else if( data.dimension != 2 ) { + throw std::runtime_error("**** DD4hep_GenericSurfaceInstallerPlugin: no or wrong " + "'dimension' argument given - has to be 1 or 2") ; + } + VolPlane surf(comp_vol, type, inner_thickness, outer_thickness, u, v, n, o); + addSurface(component,surf); + } + } + } +}// namespace