From 5acf706b78fc747a73a7907d027f831852d98682 Mon Sep 17 00:00:00 2001 From: Markus Frank <Markus.Frank@cern.ch> Date: Wed, 5 Dec 2018 16:57:49 +0100 Subject: [PATCH] Fix issue #465 and add example on how to do a volume scan. --- DDCore/src/Shapes.cpp | 47 +++++-- DDG4/src/Geant4Converter.cpp | 9 ++ examples/ClientTests/CMakeLists.txt | 10 ++ .../compact/Check_Shape_PseudoTrap.xml | 2 +- .../compact/Check_Shape_PseudoTrapCMS.xml | 38 ++++++ .../compact/Check_Shape_TubeDivision.xml | 32 +++++ .../src/PlacedVolumeScannerTest.cpp | 122 ++++++++++++++++++ .../src/TestConstantMultiplier.cpp | 2 +- 8 files changed, 252 insertions(+), 10 deletions(-) create mode 100644 examples/ClientTests/compact/Check_Shape_PseudoTrapCMS.xml create mode 100644 examples/ClientTests/compact/Check_Shape_TubeDivision.xml create mode 100644 examples/ClientTests/src/PlacedVolumeScannerTest.cpp diff --git a/DDCore/src/Shapes.cpp b/DDCore/src/Shapes.cpp index 2ee5c7431..f3ae09840 100644 --- a/DDCore/src/Shapes.cpp +++ b/DDCore/src/Shapes.cpp @@ -646,40 +646,71 @@ void PseudoTrap::make(double x1, double x2, double y1, double y2, double z, doub double startPhi = 0; double halfZ = z; double halfOpeningAngle = std::asin( x / std::abs( r ))/units::deg; - + /// calculate the displacement of the tubs w.r.t. to the trap, determine the opening angle of the tubs double delta = std::sqrt( r * r - x * x ); +#if 0 if( r < 0 && std::abs(r) >= x ) { - intersec = true; // intersection solid + intersec = true; // intersection solid h = y1 < y2 ? y2 : y1; // tubs half height - h += h/20.; // enlarge a bit - for subtraction solid + h += h/20.; // enlarge a bit - for subtraction solid + if( atMinusZ ) { + displacement = -halfZ - delta; + startPhi = 270.0 - halfOpeningAngle; + } + else { + displacement = halfZ + delta; + startPhi = 90.0 - halfOpeningAngle; + } + } + else if( r > 0 && std::abs(r) >= x ) { + if( atMinusZ ) { + displacement = -halfZ + delta; + startPhi = 90.0 - halfOpeningAngle; + h = y1; + } + else + { + displacement = halfZ - delta; + startPhi = 270.0 - halfOpeningAngle; + h = y2; + } + } + else { + except("PseudoTrap","Check parameters of the PseudoTrap!"); + } +#endif + if( r < 0 && std::abs(r) >= x ) { + intersec = true; // intersection solid + h = y1 < y2 ? y2 : y1; // tubs half height + h += h/20.; // enlarge a bit - for subtraction solid if( atMinusZ ) { displacement = - halfZ - delta; - startPhi = 270.0 - halfOpeningAngle; + startPhi = 90.0 - halfOpeningAngle; } else { displacement = halfZ + delta; - startPhi = 90.0 - halfOpeningAngle; + startPhi = -90.0 - halfOpeningAngle; } } else if( r > 0 && std::abs(r) >= x ) { if( atMinusZ ) { displacement = - halfZ + delta; - startPhi = 90.0 - halfOpeningAngle; + startPhi = 270.0 - halfOpeningAngle; h = y1; } else { displacement = halfZ - delta; - startPhi = 270.0 - halfOpeningAngle; + startPhi = 90.0 - halfOpeningAngle; h = y2; } } else { except("PseudoTrap","Check parameters of the PseudoTrap!"); } - + Solid trap(new TGeoTrd2(x1, x2, y1, y2, halfZ)); Solid tubs(new TGeoTubeSeg(0.,std::abs(r),h,startPhi,startPhi + halfOpeningAngle*2.)); TGeoCompositeShape* solid = 0; diff --git a/DDG4/src/Geant4Converter.cpp b/DDG4/src/Geant4Converter.cpp index 0d0172ac7..b5ff59e34 100644 --- a/DDG4/src/Geant4Converter.cpp +++ b/DDG4/src/Geant4Converter.cpp @@ -70,6 +70,7 @@ #include "G4UnionSolid.hh" #include "G4Paraboloid.hh" #include "G4Ellipsoid.hh" +#include "G4GenericTrap.hh" #include "G4ExtrudedSolid.hh" #include "G4EllipticalTube.hh" #include "G4SubtractionSolid.hh" @@ -527,6 +528,14 @@ void* Geant4Converter::handleSolid(const string& name, const TGeoShape* shape) c sh->GetH1() * CM_2_MM, sh->GetBl1() * CM_2_MM, sh->GetTl1() * CM_2_MM, sh->GetAlpha1() * DEGREE_2_RAD, sh->GetH2() * CM_2_MM, sh->GetBl2() * CM_2_MM, sh->GetTl2() * CM_2_MM, sh->GetAlpha2() * DEGREE_2_RAD); } + else if (shape->IsA() == TGeoArb8::Class()) { + vector<G4TwoVector> vertices; + TGeoTrap* sh = (TGeoTrap*) shape; + Double_t* vtx_xy = sh->GetVertices(); + for ( size_t i=0; i<8; ++i, vtx_xy +=2 ) + vertices.push_back(G4TwoVector(vtx_xy[0] * CM_2_MM,vtx_xy[1] * CM_2_MM)); + solid = new G4GenericTrap(name, sh->GetDz() * CM_2_MM, vertices); + } else if (shape->IsA() == TGeoCompositeShape::Class()) { const TGeoCompositeShape* sh = (const TGeoCompositeShape*) shape; const TGeoBoolNode* boolean = sh->GetBoolNode(); diff --git a/examples/ClientTests/CMakeLists.txt b/examples/ClientTests/CMakeLists.txt index fde1de970..aa66ae54e 100644 --- a/examples/ClientTests/CMakeLists.txt +++ b/examples/ClientTests/CMakeLists.txt @@ -36,6 +36,16 @@ dd4hep_install_dir( compact scripts ref DESTINATION ${ClientTestsEx_INSTALL} ) dd4hep_configure_scripts( ClientTests DEFAULT_SETUP WITH_TESTS) #--- Testing ------------------------------------------------------------ # +# Test Volume scanner for CMS +dd4hep_add_test_reg( ClientTests_volume_scanner + COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh" + EXEC_ARGS geoPluginRun -input ${ClientTestsEx_INSTALL}/compact/MiniTel.xml + -destroy -plugin DD4hep_PlacedVolumeScannerTest -detector /world + REGEX_PASS "Visited a total of 11 placed volumes" + REGEX_FAIL "Exception" + REGEX_FAIL "FAILED" + ) +# # Test namespaces for constants dd4hep_add_test_reg( ClientTests_namespace_constants COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh" diff --git a/examples/ClientTests/compact/Check_Shape_PseudoTrap.xml b/examples/ClientTests/compact/Check_Shape_PseudoTrap.xml index 79ff75fff..d9038c978 100644 --- a/examples/ClientTests/compact/Check_Shape_PseudoTrap.xml +++ b/examples/ClientTests/compact/Check_Shape_PseudoTrap.xml @@ -29,7 +29,7 @@ </check> --> - <test type="DD4hep_Mesh_Verifier" ref="${DD4hepExamplesINSTALL}/examples/ClientTests/ref/Ref_PseudoTrap.txt" create="CheckShape_create"/> + <test11 type="DD4hep_Mesh_Verifier" ref="${DD4hepExamplesINSTALL}/examples/ClientTests/ref/Ref_PseudoTrap.txt" create="CheckShape_create"/> </detector> </detectors> </lccdd> diff --git a/examples/ClientTests/compact/Check_Shape_PseudoTrapCMS.xml b/examples/ClientTests/compact/Check_Shape_PseudoTrapCMS.xml new file mode 100644 index 000000000..3343f639e --- /dev/null +++ b/examples/ClientTests/compact/Check_Shape_PseudoTrapCMS.xml @@ -0,0 +1,38 @@ +<lccdd> + <includes> + <gdmlFile ref="CheckShape.xml"/> + </includes> + + <detectors> + <detector id="1" name="Shape_PseudoTrap" type="DD4hep_TestShape_Creator"> + <!-- Union pseudo-trap: --> + <check vis="Shape1_vis"> + <shape type="PseudoTrap" name="YE1_b" + x1="0.5*m" x2="1.86356*m" + y1="0.3000*m" y2="0.3000*m" + z="0.92934*m" radius="-0.91350*m" minusZ="true"/> + <position x="0*cm" y="0*cm" z="0*cm"/> + <rotation x="0" y="0" z="0"/> + </check> + <check vis="Shape2_vis"> + <shape type="PseudoTrap" name="YE1_c" + x1="0.293734*m" x2="0.86356*m" + y1="0.3000*m" y2="0.9000*m" + z="0.92934*m" radius="-1.1350*m" minusZ="false"/> + <position x="400*cm" y="180*cm" z="0*cm"/> + <rotation x="pi/2" y="0" z="0"/> + </check> + <check vis="Shape3_vis"> + <shape type="PseudoTrap" name="YE1_d" + x1="0.293734*m" x2="0.86356*m" + y1="0.3000*m" y2="0.9000*m" + z="0.92934*m" radius="1.1350*m" minusZ="false"/> + <position x="-300*cm" y="-180*cm" z="0*cm"/> + <rotation x="0" y="pi/2" z="pi"/> + </check> + <comment> + <test type="DD4hep_Mesh_Verifier" ref="${DD4hepExamplesINSTALL}/examples/ClientTests/ref/Ref_PseudoTrap.txt" create="CheckShape_create"/> + </comment> + </detector> + </detectors> +</lccdd> diff --git a/examples/ClientTests/compact/Check_Shape_TubeDivision.xml b/examples/ClientTests/compact/Check_Shape_TubeDivision.xml new file mode 100644 index 000000000..551f0cc6a --- /dev/null +++ b/examples/ClientTests/compact/Check_Shape_TubeDivision.xml @@ -0,0 +1,32 @@ +<lccdd> + <includes> + <gdmlFile ref="CheckShape.xml"/> + </includes> + + <detectors> + <detector id="1" name="Shape_TubeDivision" type="DD4hep_TestShape_Creator"> + <check vis="Shape1_vis_20"> + <shape type="Tube" rmin="4.69*m" rmax="4.95*m" dz="31.9*cm" startphi="346.25*deg" deltaphi="360*deg"> + <position x="0" y="0" z="50"/> + <rotation x="0" y="0" z="0"/> + </shape> + </check> + <check vis="Shape2_vis"> + <shape type="Tube" rmin="4.694*m" rmax="4.955*m" dz="32*cm" startphi="346.25*deg" deltaphi="3.099999*deg"> + <position x="0" y="30" z="50"/> + <rotation x="0" y="0" z="0"/> + </shape> + </check> + <check vis="Shape3_vis"> + <shape type="Tube" rmin="4.694*m" rmax="4.955*m" dz="32*cm" startphi="10.75*deg" deltaphi="3.099999*deg"> + <position x="0" y="0" z="0"/> + <rotation x="0" y="0" z="0"/> + </shape> + </check> + +<!-- + <test type="DD4hep_Mesh_Verifier" ref="${DD4hepExamplesINSTALL}/examples/ClientTests/ref/Ref_TubeDivision.txt" create="CheckShape_create"/> +--> + </detector> + </detectors> +</lccdd> diff --git a/examples/ClientTests/src/PlacedVolumeScannerTest.cpp b/examples/ClientTests/src/PlacedVolumeScannerTest.cpp new file mode 100644 index 000000000..7800e7b1c --- /dev/null +++ b/examples/ClientTests/src/PlacedVolumeScannerTest.cpp @@ -0,0 +1,122 @@ +//========================================================================== +// 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 +// +//========================================================================== +/* + Plugin invocation: + ================== + This plugin behaves like a main program. + Invoke the plugin with something like this: + + geoPluginRun -destroy -plugin DD4hep_VolumeScannerTest -opt [-opt] + +*/ +// Framework include files +#include "DD4hep/Volumes.h" +#include "DD4hep/Detector.h" +#include "DD4hep/Printout.h" +#include "DD4hep/Factories.h" +#include "DD4hep/DetectorTools.h" +#include "DD4hep/VolumeProcessor.h" +#include "TClass.h" +#include <iomanip> + +namespace { + class MyVolumeProcessor : public dd4hep::PlacedVolumeProcessor { + public: + int count = 0; + std::vector<std::string> volume_stack; + public: + /// Default constructor + MyVolumeProcessor() = default; + /// Default destructir + virtual ~MyVolumeProcessor() = default; + /// Callback to output PlacedVolume information of an entire Placement + virtual int process(dd4hep::PlacedVolume pv, int level, bool recursive) { + volume_stack.push_back(pv.name()); + int ret = this->dd4hep::PlacedVolumeProcessor::process(pv, level, recursive); + volume_stack.pop_back(); + return ret; + } + /// Volume callback + virtual int operator()(dd4hep::PlacedVolume pv, int level) { + dd4hep::Volume vol = pv.volume(); + std::cout << "Hierarchical level:" << level << " Placement:"; + for(const auto& i : volume_stack ) std::cout << "/" << i; + std::cout << std::endl + << "\tMaterial:" << vol.material().name() + << "\tSolid: " << vol.solid().name() + << " [" << vol.solid()->IsA()->GetName() << "]" << std::endl; + ++count; + return 1; + } + }; +} + +using namespace std; +using namespace dd4hep; + +/// Plugin function: Test example of the volume scanner using a customized callback functor +/** + * + * \author M.Frank + * \version 1.0 + * \date 20/01/2018 + */ +static int scan_volumes (Detector& detector, int argc, char** argv) { + bool help = false; + string det_element_path, placed_vol_path; + for(int i=0; i<argc && argv[i]; ++i) { + if ( 0 == ::strncmp("-help",argv[i],4) ) + help = true; + else if ( 0 == ::strncmp("-path",argv[i],4) ) + placed_vol_path = argv[++i]; + else if ( 0 == ::strncmp("-detector",argv[i],4) ) + det_element_path = argv[++i]; + else + help = true; + } + if ( help ) { + /// Help printout describing the basic command line interface + cout << + "Usage: -plugin <name> -arg [-arg] \n" + " name: factory name DD4hep_PlacedVolumeScannerTest \n" + " -detector <name> Path to the detector element where to start the scan.\n" + " -path <name> Alternatively specify the physical volume path. \n" + " -help Ahow this help. \n" + "\tArguments given: " << arguments(argc,argv) << endl << flush; + ::exit(EINVAL); + } + + // Detectine the proper placed volume for the start (default=/world_volume) + PlacedVolume start_pv; + DetElement start_de, de = detector.world(); + if ( !det_element_path.empty() ) + start_de = detail::tools::findElement(detector, det_element_path); + else if ( !placed_vol_path.empty() ) + start_pv = detail::tools::findNode(de.placement(),placed_vol_path); + + if ( !start_pv.isValid() ) { + if ( !start_de.isValid() ) { + except("VolumeScanner","Failed to find start conditions for the volume scan"); + } + start_pv = start_de.placement(); + } + + // Let's scan + MyVolumeProcessor proc; + PlacedVolumeScanner().scanPlacements(proc, start_pv, 0, true); + + printout(ALWAYS,"VolumeScanner","+++ Visited a total of %d placed volumes.",proc.count); + return 1; +} + +DECLARE_APPLY(DD4hep_PlacedVolumeScannerTest,scan_volumes) diff --git a/examples/ClientTests/src/TestConstantMultiplier.cpp b/examples/ClientTests/src/TestConstantMultiplier.cpp index f2af38dc2..44e588e01 100644 --- a/examples/ClientTests/src/TestConstantMultiplier.cpp +++ b/examples/ClientTests/src/TestConstantMultiplier.cpp @@ -16,7 +16,7 @@ This plugin behaves like a main program. Invoke the plugin with something like this: - geoPluginRun -destroy -plugin DD4hep_XML-In-Memory -input <file name> + geoPluginRun -destroy -plugin DD4hep_TestConstantsMultiplier -opt [-opt] */ // Framework include files -- GitLab