From 8721b2bcbca0dc4cd70cccd3a0e1d0385e26580c Mon Sep 17 00:00:00 2001 From: Markus Frank Date: Tue, 16 Jan 2024 13:52:34 +0100 Subject: [PATCH 1/2] Fix facetIsDegenerated utility function --- DDCAD/CMakeLists.txt | 4 +- DDCAD/include/DDCAD/Utilities.h | 15 +- examples/AlignDet/src/AlephTPC_geo.cpp | 282 ++++++++++++------------- 3 files changed, 151 insertions(+), 150 deletions(-) diff --git a/DDCAD/CMakeLists.txt b/DDCAD/CMakeLists.txt index a85572aff..8e9df077d 100644 --- a/DDCAD/CMakeLists.txt +++ b/DDCAD/CMakeLists.txt @@ -37,8 +37,8 @@ elseif(DD4HEP_LOAD_ASSIMP) ExternalProject_Add( assimp_project - SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/external/assimp - INSTALL_DIR ${CMAKE_INSTALL_PREFIX} + SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/external/assimp + INSTALL_DIR ${CMAKE_INSTALL_PREFIX} GIT_REPOSITORY https://github.com/assimp/assimp.git GIT_TAG v5.0.1 CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX} diff --git a/DDCAD/include/DDCAD/Utilities.h b/DDCAD/include/DDCAD/Utilities.h index 6e12f0401..effbbeb5d 100644 --- a/DDCAD/include/DDCAD/Utilities.h +++ b/DDCAD/include/DDCAD/Utilities.h @@ -14,6 +14,7 @@ #define DDCAD_UTILITIES_H #include +#include #include #include @@ -63,13 +64,13 @@ namespace dd4hep { // // v1.z v2.z v3.z v1.z v2.z double det = 0.0 - + v1.x() * v2.y() * v3.z() - + v2.x() * v3.y() * v1.z() - + v3.x() * v1.y() * v2.z() - - v1.z() * v2.y() * v3.x() - - v2.z() * v3.y() * v1.x() - - v3.z() * v1.y() * v2.x(); - return det < epsilon; + + v1.x() * v2.y() * v3.z() + + v2.x() * v3.y() * v1.z() + + v3.x() * v1.y() * v2.z() + - v1.z() * v2.y() * v3.x() + - v2.z() * v3.y() * v1.x() + - v3.z() * v1.y() * v2.x(); + return std::fabs(det) < epsilon; } } } diff --git a/examples/AlignDet/src/AlephTPC_geo.cpp b/examples/AlignDet/src/AlephTPC_geo.cpp index 0c0fe041d..b4a089d03 100644 --- a/examples/AlignDet/src/AlephTPC_geo.cpp +++ b/examples/AlignDet/src/AlephTPC_geo.cpp @@ -164,133 +164,133 @@ static Ref_t create_element(Detector& description, xml_h e, SensitiveDetector se if ( layer_vis.empty() ) layer_vis = sector_vis; if ( sector_type == 'K' ) { - double angle = M_PI/12.0; - double angle1 = std::tan(angle); - double v[8][2]; - v[0][0] = rmin; - v[0][1] = 0; - v[1][0] = rmin; - v[1][1] = rmin*angle1; - v[2][0] = rmax; - v[2][1] = rmax*angle1; - v[3][0] = rmax; - v[3][1] = 0; - ::memcpy(&v[4][0],&v[0][0],8*sizeof(double)); - EightPointSolid upper(layer_thickness/2,&v[0][0]); - - v[0][0] = rmin; - v[0][1] = 0; - v[1][0] = rmax; - v[1][1] = 0; - v[2][0] = rmax; - v[2][1] = -rmax*angle1; - v[3][0] = rmin; - v[3][1] = -rmin*angle1; - ::memcpy(&v[4][0],&v[0][0],8*sizeof(double)); - EightPointSolid lower(layer_thickness/2,&v[0][0]); - - v[0][0] = rmin; - v[0][1] = gap_half; - v[1][0] = rmin; - v[1][1] = rmin*angle1; - v[2][0] = rmax; - v[2][1] = rmax*angle1; - v[3][0] = rmax; - v[3][1] = gap_half; - ::memcpy(&v[4][0],&v[0][0],8*sizeof(double)); - EightPointSolid top(layer_thickness/2,&v[0][0]); - - v[0][0] = rmin; - v[0][1] = -gap_half; - v[1][0] = rmax; - v[1][1] = -gap_half; - v[2][0] = rmax; - v[2][1] = -rmax*angle1; - v[3][0] = rmin; - v[3][1] = -rmin*angle1; - ::memcpy(&v[4][0],&v[0][0],8*sizeof(double)); - EightPointSolid bottom(layer_thickness/2,&v[0][0]); - - UnionSolid u(UnionSolid(upper,lower),top,Rotation3D(RotationZ(2*(angle)))); - tm = UnionSolid(u,bottom,Rotation3D(RotationZ(-2*(angle)))); + double angle = M_PI/12.0; + double angle1 = std::tan(angle); + double v[8][2]; + v[0][0] = rmin; + v[0][1] = 0; + v[1][0] = rmin; + v[1][1] = rmin*angle1; + v[2][0] = rmax; + v[2][1] = rmax*angle1; + v[3][0] = rmax; + v[3][1] = 0; + ::memcpy(&v[4][0],&v[0][0],8*sizeof(double)); + EightPointSolid upper(layer_thickness/2,&v[0][0]); + + v[0][0] = rmin; + v[0][1] = 0; + v[1][0] = rmax; + v[1][1] = 0; + v[2][0] = rmax; + v[2][1] = -rmax*angle1; + v[3][0] = rmin; + v[3][1] = -rmin*angle1; + ::memcpy(&v[4][0],&v[0][0],8*sizeof(double)); + EightPointSolid lower(layer_thickness/2,&v[0][0]); + + v[0][0] = rmin; + v[0][1] = gap_half; + v[1][0] = rmin; + v[1][1] = rmin*angle1; + v[2][0] = rmax; + v[2][1] = rmax*angle1; + v[3][0] = rmax; + v[3][1] = gap_half; + ::memcpy(&v[4][0],&v[0][0],8*sizeof(double)); + EightPointSolid top(layer_thickness/2,&v[0][0]); + + v[0][0] = rmin; + v[0][1] = -gap_half; + v[1][0] = rmax; + v[1][1] = -gap_half; + v[2][0] = rmax; + v[2][1] = -rmax*angle1; + v[3][0] = rmin; + v[3][1] = -rmin*angle1; + ::memcpy(&v[4][0],&v[0][0],8*sizeof(double)); + EightPointSolid bottom(layer_thickness/2,&v[0][0]); + + UnionSolid u(UnionSolid(upper,lower),top,Rotation3D(RotationZ(2*(angle)))); + tm = UnionSolid(u,bottom,Rotation3D(RotationZ(-2*(angle)))); } else { - double overlap = sector_type=='W' ? 20 : -20; - double angle = M_PI/12.0; - double angle1 = std::tan(angle); - double v[8][2], dr = 0; - - if ( sector_type == 'W' ) { - rmax += overlap*std::tan(angle/2); - dr = overlap*std::tan(angle/2); - } - - v[0][0] = rmin; - v[0][1] = -rmin*angle1+gap_half; - v[1][0] = rmin; - v[1][1] = rmin*angle1-gap_half; - v[2][0] = rmax; - v[2][1] = rmax*angle1-gap_half; - v[3][0] = rmax; - v[3][1] = -rmax*angle1+gap_half; - ::memcpy(&v[4][0],&v[0][0],8*sizeof(double)); - printCoordinates(sector_type,"t2:",v); - EightPointSolid sectorSolid(layer_thickness/2,&v[0][0]); - - if ( sector_type=='W' ) { - v[0][0] = (rmax+rmin)/2-dr; - v[0][1] = (rmax+rmin)/2*angle1-gap_half; - v[1][0] = rmax+0.0001; - v[1][1] = rmax*angle1-gap_half; - v[2][0] = rmax+0.0001; - v[2][1] = (rmax-overlap)*angle1-gap_half; - v[3][0] = (rmax+rmin)/2-dr; - v[3][1] = (rmax+rmin-overlap)/2*angle1-gap_half; - } - else { - v[0][0] = (rmax+rmin)/2-dr; - v[0][1] = (rmax+rmin)/2*angle1-gap_half; - v[3][0] = rmax+0.0001; - v[3][1] = rmax*angle1-gap_half; - v[2][0] = rmax+0.0001; - v[2][1] = (rmax-overlap)*angle1-gap_half; - v[1][0] = (rmax+rmin)/2-dr; - v[1][1] = (rmax+rmin-overlap)/2*angle1-gap_half; - } - printCoordinates(sector_type,"upper_boolean:",v); - ::memcpy(&v[4][0],&v[0][0],8*sizeof(double)); - EightPointSolid upper_boolean((sector_type == 'W' ? 1.1 : 1.0) * layer_thickness/2,&v[0][0]); - - if ( sector_type=='W' ) { - v[0][0] = (rmax+rmin)/2-dr; - v[0][1] = -((rmax+rmin)/2*angle1-gap_half); - v[1][0] = (rmax+rmin)/2-dr; - v[1][1] = -((rmax+rmin-overlap)/2*angle1-gap_half); - v[2][0] = rmax+0.0001; - v[2][1] = -((rmax-overlap)*angle1-gap_half); - v[3][0] = rmax+0.0001; - v[3][1] = -(rmax*angle1-gap_half); - } - else { - v[0][0] = (rmax+rmin)/2-dr; - v[0][1] = -((rmax+rmin)/2*angle1-gap_half); - v[3][0] = (rmax+rmin)/2-dr; - v[3][1] = -((rmax+rmin-overlap)/2*angle1-gap_half); - v[2][0] = rmax+0.0001; - v[2][1] = -((rmax-overlap)*angle1-gap_half); - v[1][0] = rmax+0.0001; - v[1][1] = -(rmax*angle1-gap_half); - } - printCoordinates(sector_type,"lower_boolean:",v); - ::memcpy(&v[4][0],&v[0][0],8*sizeof(double)); - - // For W sectors make the subtraction solid slightly thicker to ensure everything is cut off - // and no left-overs from numerical precision are left. - EightPointSolid lower_boolean((sector_type == 'W' ? 1.1 : 1.0) * layer_thickness/2,&v[0][0]); - if ( sector_type == 'W' ) - tm = SubtractionSolid(SubtractionSolid(sectorSolid,upper_boolean),lower_boolean); - else - tm = UnionSolid(UnionSolid(sectorSolid,upper_boolean),lower_boolean); + double overlap = sector_type=='W' ? 20 : -20; + double angle = M_PI/12.0; + double angle1 = std::tan(angle); + double v[8][2], dr = 0; + + if ( sector_type == 'W' ) { + rmax += overlap*std::tan(angle/2); + dr = overlap*std::tan(angle/2); + } + + v[0][0] = rmin; + v[0][1] = -rmin*angle1+gap_half; + v[1][0] = rmin; + v[1][1] = rmin*angle1-gap_half; + v[2][0] = rmax; + v[2][1] = rmax*angle1-gap_half; + v[3][0] = rmax; + v[3][1] = -rmax*angle1+gap_half; + ::memcpy(&v[4][0],&v[0][0],8*sizeof(double)); + printCoordinates(sector_type,"t2:",v); + EightPointSolid sectorSolid(layer_thickness/2,&v[0][0]); + + if ( sector_type=='W' ) { + v[0][0] = (rmax+rmin)/2-dr; + v[0][1] = (rmax+rmin)/2*angle1-gap_half; + v[1][0] = rmax+0.0001; + v[1][1] = rmax*angle1-gap_half; + v[2][0] = rmax+0.0001; + v[2][1] = (rmax-overlap)*angle1-gap_half; + v[3][0] = (rmax+rmin)/2-dr; + v[3][1] = (rmax+rmin-overlap)/2*angle1-gap_half; + } + else { + v[0][0] = (rmax+rmin)/2-dr; + v[0][1] = (rmax+rmin)/2*angle1-gap_half; + v[3][0] = rmax+0.0001; + v[3][1] = rmax*angle1-gap_half; + v[2][0] = rmax+0.0001; + v[2][1] = (rmax-overlap)*angle1-gap_half; + v[1][0] = (rmax+rmin)/2-dr; + v[1][1] = (rmax+rmin-overlap)/2*angle1-gap_half; + } + printCoordinates(sector_type,"upper_boolean:",v); + ::memcpy(&v[4][0],&v[0][0],8*sizeof(double)); + EightPointSolid upper_boolean((sector_type == 'W' ? 1.1 : 1.0) * layer_thickness/2,&v[0][0]); + + if ( sector_type=='W' ) { + v[0][0] = (rmax+rmin)/2-dr; + v[0][1] = -((rmax+rmin)/2*angle1-gap_half); + v[1][0] = (rmax+rmin)/2-dr; + v[1][1] = -((rmax+rmin-overlap)/2*angle1-gap_half); + v[2][0] = rmax+0.0001; + v[2][1] = -((rmax-overlap)*angle1-gap_half); + v[3][0] = rmax+0.0001; + v[3][1] = -(rmax*angle1-gap_half); + } + else { + v[0][0] = (rmax+rmin)/2-dr; + v[0][1] = -((rmax+rmin)/2*angle1-gap_half); + v[3][0] = (rmax+rmin)/2-dr; + v[3][1] = -((rmax+rmin-overlap)/2*angle1-gap_half); + v[2][0] = rmax+0.0001; + v[2][1] = -((rmax-overlap)*angle1-gap_half); + v[1][0] = rmax+0.0001; + v[1][1] = -(rmax*angle1-gap_half); + } + printCoordinates(sector_type,"lower_boolean:",v); + ::memcpy(&v[4][0],&v[0][0],8*sizeof(double)); + + // For W sectors make the subtraction solid slightly thicker to ensure everything is cut off + // and no left-overs from numerical precision are left. + EightPointSolid lower_boolean((sector_type == 'W' ? 1.1 : 1.0) * layer_thickness/2,&v[0][0]); + if ( sector_type == 'W' ) + tm = SubtractionSolid(SubtractionSolid(sectorSolid,upper_boolean),lower_boolean); + else + tm = UnionSolid(UnionSolid(sectorSolid,upper_boolean),lower_boolean); } Volume secVol(name+"_sector_"+sector_type+_toString(i_layer,"_layer%d"),tm,description.material(layer_mat)); @@ -304,22 +304,22 @@ static Ref_t create_element(Detector& description, xml_h e, SensitiveDetector se int j = i + (sector_type=='W' ? 1 : 0); double phi = dphi*j+shift + (sector_type=='K' ? 0 : M_PI/12.0); if ( sector_type == 'K' || (i%2)==0 ) { - Transform3D trA(RotationZYX(phi,0,0),Position(0,0,0.00001)); - Transform3D trB(RotationZYX(phi,0,0),Position(0,0,0.00001)); - - pv = endCapAVol.placeVolume(sector,trA); - pv.addPhysVolID("type", sector_type=='K' ? 1 : sector_type=='M' ? 2 : 3); - pv.addPhysVolID("sector",j); - DetElement sectorA(detA,detA.name()+_toString(sector_count,"_sector%02d"),1); - sectorA.setPlacement(pv); - - pv = endCapBVol.placeVolume(sector,trB); - pv.addPhysVolID("type", sector_type=='K' ? 1 : sector_type=='M' ? 2 : 3); - pv.addPhysVolID("sector",j); - DetElement sectorB(detB,detB.name()+_toString(sector_count,"_sector%02d"),1); - sectorB.setPlacement(pv); - cout << "Placed " << sector_type << " sector at phi=" << phi << endl; - ++sector_count; + Transform3D trA(RotationZYX(phi,0,0),Position(0,0,0.00001)); + Transform3D trB(RotationZYX(phi,0,0),Position(0,0,0.00001)); + + pv = endCapAVol.placeVolume(sector,trA); + pv.addPhysVolID("type", sector_type=='K' ? 1 : sector_type=='M' ? 2 : 3); + pv.addPhysVolID("sector",j); + DetElement sectorA(detA,detA.name()+_toString(sector_count,"_sector%02d"),1); + sectorA.setPlacement(pv); + + pv = endCapBVol.placeVolume(sector,trB); + pv.addPhysVolID("type", sector_type=='K' ? 1 : sector_type=='M' ? 2 : 3); + pv.addPhysVolID("sector",j); + DetElement sectorB(detB,detB.name()+_toString(sector_count,"_sector%02d"),1); + sectorB.setPlacement(pv); + cout << "Placed " << sector_type << " sector at phi=" << phi << endl; + ++sector_count; } } } From 0bc3e03e6e66c458ceebd245a4e009629f547963 Mon Sep 17 00:00:00 2001 From: Markus Frank Date: Tue, 16 Jan 2024 17:38:41 +0100 Subject: [PATCH 2/2] Add FiberTubeCalorimeter test detector. See https://github.com/AIDASoft/DD4hep/issues/1173 --- DDCore/src/plugins/DetectorCheck.cpp | 73 ++++---- .../compact/FiberTubeCalorimeter.xml | 110 +++++++++++ .../src/FiberTubeCalorimeter_geo.cpp | 177 ++++++++++++++++++ 3 files changed, 328 insertions(+), 32 deletions(-) create mode 100644 examples/ClientTests/compact/FiberTubeCalorimeter.xml create mode 100644 examples/ClientTests/src/FiberTubeCalorimeter_geo.cpp diff --git a/DDCore/src/plugins/DetectorCheck.cpp b/DDCore/src/plugins/DetectorCheck.cpp index 21421a8a1..2add90095 100644 --- a/DDCore/src/plugins/DetectorCheck.cpp +++ b/DDCore/src/plugins/DetectorCheck.cpp @@ -97,6 +97,7 @@ namespace { bool check_placements { false }; bool check_volmgr { false }; bool check_sensitive { false }; + bool ignore_detector { false }; SensitiveDetector get_current_sensitive_detector(); @@ -449,7 +450,7 @@ void DetectorCheck::checkManagerSingleVolume(DetElement detector, PlacedVolume p if ( pv.volume().isSensitive() ) { PlacedVolume det_place = m_volMgr.lookupDetElementPlacement(vid); ++m_sens_counters.elements; - if ( pv.ptr() != det_place.ptr() ) { + if ( !ignore_detector && pv.ptr() != det_place.ptr() ) { err << "VolumeMgrTest: Wrong placement " << " got " << det_place.name() << " (" << (void*)det_place.ptr() << ")" << " instead of " << pv.name() << " (" << (void*)pv.ptr() << ") " @@ -551,33 +552,35 @@ void DetectorCheck::checkManagerSingleVolume(DetElement detector, PlacedVolume p printout(ERROR, m_det.name(), "DETELEMENT_PERSISTENCY FAILED: World transformation have DIFFERET pointer!"); ++m_place_counters.errors; } - - if ( pv.ptr() == det_elem.placement().ptr() ) { - // The computed transformation 'trafo' MUST be equal to: - // m_volMgr.worldTransformation(vid) AND det_elem.nominal().worldTransformation() - int res1 = detail::matrix::_matrixEqual(trafo, det_elem.nominal().worldTransformation()); - int res2 = detail::matrix::_matrixEqual(trafo, m_volMgr.worldTransformation(m_mapping,vid)); - if ( res1 != detail::matrix::MATRICES_EQUAL || res2 != detail::matrix::MATRICES_EQUAL ) { - printout(ERROR, m_det.name(), "DETELEMENT_PLACEMENT FAILED: World transformation DIFFER."); - ++m_place_counters.errors; - } - else { - printout(INFO, m_det.name(), "DETELEMENT_PLACEMENT: PASSED. All matrices equal: %s", - volumeID(vid).c_str()); - } - } - else { - // The computed transformation 'trafo' MUST be equal to: - // m_volMgr.worldTransformation(vid) - // The det_elem.nominal().worldTransformation() however is DIFFERENT! - int res2 = detail::matrix::_matrixEqual(trafo, m_volMgr.worldTransformation(m_mapping,vid)); - if ( res2 != detail::matrix::MATRICES_EQUAL ) { - printout(ERROR, m_det.name(), "VOLUME_PLACEMENT FAILED: World transformation DIFFER."); - ++m_place_counters.errors; + + if ( !ignore_detector ) { + if ( pv.ptr() == det_elem.placement().ptr() ) { + // The computed transformation 'trafo' MUST be equal to: + // m_volMgr.worldTransformation(vid) AND det_elem.nominal().worldTransformation() + int res1 = detail::matrix::_matrixEqual(trafo, det_elem.nominal().worldTransformation()); + int res2 = detail::matrix::_matrixEqual(trafo, m_volMgr.worldTransformation(m_mapping,vid)); + if ( res1 != detail::matrix::MATRICES_EQUAL || res2 != detail::matrix::MATRICES_EQUAL ) { + printout(ERROR, m_det.name(), "DETELEMENT_PLACEMENT FAILED: World transformation DIFFER."); + ++m_place_counters.errors; + } + else { + printout(INFO, m_det.name(), "DETELEMENT_PLACEMENT: PASSED. All matrices equal: %s", + volumeID(vid).c_str()); + } } else { - printout(INFO, m_det.name(), "VOLUME_PLACEMENT: PASSED. All matrices equal: %s", - volumeID(vid).c_str()); + // The computed transformation 'trafo' MUST be equal to: + // m_volMgr.worldTransformation(vid) + // The det_elem.nominal().worldTransformation() however is DIFFERENT! + int res2 = detail::matrix::_matrixEqual(trafo, m_volMgr.worldTransformation(m_mapping,vid)); + if ( res2 != detail::matrix::MATRICES_EQUAL ) { + printout(ERROR, m_det.name(), "VOLUME_PLACEMENT FAILED: World transformation DIFFER."); + ++m_place_counters.errors; + } + else { + printout(INFO, m_det.name(), "VOLUME_PLACEMENT: PASSED. All matrices equal: %s", + volumeID(vid).c_str()); + } } } } @@ -643,6 +646,7 @@ void DetectorCheck::help(int argc,char** argv) { " sensitive volume placements. \n\n" " NOTE: Option requires proper PhysVolID setup \n" " of the sensitive volume placements ! \n" + " -ignore_detector Ignore DetElement placement check for -volmgr \n" << std::endl; std::cout << "Arguments: " << std::endl; for(int iarg=0; iarg + + The compact format for the SCEPCAL IDEA from Sarah Eno + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + system:8,layer:12,tube:12,hole:3,type:3 + + + + + + + + + + + + + + + + + + diff --git a/examples/ClientTests/src/FiberTubeCalorimeter_geo.cpp b/examples/ClientTests/src/FiberTubeCalorimeter_geo.cpp new file mode 100644 index 000000000..ed2251b2b --- /dev/null +++ b/examples/ClientTests/src/FiberTubeCalorimeter_geo.cpp @@ -0,0 +1,177 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// 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 : M.Frank +// +//========================================================================== +// +// Specialized generic detector constructor for fiber tube calorimeter. +// See https://github.com/AIDASoft/DD4hep/issues/1173 for details +// +// Detector geometry structure +// +// /world_volume/FiberCalo/rowtube_1/brass_1/hole_1/quartz_1 +// /brass_2/hole_1/scintillator_1 brass_1 == brass_2 == brass....n +// /brass_3/hole_1/quartz_1 +// /brass_4/hole_1/scintillator_1 +// /brass_5/hole_1/quartz_1 +// brass_1/quartz_1 Volume(brass) / hole +// Volume(hole) / quartz +// alt: Volume(hole) / scintillator +// +// /world_volume/FiberCalo/rowtube_1/brass/quartz +// +// Dump using: +// geoPluginRun -input examples/ClientTests/compact/FiberTubeCalorimeter.xml \ +// -volmgr -print 3 -plugin DD4hep_DetectorCheck \ +// -name FiberTubeCalorimeter -geometry -structure -sensitive -volmgr -ignore +// +//========================================================================== +#include "DD4hep/DetFactoryHelper.h" + +using namespace std; +using namespace dd4hep; +using namespace dd4hep::detail; + +static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector sens) { + constexpr double tol = 0.0; + xml_det_t x_det = e; + + // for volume tags in detector + int det_id = x_det.id(); + string det_name = x_det.nameStr(); + Material air = description.air(); + + // pointer to finding dimensins text in xml file + // look in DDCore/include/Parsers/detail/Dimension.h for arguments + xml_comp_t x_dim = x_det.dimensions(); + double hthick = x_dim.thickness(); + double hzlength = x_dim.z_length()/2.; + double hzph = x_dim.z1(); + int Ncount = x_dim.numsides(); + double agap = x_dim.gap(); + double azmin = x_dim.zmin(); + + // these refer to different fields in the xml file for this detector + xml_comp_t fX_struct( x_det.child( _Unicode(structure) ) ); + xml_comp_t fX_absorb( fX_struct.child( _Unicode(absorb) ) ); + xml_comp_t fX_core1( fX_struct.child( _Unicode(core1) ) ); + xml_comp_t fX_core2( fX_struct.child( _Unicode(core2) ) ); + xml_comp_t fX_hole( fX_struct.child( _Unicode(hole) ) ); + xml_comp_t fX_phdet1( fX_struct.child( _Unicode(phdet1) ) ); + xml_comp_t fX_phdet2( fX_struct.child( _Unicode(phdet2) ) ); + + // detector element for entire detector. + DetElement sdet (det_name, det_id); + Volume motherVol = description.pickMotherVolume(sdet); + Box env_box ((2*Ncount+1)*(hthick+agap+tol),(2*Ncount+1)*(hthick+agap+tol), (hzlength+hzph+tol)); + Volume envelopeVol (det_name, env_box, air); + envelopeVol.setAttributes(description,x_det.regionStr(),x_det.limitsStr(),x_det.visStr()); + + Material mat; + Transform3D trafo; + PlacedVolume pv; + + pv = motherVol.placeVolume(envelopeVol, Position(0.,0.,azmin+hzlength+hzph+tol)); + pv.addPhysVolID("system", det_id); + sdet.setPlacement(pv); // associate the placed volume to the detector element + sens.setType("calorimeter"); + + // scint fiber + mat = description.material(fX_core1.materialStr()); + Volume fiber_scint_vol("fiber1", Tube(0.,fX_core1.rmax(), hzlength), mat); + fiber_scint_vol.setAttributes(description,fX_core1.regionStr(),fX_core1.limitsStr(),fX_core1.visStr()); + if ( fX_core1.isSensitive() ) { + fiber_scint_vol.setSensitiveDetector(sens); + } + + // quartz fiber + Tube fiber_quartz_tub(0.,fX_core2.rmax(), hzlength); + Volume fiber_quartz_vol("fiber_quartz", fiber_quartz_tub, description.material(fX_core2.materialStr())); + fiber_quartz_vol.setAttributes(description,fX_core2.regionStr(),fX_core2.limitsStr(),fX_core2.visStr()); + cout<<"fiber_quartz vis is "<