diff --git a/Core/src/Visualization/GeometryView3D.cpp b/Core/src/Visualization/GeometryView3D.cpp index 33822f9ac7d..93f45c4e91d 100644 --- a/Core/src/Visualization/GeometryView3D.cpp +++ b/Core/src/Visualization/GeometryView3D.cpp @@ -296,7 +296,6 @@ void Acts::GeometryView3D::drawTrackingVolume( std::string vname = tVolume.volumeName(); if (writeIt) { std::vector repChar = {"::" /*, "|", " ", "{", "}"*/}; - // std::cout << "PRE: " << vname << std::endl; for (const auto& rchar : repChar) { while (vname.find(rchar) != std::string::npos) { vname.replace(vname.find(rchar), rchar.size(), std::string("_")); diff --git a/Examples/Python/src/GeoModel.cpp b/Examples/Python/src/GeoModel.cpp index dd190179b0a..b9b59b02ec7 100644 --- a/Examples/Python/src/GeoModel.cpp +++ b/Examples/Python/src/GeoModel.cpp @@ -17,7 +17,7 @@ #include "Acts/Plugins/GeoModel/GeoModelBlueprintCreater.hpp" #include "Acts/Plugins/GeoModel/GeoModelConverters.hpp" #include "Acts/Plugins/GeoModel/GeoModelDetectorElement.hpp" -#include "Acts/Plugins/GeoModel/GeoModelDetectorSurfaceFactory.hpp" +#include "Acts/Plugins/GeoModel/GeoModelDetectorObjectFactory.hpp" #include "Acts/Plugins/GeoModel/GeoModelReader.hpp" #include "Acts/Plugins/GeoModel/GeoModelTree.hpp" #include "Acts/Plugins/GeoModel/IGeoShapeConverter.hpp" @@ -98,42 +98,47 @@ void addGeoModel(Context& ctx) { .def("toPassiveSurface", &Acts::GeoShiftConverter::toPassiveSurface); } - // Surface factory + // Volume factory { - auto f = - py::class_>( - gm, "GeoModelDetectorSurfaceFactory") + auto a = + py::class_>( + gm, "GeoModelDetectorObjectFactory") .def(py::init( - [](const Acts::GeoModelDetectorSurfaceFactory::Config& cfg, + [](const Acts::GeoModelDetectorObjectFactory::Config& cfg, Acts::Logging::Level level) { - return std::make_shared( + return std::make_shared( cfg, Acts::getDefaultLogger( - "GeoModelDetectorSurfaceFactory", level)); + "GeoModelDetectorObjectFactory", level)); })) - .def("construct", &Acts::GeoModelDetectorSurfaceFactory::construct); + .def("construct", &Acts::GeoModelDetectorObjectFactory::construct); - py::class_(f, "Config") + py::class_(a, "Config") .def(py::init<>()) .def_readwrite( - "shapeConverters", - &Acts::GeoModelDetectorSurfaceFactory::Config::shapeConverters) + "convertSubVolumes", + &Acts::GeoModelDetectorObjectFactory::Config::convertSubVolumes) .def_readwrite("nameList", - &Acts::GeoModelDetectorSurfaceFactory::Config::nameList) + &Acts::GeoModelDetectorObjectFactory::Config::nameList) + .def_readwrite("convertBox", + &Acts::GeoModelDetectorObjectFactory::Config::convertBox) .def_readwrite( "materialList", - &Acts::GeoModelDetectorSurfaceFactory::Config::materialList); + &Acts::GeoModelDetectorObjectFactory::Config::materialList); - py::class_(f, "Cache") + py::class_(a, "Cache") .def(py::init<>()) .def_readwrite( "sensitiveSurfaces", - &Acts::GeoModelDetectorSurfaceFactory::Cache::sensitiveSurfaces); + &Acts::GeoModelDetectorObjectFactory::Cache::sensitiveSurfaces) + .def_readwrite( + "boundingBoxes", + &Acts::GeoModelDetectorObjectFactory::Cache::boundingBoxes); - py::class_(f, "Options") + py::class_(a, "Options") .def(py::init<>()) .def_readwrite("queries", - &Acts::GeoModelDetectorSurfaceFactory::Options::queries); + &Acts::GeoModelDetectorObjectFactory::Options::queries); } { diff --git a/Examples/Python/src/Obj.cpp b/Examples/Python/src/Obj.cpp index 378b548707c..1a7faa287fd 100644 --- a/Examples/Python/src/Obj.cpp +++ b/Examples/Python/src/Obj.cpp @@ -7,6 +7,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include +#include #include #include #include @@ -47,6 +48,47 @@ void addObj(Context& ctx) { Acts::GeometryView3D view3D; Acts::ObjVisualization3D obj; + for (const auto& surface : surfaces) { + view3D.drawSurface(obj, *surface, viewContext, + Acts::Transform3::Identity(), sConfig); + } + obj.write(fileName); + }); + mex.def("writeVolumesObj", + [](const std::vector>& + Volumes, + const GeometryContext& viewContext, + const std::array& viewRgb, unsigned int viewSegements, + const std::string& fileName) { + Acts::ViewConfig sConfig = Acts::ViewConfig{viewRgb}; + sConfig.nSegments = viewSegements; + Acts::GeometryView3D view3D; + Acts::ObjVisualization3D obj; + + for (const auto& volume : Volumes) { + view3D.drawDetectorVolume(obj, *volume, viewContext, + Acts::Transform3::Identity(), + sConfig); + } + obj.write(fileName); + }); + mex.def("writeVolumesSurfacesObj", + [](const std::vector>& surfaces, + const std::vector>& + Volumes, + const GeometryContext& viewContext, + const std::array& viewRgb, unsigned int viewSegements, + const std::string& fileName) { + Acts::ViewConfig sConfig = Acts::ViewConfig{viewRgb}; + sConfig.nSegments = viewSegements; + Acts::GeometryView3D view3D; + Acts::ObjVisualization3D obj; + + for (const auto& volume : Volumes) { + view3D.drawDetectorVolume(obj, *volume, viewContext, + Acts::Transform3::Identity(), + sConfig); + } for (const auto& surface : surfaces) { view3D.drawSurface(obj, *surface, viewContext, Acts::Transform3::Identity(), sConfig); diff --git a/Examples/Scripts/Python/geomodel.py b/Examples/Scripts/Python/geomodel.py index 82fc851b727..9cfca061b24 100644 --- a/Examples/Scripts/Python/geomodel.py +++ b/Examples/Scripts/Python/geomodel.py @@ -29,6 +29,24 @@ def main(): help="List of Queries for Published full phys volumes", ) + p.add_argument( + "-n", + "--name-list", + type=str, + nargs="+", + default=[], + help="List of Name List for the Surface Factory", + ) + + p.add_argument( + "-ml", + "--material-list", + type=str, + nargs="+", + default=[], + help="List of Material List for the Surface Factory", + ) + p.add_argument( "--table-name", type=str, @@ -56,6 +74,13 @@ def main(): "-m", "--map", type=str, default="", help="Input file for the material map" ) + p.add_argument( + "--convert-subvols", + help="Convert the children of the top level full phys vol", + action="store_true", + default=False, + ) + p.add_argument( "--output-svg", help="Write the surfaces to SVG files", @@ -84,6 +109,13 @@ def main(): default=False, ) + p.add_argument( + "--enable-blueprint", + help="Enable the usage of the blueprint", + action="store_true", + default=False, + ) + args = p.parse_args() gContext = acts.GeometryContext() @@ -98,11 +130,9 @@ def main(): gmTree = acts.geomodel.readFromDb(args.input) gmFactoryConfig = gm.GeoModelDetectorSurfaceFactory.Config() - gmFactoryConfig.shapeConverters = [ - gm.GeoBoxConverter(), - gm.GeoTrdConverter(), - gm.GeoIntersectionAnnulusConverter(), - ] + gmFactoryConfig.materialList = args.material_list + gmFactoryConfig.nameList = args.name_list + gmFactoryConfig.convertSubVolumes = args.convert_subvols gmFactory = gm.GeoModelDetectorSurfaceFactory(gmFactoryConfig, logLevel) # The options gmFactoryOptions = gm.GeoModelDetectorSurfaceFactory.Options() @@ -177,12 +207,46 @@ def main(): args.output + "_detector", ) - # Output the internal navigation to SVG - if args.output_internals_svg: - for vol in detector.volumes(): - acts.svg.viewInternalNavigation( - gContext, vol, [66, 111, 245, 245, 203, 66, 0.8], "/;:" - ) + gmDetectorBuilder = DetectorBuilder(gmDetectorConfig, args.top_node, logLevel) + detector = gmDetectorBuilder.construct(gContext) + + materialSurfaces = detector.extractMaterialSurfaces() + print("Found ", len(materialSurfaces), " material surfaces") + + # Output the detector to SVG + if args.output_svg: + surfaceStyle = acts.svg.Style() + surfaceStyle.fillColor = [5, 150, 245] + surfaceStyle.fillOpacity = 0.5 + + surfaceOptions = acts.svg.SurfaceOptions() + surfaceOptions.style = surfaceStyle + + viewRange = acts.Extent([]) + volumeOptions = acts.svg.DetectorVolumeOptions() + volumeOptions.surfaceOptions = surfaceOptions + + xyRange = acts.Extent([[acts.Binning.z, [-50, 50]]]) + zrRange = acts.Extent([[acts.Binning.phi, [-0.8, 0.8]]]) + + acts.svg.viewDetector( + gContext, + detector, + args.top_node, + [[ivol, volumeOptions] for ivol in range(detector.numberVolumes())], + [ + ["xy", ["sensitives", "portals"], xyRange], + ["zr", ["", "", "materials"], zrRange], + ], + args.output + "_detector", + ) + + # Output the internal navigation to SVG + if args.output_internals_svg: + for vol in detector.volumes(): + acts.svg.viewInternalNavigation( + gContext, vol, [66, 111, 245, 245, 203, 66, 0.8], "/;:" + ) # Output the surface to an OBJ file if args.output_obj: diff --git a/Examples/Scripts/Python/geomodel_vol.py b/Examples/Scripts/Python/geomodel_vol.py new file mode 100644 index 00000000000..95d3c171658 --- /dev/null +++ b/Examples/Scripts/Python/geomodel_vol.py @@ -0,0 +1,174 @@ +import acts +import argparse +from acts import ( + logging, + GeometryContext, + CylindricalContainerBuilder, + DetectorBuilder, + GeometryIdGenerator, +) +from acts import geomodel as gm +from acts import examples + + +def main(): + p = argparse.ArgumentParser() + + p.add_argument("-i", "--input", type=str, default="", help="Input SQL file") + + p.add_argument( + "-o", "--output", type=str, default="GeoModel", help="Output file(s) base name" + ) + + p.add_argument( + "-q", + "--queries", + type=str, + nargs="+", + default="GeoModelXML", + help="List of Queries for Published full phys volumes", + ) + + p.add_argument( + "-n", + "--name-list", + type=str, + nargs="+", + default=[], + help="List of Name List for the Surface Factory", + ) + + p.add_argument( + "-ml", + "--material-list", + type=str, + nargs="+", + default=[], + help="List of Material List for the Surface Factory", + ) + + p.add_argument( + "--table-name", + type=str, + default="ActsBlueprint", + help="Name of the blueprint table", + ) + + p.add_argument( + "-t", + "--top-node", + type=str, + default="", + help="Name of the top node in the blueprint tree", + ) + + p.add_argument( + "-b", + "--top-node-bounds", + type=str, + default="", + help="Table entry string overriding the top node bounds", + ) + + p.add_argument( + "-m", "--map", type=str, default="", help="Input file for the material map" + ) + + p.add_argument( + "--convert-subvols", + help="Convert the children of the top level full phys vol", + action="store_true", + default=False, + ) + + p.add_argument( + "--convert-boundingboxes", + help="Convert the fpvs to bounding boxes", + type=str, + nargs="+", + default=[], + ) + + p.add_argument( + "--output-svg", + help="Write the surfaces to SVG files", + action="store_true", + default=False, + ) + + p.add_argument( + "--output-internals-svg", + help="Write the internal navigation to SVG files", + action="store_true", + default=False, + ) + + p.add_argument( + "--output-obj", + help="Write the surfaces to OBJ files", + action="store_true", + default=False, + ) + + p.add_argument( + "--output-json", + help="Write the surfaces to OBJ files", + action="store_true", + default=False, + ) + + p.add_argument( + "--enable-blueprint", + help="Enable the usage of the blueprint", + action="store_true", + default=False, + ) + + args = p.parse_args() + + gContext = acts.GeometryContext() + logLevel = logging.INFO + + materialDecorator = None + if args.map != "": + print("Loading a material decorator from file:", args.map) + materialDecorator = acts.IMaterialDecorator.fromFile(args.map) + + # Read the geometry model from the database + gmTree = acts.geomodel.readFromDb(args.input) + gmFactoryConfig = gm.GeoModelDetectorObjectFactory.Config() + gmFactoryConfig.materialList = args.material_list + gmFactoryConfig.nameList = args.name_list + gmFactoryConfig.convertBox = args.convert_boundingboxes + gmFactoryConfig.convertSubVolumes = args.convert_subvols + gmFactory = gm.GeoModelDetectorObjectFactory(gmFactoryConfig, logLevel) + # The options + gmFactoryOptions = gm.GeoModelDetectorObjectFactory.Options() + gmFactoryOptions.queries = args.queries + # The Cache & construct call + gmFactoryCache = gm.GeoModelDetectorObjectFactory.Cache() + gmFactory.construct(gmFactoryCache, gContext, gmTree, gmFactoryOptions) + + # All surfaces from GeoModel + # Output the surface to an OBJ file + if args.output_obj: + segments = 720 + gmBoxes = gmFactoryCache.boundingBoxes + gmBoxSurfaces = [] + for gmBox in gmBoxes: + gmBoxSurfaces.extend(gmBox.surfaces()) + gmSurfaces = [ss[1] for ss in gmFactoryCache.sensitiveSurfaces] + unboundSurfaces = [item for item in gmSurfaces if item not in gmBoxSurfaces] + + acts.examples.writeVolumesSurfacesObj( + unboundSurfaces, + gmBoxes, + gContext, + [75, 220, 100], + segments, + args.output + "_vols.obj", + ) + + +if "__main__" == __name__: + main() diff --git a/Plugins/GeoModel/CMakeLists.txt b/Plugins/GeoModel/CMakeLists.txt index 5e40ade3230..5386e5cb4c0 100644 --- a/Plugins/GeoModel/CMakeLists.txt +++ b/Plugins/GeoModel/CMakeLists.txt @@ -5,9 +5,11 @@ add_library( SHARED src/GeoModelBlueprintCreater.cpp src/GeoModelConversionError.cpp + src/GeoModelToDetectorVolume.cpp src/GeoModelReader.cpp src/GeoModelDetectorElement.cpp - src/GeoModelDetectorSurfaceFactory.cpp + src/GeoModelDetectorObjectFactory.cpp + src/GeoModelMaterialConverter.cpp src/detail/GeoBoxConverter.cpp src/detail/GeoTrdConverter.cpp src/detail/GeoTubeConverter.cpp diff --git a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelConverters.hpp b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelConverters.hpp index b9dc0a5d90f..fe294ba4662 100644 --- a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelConverters.hpp +++ b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelConverters.hpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -68,4 +69,25 @@ using GeoUnionDoubleTrdConverter = detail::GenericGeoShapeConverter; +/// @brief The map that maps the converters with the shapes + +inline std::shared_ptr geoShapesConverters( + int geoShapeId) { + static const std::unordered_map> + converters{ + {GeoBox::getClassTypeID(), std::make_shared()}, + {GeoShapeIntersection::getClassTypeID(), + std::make_shared()}, + {GeoShapeShift::getClassTypeID(), + std::make_shared()}, + {GeoTrd::getClassTypeID(), std::make_shared()}, + {GeoTube::getClassTypeID(), std::make_shared()}, + {GeoShapeUnion::getClassTypeID(), + std::make_shared()}}; + auto itr = converters.find(geoShapeId); + + return itr != converters.end() ? itr->second : nullptr; +}; + } // namespace Acts diff --git a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelDetectorElement.hpp b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelDetectorElement.hpp index 6e702dc6a8b..62357f8e6e5 100644 --- a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelDetectorElement.hpp +++ b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelDetectorElement.hpp @@ -15,7 +15,9 @@ #include -class GeoFullPhysVol; +#include + +class GeoVPhysVol; namespace Acts { @@ -48,9 +50,8 @@ class GeoModelDetectorElement : public DetectorElementBase { /// @return a shared pointer to an instance of the detector element template static std::shared_ptr createDetectorElement( - const GeoFullPhysVol& geoPhysVol, - const std::shared_ptr bounds, const Transform3& sfTransform, - ActsScalar thickness) { + PVConstLink geoPhysVol, const std::shared_ptr bounds, + const Transform3& sfTransform, ActsScalar thickness) { // First create the detector element with a nullptr auto detElement = std::make_shared( geoPhysVol, nullptr, sfTransform, thickness); @@ -65,7 +66,7 @@ class GeoModelDetectorElement : public DetectorElementBase { /// @param surface the representing surface /// @param sfTransform the surface transform /// @param thickness the thickness of the detector element - GeoModelDetectorElement(const GeoFullPhysVol& geoPhysVol, + GeoModelDetectorElement(PVConstLink geoPhysVol, std::shared_ptr surface, const Transform3& sfTransform, ActsScalar thickness); @@ -84,7 +85,7 @@ class GeoModelDetectorElement : public DetectorElementBase { ActsScalar thickness() const override; /// @return to the Geant4 physical volume - const GeoFullPhysVol& physicalVolume() const; + PVConstLink physicalVolume() const; private: /// Attach a surface @@ -95,7 +96,7 @@ class GeoModelDetectorElement : public DetectorElementBase { } /// The GeoModel full physical volume - const GeoFullPhysVol* m_geoPhysVol{nullptr}; + PVConstLink m_geoPhysVol{nullptr}; /// The surface std::shared_ptr m_surface; /// The global transformation before the volume diff --git a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelDetectorObjectFactory.hpp b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelDetectorObjectFactory.hpp new file mode 100644 index 00000000000..72bf02cda90 --- /dev/null +++ b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelDetectorObjectFactory.hpp @@ -0,0 +1,81 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Detector/DetectorVolume.hpp" +#include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Plugins/GeoModel/GeoModelDetectorElement.hpp" +#include "Acts/Plugins/GeoModel/GeoModelToDetectorVolume.hpp" +#include "Acts/Plugins/GeoModel/GeoModelTree.hpp" +#include "Acts/Utilities/Logger.hpp" + +#include + +#include "GeoModelKernel/GeoDefinitions.h" + +class GeoShape; +struct GeoModelTree; +class Surface; +namespace Acts { +class GeoModelDetectorObjectFactory { + public: + using GeoModelBoundingBox = std::shared_ptr; + + struct Options { + std::vector queries = {}; + }; + + // substring matching for additional parameters + // empty vectors will be matched to everything + struct Config { + // List for names to match + std::vector nameList; + // List for materials to match + std::vector materialList; + + // boolean flag to build subvolumes + bool convertSubVolumes = false; + + // flag to build the desired bounding Boxes + std::vector convertBox; + }; + + struct Cache { + // The created detector elements and their surfaces + std::vector sensitiveSurfaces; + // The created representation of bounding box + std::vector boundingBoxes; + }; + + GeoModelDetectorObjectFactory( + const Config& cfg, + std::unique_ptr mlogger = getDefaultLogger( + "GeoModelDetectorObjectFactory", Acts::Logging::WARNING)); + + void construct(Cache& cache, const GeometryContext& gctx, + const GeoModelTree& geoModelTree, const Options& options); + + void convertSensitive(PVConstLink geoPV, const Acts::Transform3& transform, + std::vector& sensitives); + + std::vector findAllSubVolumes(PVConstLink geoPV); + + bool convertBox(std::string name); + bool matches(const std::string& name, PVConstLink physvol); + + void convertFpv(std::string name, GeoFullPhysVol* fpv, Cache& cache, + const GeometryContext& gctx); + + private: + std::unique_ptr m_logger; + Config m_cfg; + + const Logger& logger() const { return *m_logger; } +}; +} // namespace Acts diff --git a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelDetectorSurfaceFactory.hpp b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelDetectorSurfaceFactory.hpp deleted file mode 100644 index 13631293e9a..00000000000 --- a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelDetectorSurfaceFactory.hpp +++ /dev/null @@ -1,93 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2024 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include "Acts/Geometry/GeometryContext.hpp" -#include "Acts/Plugins/GeoModel/GeoModelDetectorElement.hpp" -#include "Acts/Plugins/GeoModel/IGeoShapeConverter.hpp" -#include "Acts/Utilities/Logger.hpp" - -#include -#include -#include -#include - -class GeoShape; -class GeoFullPhysVol; - -namespace Acts { - -struct GeoModelTree; -class Surface; - -/// A factory to convert GeoModel volume into sensitive -/// or passive surfaces which are filled into a Cache object, -/// also the create GeoModelDetectorElements which are also -/// returned. -class GeoModelDetectorSurfaceFactory { - public: - /// Collect the passive surfaces, bool whether it should be - /// added as an "always try, i.e. assignToAll=true" surface - using GeoModelPassiveSurface = std::tuple, bool>; - - // Configuration struct for the Detector surface factory - struct Config { - /// The shape converters to be use - std::vector> shapeConverters = {}; - /// List for names to match - std::vector nameList; - /// List for materials to match - std::vector materialList; - }; - - /// Nested cache that records the conversion status - struct Cache { - /// The created detector elements and their surfaces - std::vector sensitiveSurfaces; - /// The created passive representation surfaces - std::vector passiveSurfaces; - }; - - /// The options to steer the conversion - struct Options { - std::vector queries = {}; - }; - - /// The GeoModel detector element factory - /// - /// @param cfg the configuration struct - /// @param mlogger a screen output logger - GeoModelDetectorSurfaceFactory( - const Config& cfg, - std::unique_ptr mlogger = getDefaultLogger( - "GeoModelDetectorSurfaceFactory", Acts::Logging::INFO)); - - /// Construction method of the detector elements - /// - /// @param cache [in,out] into which the Elements are filled - /// @param gctx the geometry context - /// @param geoModelTree the gjeo model tree - /// @param options to steer the conversion - /// - /// @note this method will call the recursive construction - void construct(Cache& cache, const GeometryContext& gctx, - const GeoModelTree& geoModelTree, const Options& options); - - private: - /// The configuration struct - Config m_cfg; - - /// Logging instance - std::unique_ptr m_logger; - - /// Private access to the logger - const Logger& logger() const { return *m_logger; } -}; - -} // namespace Acts diff --git a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelMaterialConverter.hpp b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelMaterialConverter.hpp new file mode 100644 index 00000000000..0846adcfb6a --- /dev/null +++ b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelMaterialConverter.hpp @@ -0,0 +1,25 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +#pragma once + +#include "Acts/Material/Material.hpp" + +class GeoMaterial; + +namespace Acts { + +namespace GeoModel { +/// @brief Convert GeoMaterial to Acts::Material +/// +/// @param gm The GeoMaterial to be converted +/// @return the Acts::Material +Material geoMaterialConverter(const GeoMaterial& gm, + bool useMolarDensity = true); + +} // namespace GeoModel +} // namespace Acts diff --git a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelToDetectorVolume.hpp b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelToDetectorVolume.hpp new file mode 100644 index 00000000000..bca7a45a838 --- /dev/null +++ b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/GeoModelToDetectorVolume.hpp @@ -0,0 +1,29 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +#pragma once + +#include "Acts/Detector/DetectorVolume.hpp" +#include "Acts/Plugins/GeoModel/GeoModelDetectorElement.hpp" + +#include "GeoModelKernel/GeoDefinitions.h" +class GeoShape; + +namespace Acts { + +namespace GeoModel { +/// @brief Convert a GeoModel shape to a DetectorVolume +/// +/// @param shape the GeoModel shape +/// @param transform the transform to be applied +/// @return the DetectorVolume +std::shared_ptr convertVolume( + const GeometryContext& context, const GeoShape& shape, + const std::string& name, const GeoTrf::Transform3D transform, + const std::vector& sensitives); +} // namespace GeoModel +} // namespace Acts diff --git a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/IGeoShapeConverter.hpp b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/IGeoShapeConverter.hpp index fb9f0f94052..f6a93ae315d 100644 --- a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/IGeoShapeConverter.hpp +++ b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/IGeoShapeConverter.hpp @@ -35,7 +35,7 @@ class IGeoShapeConverter { /// /// @return The detector element and surface virtual Result toSensitiveSurface( - const GeoFullPhysVol& geoFPV) const = 0; + PVConstLink geoPV, const Transform3& transform) const = 0; /// @brief Convert a GeoShape to a detector element and passive surface /// @@ -43,7 +43,7 @@ class IGeoShapeConverter { /// /// @return The representing surface virtual Result> toPassiveSurface( - const GeoFullPhysVol& geoFPV) const = 0; + PVConstLink geoPV, const Transform3& transform) const = 0; }; } // namespace Acts diff --git a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GenericGeoShapeConverter.hpp b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GenericGeoShapeConverter.hpp index 1115ee05545..f00b309c7ea 100644 --- a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GenericGeoShapeConverter.hpp +++ b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GenericGeoShapeConverter.hpp @@ -20,15 +20,14 @@ namespace Acts::detail { template struct GenericGeoShapeConverter : public IGeoShapeConverter { Acts::Result toSensitiveSurface( - const GeoFullPhysVol& geoFPV) const override { + PVConstLink geoPV, const Transform3& transform) const override { // Retrieve logical volume and absolute transform - const GeoLogVol* logVol = geoFPV.getLogVol(); - const Transform3& transform = geoFPV.getAbsoluteTransform(nullptr); + const GeoLogVol* logVol = geoPV->getLogVol(); if (logVol != nullptr) { const GeoShape* geoShape = logVol->getShape(); auto concreteShape = dynamic_cast(geoShape); if (concreteShape != nullptr) { - return Converter{}(geoFPV, *concreteShape, transform, true); + return Converter{}(geoPV, *concreteShape, transform, true); } return Result::failure( GeoModelConversionError::WrongShapeForConverter); @@ -38,17 +37,16 @@ struct GenericGeoShapeConverter : public IGeoShapeConverter { } Acts::Result> toPassiveSurface( - const GeoFullPhysVol& geoFPV) const override { + PVConstLink geoPV, const Transform3& transform) const override { // Retrieve logical volume and absolute transform - const GeoLogVol* logVol = geoFPV.getLogVol(); - const Transform3& transform = geoFPV.getAbsoluteTransform(nullptr); + const GeoLogVol* logVol = geoPV->getLogVol(); if (logVol != nullptr) { const GeoShape* geoShape = logVol->getShape(); auto concreteShape = dynamic_cast(geoShape); if (concreteShape != nullptr) { // Conversion function call with sensitive = false - auto res = Converter{}(geoFPV, *concreteShape, transform, false); + auto res = Converter{}(geoPV, *concreteShape, transform, false); if (!res.ok()) { return res.error(); } diff --git a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoBoxConverter.hpp b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoBoxConverter.hpp index 61190f88a38..cf48911f60a 100644 --- a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoBoxConverter.hpp +++ b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoBoxConverter.hpp @@ -28,7 +28,7 @@ struct GeoBoxConverter { /// @param bool sensitive /// /// @return The detector element and surface - Result operator()(const GeoFullPhysVol& geoFPV, + Result operator()(PVConstLink geoPV, const GeoBox& geoBox, const Transform3& absTransform, bool sensitive) const; diff --git a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoIntersectionAnnulusConverter.hpp b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoIntersectionAnnulusConverter.hpp index 534f290a887..7afbc7973aa 100644 --- a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoIntersectionAnnulusConverter.hpp +++ b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoIntersectionAnnulusConverter.hpp @@ -29,7 +29,7 @@ struct GeoIntersectionAnnulusConverter { /// /// @return The detector element and surface Result operator()( - const GeoFullPhysVol& geoFPV, const GeoShapeIntersection& geoIntersection, + PVConstLink geoPV, const GeoShapeIntersection& geoIntersection, const Transform3& absTransform, bool sensitive) const; }; diff --git a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoShiftConverter.hpp b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoShiftConverter.hpp index 95a5cd2403a..3a037fbe32d 100644 --- a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoShiftConverter.hpp +++ b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoShiftConverter.hpp @@ -27,7 +27,7 @@ struct GeoShiftConverter { /// @param bool sensitive /// /// @return The detector element and surface - Result operator()(const GeoFullPhysVol& geoFPV, + Result operator()(PVConstLink geoPV, const GeoShapeShift& geoShift, const Transform3& absTransform, bool sensitive) const; diff --git a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoTrdConverter.hpp b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoTrdConverter.hpp index c5fb8ae48fc..2076f0b40d9 100644 --- a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoTrdConverter.hpp +++ b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoTrdConverter.hpp @@ -34,7 +34,7 @@ struct GeoTrdConverter { /// @param bool sensitive /// /// @return The detector element and surface - Result operator()(const GeoFullPhysVol& geoFPV, + Result operator()(PVConstLink geoPV, const GeoTrd& geoTrd, const Transform3& absTransform, bool sensitive) const; diff --git a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoTubeConverter.hpp b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoTubeConverter.hpp index fe2f0f5adf3..7ebdbd828fa 100644 --- a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoTubeConverter.hpp +++ b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoTubeConverter.hpp @@ -29,7 +29,7 @@ struct GeoTubeConverter { /// @param bool sensitive /// /// @return The detector element and surface - Result operator()(const GeoFullPhysVol& geoFPV, + Result operator()(PVConstLink geoPV, const GeoTube& geoTube, const Transform3& absTransform, bool sensitive) const; diff --git a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoUnionDoubleTrdConverter.hpp b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoUnionDoubleTrdConverter.hpp index a8b651e7409..5bd11c2d7c1 100644 --- a/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoUnionDoubleTrdConverter.hpp +++ b/Plugins/GeoModel/include/Acts/Plugins/GeoModel/detail/GeoUnionDoubleTrdConverter.hpp @@ -35,7 +35,8 @@ struct GeoUnionDoubleTrdConverter { /// @param bool sensitive /// /// @return The detector element and surface - Result operator()(const GeoFullPhysVol& geoFPV, + + Result operator()(PVConstLink geoFPV, const GeoShapeUnion& geoUnion, const Transform3& absTransform, bool sensitive) const; diff --git a/Plugins/GeoModel/src/GeoModelDetectorElement.cpp b/Plugins/GeoModel/src/GeoModelDetectorElement.cpp index fb2894cbd4a..e6ae3b9b402 100644 --- a/Plugins/GeoModel/src/GeoModelDetectorElement.cpp +++ b/Plugins/GeoModel/src/GeoModelDetectorElement.cpp @@ -13,9 +13,9 @@ #include Acts::GeoModelDetectorElement::GeoModelDetectorElement( - const GeoFullPhysVol& geoPhysVol, std::shared_ptr surface, + PVConstLink geoPhysVol, std::shared_ptr surface, const Transform3& sfTransform, ActsScalar thickness) - : m_geoPhysVol(&geoPhysVol), + : m_geoPhysVol(geoPhysVol), m_surface(std::move(surface)), m_surfaceTransform(sfTransform), m_thickness(thickness) {} @@ -37,6 +37,6 @@ Acts::ActsScalar Acts::GeoModelDetectorElement::thickness() const { return m_thickness; } -const GeoFullPhysVol& Acts::GeoModelDetectorElement::physicalVolume() const { - return *m_geoPhysVol; +PVConstLink Acts::GeoModelDetectorElement::physicalVolume() const { + return m_geoPhysVol; } diff --git a/Plugins/GeoModel/src/GeoModelDetectorObjectFactory.cpp b/Plugins/GeoModel/src/GeoModelDetectorObjectFactory.cpp new file mode 100644 index 00000000000..d779f58cc19 --- /dev/null +++ b/Plugins/GeoModel/src/GeoModelDetectorObjectFactory.cpp @@ -0,0 +1,219 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "Acts/Plugins/GeoModel/GeoModelDetectorObjectFactory.hpp" + +#include "Acts/Detector/GeometryIdGenerator.hpp" +#include "Acts/Detector/PortalGenerators.hpp" +#include "Acts/Geometry/CuboidVolumeBounds.hpp" +#include "Acts/Geometry/CutoutCylinderVolumeBounds.hpp" +#include "Acts/Geometry/CylinderVolumeBounds.hpp" +#include "Acts/Geometry/GeometryIdentifier.hpp" +#include "Acts/Geometry/TrapezoidVolumeBounds.hpp" +#include "Acts/Navigation/InternalNavigation.hpp" +#include "Acts/Plugins/GeoModel/GeoModelConverters.hpp" +#include "Acts/Plugins/GeoModel/IGeoShapeConverter.hpp" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { +std::string recType(const GeoShapeShift &gshift); +std::string recType(const GeoShapeUnion &gunion); +std::string recType(const GeoShape &gshape); + +std::string recType(const GeoShapeShift &gshift) { + return "Shift[" + recType(*gshift.getOp()) + "]"; +} +std::string recType(const GeoShapeUnion &gunion) { + return "Union[" + recType(*gunion.getOpA()) + ", " + + recType(*gunion.getOpB()) + "]"; +} +std::string recType(const GeoShape &gshape) { + if (auto ptr = dynamic_cast(&gshape); ptr != nullptr) { + return recType(*ptr); + } + if (auto ptr = dynamic_cast(&gshape); ptr != nullptr) { + return recType(*ptr); + } + return gshape.type(); +} + +} // namespace + +namespace Acts { +Acts::GeoModelDetectorObjectFactory::GeoModelDetectorObjectFactory( + const Config &cfg, std::unique_ptr mlogger) + : m_logger(std::move(mlogger)), m_cfg(cfg) {} + +void Acts::GeoModelDetectorObjectFactory::construct( + Cache &cache, const GeometryContext &gctx, const GeoModelTree &geoModelTree, + const Options &options) { + if (geoModelTree.geoReader == nullptr) { + throw std::invalid_argument("GeoModelTree has no GeoModelReader"); + } + for (const auto &q : options.queries) { + ACTS_VERBOSE("Constructing detector elements for query " << q); + // load data from database according to querie (Muon) + auto qFPV = geoModelTree.geoReader + ->getPublishedNodes(q); + + // go through each fpv + for (const auto &[name, fpv] : qFPV) { + PVConstLink physVol{fpv}; + // if the match lambda returns false skip the rest of the loop + if (!matches(name, physVol)) { + continue; + } + convertFpv(name, fpv, cache, gctx); + } + } +} + +void Acts::GeoModelDetectorObjectFactory::convertSensitive( + PVConstLink geoPV, const Acts::Transform3 &transform, + std::vector &sensitives) { + const GeoLogVol *logVol = geoPV->getLogVol(); + const GeoShape *shape = logVol->getShape(); + int shapeId = shape->typeID(); + std::string name = logVol->getName(); + std::shared_ptr converter = + Acts::geoShapesConverters(shapeId); + if (converter == nullptr) { + throw std::runtime_error("The converter for " + recType(*shape) + + " is nullptr"); + } + + auto converted = converter->toSensitiveSurface(geoPV, transform); + if (converted.ok()) { + sensitives.push_back(converted.value()); + const auto &[el, sf] = converted.value(); + auto ss = std::get<1>(converted.value()); + + ACTS_VERBOSE("(successfully converted: " + << name << " / " << recType(*shape) << " / " + << logVol->getMaterial()->getName() << ")"); + + if (!el || !sf) { + throw std::runtime_error( + "The Detector Element or the Surface is nullptr"); + } + return; + } + ACTS_ERROR(name << " / " << recType(*shape) + << ") could not be converted by any converter"); +} + +std::vector +Acts::GeoModelDetectorObjectFactory::findAllSubVolumes(PVConstLink vol) { + std::vector subvolumes = getChildrenWithRef(vol, false); + std::vector sensitives; + for (auto subvolume : subvolumes) { + if (matches(subvolume.nodeName, subvolume.volume)) { + sensitives.push_back(subvolume); + } + std::vector senssubsubvolumes = + findAllSubVolumes(subvolume.volume); + std::transform(std::make_move_iterator(senssubsubvolumes.begin()), + std::make_move_iterator(senssubsubvolumes.end()), + std::back_inserter(sensitives), + [&subvolume](GeoChildNodeWithTrf &&volume) { + volume.transform = subvolume.transform * volume.transform; + return volume; + }); + } + return sensitives; +} +bool Acts::GeoModelDetectorObjectFactory::convertBox(std::string name) { + auto convB = std::any_of( + m_cfg.convertBox.begin(), m_cfg.convertBox.end(), + [&](const auto &n) { return name.find(n) != std::string::npos; }); + // return (name.find(m_cfg.convertBox) != std::string::npos); + return convB; +} +void Acts::GeoModelDetectorObjectFactory::convertFpv( + std::string name, GeoFullPhysVol *fpv, Cache &cache, + const GeometryContext &gctx) { + PVConstLink physVol{fpv}; + + // get children + std::vector subvolumes = + getChildrenWithRef(physVol, false); + if (subvolumes.size() > 0) { + // vector containing all subvolumes to be converted to surfaces + std::vector surfaces = findAllSubVolumes(physVol); + std::vector sensitives; + + for (auto surface : surfaces) { + const Transform3 &transform = + fpv->getAbsoluteTransform() * surface.transform; + convertSensitive(surface.volume, transform, sensitives); + } + cache.sensitiveSurfaces.insert(cache.sensitiveSurfaces.end(), + sensitives.begin(), sensitives.end()); + if (convertBox(name)) { + const GeoLogVol *logVol = + physVol->getLogVol(); // get logVol for the shape of the volume + const GeoShape *shape = logVol->getShape(); // get shape + const Acts::Transform3 &fpvtransform = fpv->getAbsoluteTransform(nullptr); + + // convert bounding boxes with surfaces inside + std::shared_ptr box = + Acts::GeoModel::convertVolume(gctx, *shape, name, fpvtransform, + sensitives); + cache.boundingBoxes.push_back(box); + } + } else { + // convert fpvs to surfaces + const Transform3 &transform = fpv->getAbsoluteTransform(); + convertSensitive(fpv, transform, cache.sensitiveSurfaces); + } +} +// lambda to determine if object fits query +bool Acts::GeoModelDetectorObjectFactory::matches(const std::string &name, + PVConstLink physvol) { + if (m_cfg.nameList.empty() && m_cfg.materialList.empty()) { + return true; + } + + auto matchName = std::any_of( + m_cfg.nameList.begin(), m_cfg.nameList.end(), + [&](const auto &n) { return name.find(n) != std::string::npos; }); + + std::string matStr = physvol->getLogVol()->getMaterial()->getName(); + + auto matchMaterial = std::any_of( + m_cfg.materialList.begin(), m_cfg.materialList.end(), + [&](const auto &m) { return matStr.find(m) != std::string::npos; }); + + bool match = matchMaterial && matchName; + GeoIntrusivePtr fullVol = + dynamic_pointer_cast(physvol); + + // for the fullphysvol we only check the name + if (m_cfg.nameList.empty()) { + return matchMaterial; + } + + // if no material specified or we're looking at fpv judge by name only + if (m_cfg.materialList.empty() || !(fullVol == nullptr)) { + return matchName; + } + return match; +} +} // namespace Acts diff --git a/Plugins/GeoModel/src/GeoModelDetectorSurfaceFactory.cpp b/Plugins/GeoModel/src/GeoModelDetectorSurfaceFactory.cpp deleted file mode 100644 index 2b7553b0512..00000000000 --- a/Plugins/GeoModel/src/GeoModelDetectorSurfaceFactory.cpp +++ /dev/null @@ -1,141 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2024 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include "Acts/Plugins/GeoModel/GeoModelDetectorSurfaceFactory.hpp" - -#include "Acts/Plugins/GeoModel/GeoModelDetectorElement.hpp" -#include "Acts/Plugins/GeoModel/GeoModelTree.hpp" - -#include - -#include -#include - -namespace { -std::string recType(const GeoShape &gshape); - -std::string recType(const GeoShapeShift &gshift) { - return "Shift[" + recType(*gshift.getOp()) + "]"; -} -std::string recType(const GeoShapeUnion &gunion) { - return "Union[" + recType(*gunion.getOpA()) + ", " + - recType(*gunion.getOpB()) + "]"; -} -std::string recType(const GeoShape &gshape) { - if (auto ptr = dynamic_cast(&gshape); ptr != nullptr) { - return recType(*ptr); - } - if (auto ptr = dynamic_cast(&gshape); ptr != nullptr) { - return recType(*ptr); - } - return gshape.type(); -} - -} // namespace - -Acts::GeoModelDetectorSurfaceFactory::GeoModelDetectorSurfaceFactory( - const Config &cfg, std::unique_ptr mlogger) - : m_cfg(cfg), m_logger(std::move(mlogger)) {} - -void Acts::GeoModelDetectorSurfaceFactory::construct( - Cache &cache, const GeometryContext & /*gctx*/, - const GeoModelTree &geoModelTree, const Options &options) { - if (geoModelTree.geoReader == nullptr) { - throw std::invalid_argument("GeoModelTree has no GeoModelReader"); - } - - for (const auto &q : options.queries) { - ACTS_VERBOSE("Constructing detector elements for query " << q); - auto qFPV = geoModelTree.geoReader - ->getPublishedNodes(q); - - auto matches = [&](const std::string &name, const GeoVFullPhysVol &fpv) { - bool match = m_cfg.nameList.empty() && m_cfg.materialList.empty(); - if (match) { - return true; - } - - match |= std::any_of( - m_cfg.nameList.begin(), m_cfg.nameList.end(), - [&](const auto &n) { return name.find(n) != std::string::npos; }); - if (match) { - return true; - } - - const auto &matStr = fpv.getLogVol()->getMaterial()->getName(); - match |= std::any_of( - m_cfg.materialList.begin(), m_cfg.materialList.end(), - [&](const auto &m) { return matStr.find(m) != std::string::npos; }); - - return match; - }; - - // Store stems of volume names and materials for INFO output - std::set volNameStems; - std::set materials; - - for (auto &[name, fpv] : qFPV) { - if (fpv == nullptr) { - ACTS_WARNING("Pointer to volume '" << name << "' is null"); - continue; - } - - const std::string &vname = fpv->getLogVol()->getName(); - const GeoShape &shape = *fpv->getLogVol()->getShape(); - - if (!matches(name, *fpv)) { - continue; - } - - // Convert using the list of converters - bool success = false; - - for (const auto &converter : m_cfg.shapeConverters) { - auto converted = converter->toSensitiveSurface(*fpv); - if (converted.ok()) { - // Add the element and surface to the cache - cache.sensitiveSurfaces.push_back(converted.value()); - const auto &[el, sf] = converted.value(); - success = true; - ACTS_VERBOSE("successfully converted " - << name << " (" << vname << " / " << recType(shape) - << " / " << fpv->getLogVol()->getMaterial()->getName() - << ")"); - if (!(el && sf)) { - throw std::runtime_error("something is nullptr"); - } - break; - } - } - - if (!success) { - ACTS_DEBUG(name << " (" << vname << " / " << recType(shape) - << ") could not be converted by any converter"); - } else { - volNameStems.emplace(name.substr(0, 6)); - materials.emplace(fpv->getLogVol()->getMaterial()->getName()); - } - } - ACTS_VERBOSE("Found " << qFPV.size() - << " full physical volumes matching the query."); - - auto streamVec = [](const auto &v) { - std::stringstream ss; - for (const auto &el : v) { - ss << el << " "; - } - return ss.str(); - }; - - ACTS_INFO("Converted volumes (stems): " << streamVec(volNameStems)); - ACTS_INFO("Materials of converted volumes: " << streamVec(materials)); - } - ACTS_DEBUG("Constructed " - << cache.sensitiveSurfaces.size() << " sensitive elements and " - << cache.passiveSurfaces.size() << " passive elements"); -} diff --git a/Plugins/GeoModel/src/GeoModelMaterialConverter.cpp b/Plugins/GeoModel/src/GeoModelMaterialConverter.cpp new file mode 100644 index 00000000000..6fc66567491 --- /dev/null +++ b/Plugins/GeoModel/src/GeoModelMaterialConverter.cpp @@ -0,0 +1,39 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "Acts/Plugins/GeoModel/GeoModelMaterialConverter.hpp" + +#include "Acts/Material/Material.hpp" + +#include "GeoModelKernel/GeoMaterial.h" +#include "GeoModelKernel/Units.h" +namespace { +constexpr double s_densityCnvFactor = 1. / GeoModelKernelUnits::gram; +} +Acts::Material Acts::GeoModel::geoMaterialConverter(const GeoMaterial& gm, + bool useMolarDensity) { + double x0 = gm.getRadLength(); + double l0 = gm.getIntLength(); + double density = gm.getDensity() * s_densityCnvFactor; + double A = 0.; + double Z = 0.; + // Get number elements + int numberOfElements = gm.getNumElements(); + // Loop + for (int iEl = 0; iEl < numberOfElements; ++iEl) { + const GeoElement* geoEl = gm.getElement(iEl); + double fraction = gm.getFraction(iEl); + A += fraction * (geoEl->getA() / GeoModelKernelUnits::gram); + Z += fraction * geoEl->getZ(); + } + if (useMolarDensity) { + return Material::fromMolarDensity(x0, l0, A, Z, density); + } else { + return Material::fromMassDensity(x0, l0, A, Z, density); + } +} diff --git a/Plugins/GeoModel/src/GeoModelToDetectorVolume.cpp b/Plugins/GeoModel/src/GeoModelToDetectorVolume.cpp new file mode 100644 index 00000000000..fab7945cf31 --- /dev/null +++ b/Plugins/GeoModel/src/GeoModelToDetectorVolume.cpp @@ -0,0 +1,188 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "Acts/Plugins/GeoModel/GeoModelToDetectorVolume.hpp" + +#include "Acts/Detector/GeometryIdGenerator.hpp" +#include "Acts/Detector/PortalGenerators.hpp" +#include "Acts/Geometry/CuboidVolumeBounds.hpp" +#include "Acts/Geometry/CutoutCylinderVolumeBounds.hpp" +#include "Acts/Geometry/CylinderVolumeBounds.hpp" +#include "Acts/Geometry/GeometryIdentifier.hpp" +#include "Acts/Geometry/TrapezoidVolumeBounds.hpp" +#include "Acts/Navigation/DetectorVolumeFinders.hpp" +#include "Acts/Navigation/InternalNavigation.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Acts { +namespace GeoModel { +std::shared_ptr convertVolume( + const GeometryContext& context, const GeoShape& shape, + const std::string& name, const GeoTrf::Transform3D transform, + const std::vector& sensitives) { + // dummy volume for conversion with surfaces + std::vector> a; + + // type conversion from GeoModelSensitiveSurface to Surface + std::vector> sensSurfaces(sensitives.size()); + std::transform(sensitives.begin(), sensitives.end(), sensSurfaces.begin(), + [](const std::tuple, + std::shared_ptr>& t) { + return std::get<1>(t); + }); + auto portalGenerator = Experimental::defaultPortalAndSubPortalGenerator(); + if (shape.typeID() == GeoTube::getClassTypeID()) { + const GeoTube* tube = dynamic_cast(&shape); + std::shared_ptr bounds = + std::make_shared(tube->getRMin(), tube->getRMax(), + tube->getZHalfLength()); + return Experimental::DetectorVolumeFactory::construct( + portalGenerator, context, name, transform, bounds, + Experimental::tryAllPortalsAndSurfaces()); + } else if (shape.typeID() == GeoTubs::getClassTypeID()) { + const GeoTubs* tubs = dynamic_cast(&shape); + std::shared_ptr bounds = + std::make_shared(tubs->getRMin(), tubs->getRMax(), + tubs->getZHalfLength(), + tubs->getDPhi() / 2); + GeoTrf::Transform3D newTransform = + transform * GeoTrf::RotateZ3D(tubs->getSPhi() + 0.5 * tubs->getDPhi()); + return Experimental::DetectorVolumeFactory::construct( + portalGenerator, context, name, newTransform, bounds, + Experimental::tryAllPortalsAndSurfaces()); + } else if (shape.typeID() == GeoBox::getClassTypeID()) { + // TODO do the surfaces + const GeoBox* box = dynamic_cast(&shape); + std::shared_ptr bounds = + std::make_shared(box->getXHalfLength(), + box->getYHalfLength(), + box->getZHalfLength()); + return Experimental::DetectorVolumeFactory::construct( + portalGenerator, context, name, transform, bounds, sensSurfaces, a, + Experimental::tryNoVolumes(), Experimental::tryAllPortalsAndSurfaces()); + } else if (shape.typeID() == GeoSimplePolygonBrep::getClassTypeID()) { + const GeoSimplePolygonBrep* brep = + dynamic_cast(&shape); + double xmin{0}, xmax{0}, ymin{0}, ymax{0}, zmin{0}, zmax{0}; + brep->extent(xmin, ymin, zmin, xmax, ymax, zmax); + std::shared_ptr bounds = + std::make_shared( + (xmax - xmin) / 2, (ymax - ymin) / 2, (zmax - zmin) / 2); + return Experimental::DetectorVolumeFactory::construct( + portalGenerator, context, name, transform, bounds, + Experimental::tryAllPortalsAndSurfaces()); + } else if (shape.typeID() == GeoTrd::getClassTypeID()) { + const GeoTrd* trd = dynamic_cast(&shape); + double x1 = trd->getXHalfLength1(); + double x2 = trd->getXHalfLength2(); + double y1 = trd->getYHalfLength1(); + double y2 = trd->getYHalfLength2(); + double z = trd->getZHalfLength(); + + if (y1 == y2) { + if (x1 <= x2) { + // y axis in ACTS is z axis in geomodel + std::shared_ptr bounds = + std::make_shared(x1, x2, z, y1); + constexpr double rotationAngle = M_PI / 2; + GeoTrf::Transform3D newTransform = + transform * GeoTrf::RotateX3D(rotationAngle); + return Experimental::DetectorVolumeFactory::construct( + portalGenerator, context, name, newTransform, bounds, sensSurfaces, + a, Experimental::tryNoVolumes(), + Experimental::tryAllPortalsAndSurfaces()); + } else { + std::shared_ptr bounds = + std::make_shared(x2, x1, z, y1); + constexpr double rotationAngle = M_PI; + GeoTrf::Transform3D newTransform = transform * + GeoTrf::RotateY3D(rotationAngle) * + GeoTrf::RotateZ3D(rotationAngle); + return Experimental::DetectorVolumeFactory::construct( + portalGenerator, context, name, newTransform, bounds, sensSurfaces, + a, Experimental::tryNoVolumes(), + Experimental::tryAllPortalsAndSurfaces()); + } + } else if (x1 == x2) { + if (y1 < y2) { + std::shared_ptr bounds = + std::make_shared(y1, y2, z, x1); + auto rotationAngle = M_PI / 2; + GeoTrf::Transform3D newTransform = transform * + GeoTrf::RotateZ3D(rotationAngle) * + GeoTrf::RotateX3D(rotationAngle); + return Experimental::DetectorVolumeFactory::construct( + portalGenerator, context, name, newTransform, bounds, sensSurfaces, + a, Experimental::tryNoVolumes(), + Experimental::tryAllPortalsAndSurfaces()); + } else { + std::shared_ptr bounds = + std::make_shared(y2, y1, z, x1); + auto rotationAngle = M_PI; + GeoTrf::Transform3D newTransform = + transform * GeoTrf::RotateX3D(rotationAngle) * + GeoTrf::RotateZ3D(rotationAngle / 2) * + GeoTrf::RotateX3D(rotationAngle / 2); + return Experimental::DetectorVolumeFactory::construct( + portalGenerator, context, name, newTransform, bounds, sensSurfaces, + a, Experimental::tryNoVolumes(), + Experimental::tryAllPortalsAndSurfaces()); + } + } else { + throw std::runtime_error("FATAL: Translating GeoTrd to ACTS failed"); + } + } else if (shape.typeID() == GeoShapeUnion::getClassTypeID()) { + const GeoShapeUnion* unionShape = + dynamic_cast(&shape); + double xmin{0}, xmax{0}, ymin{0}, ymax{0}, zmin{0}, zmax{0}; + unionShape->extent(xmin, ymin, zmin, xmax, ymax, zmax); + std::shared_ptr bounds = + std::make_shared( + (xmax - xmin) / 2, (ymax - ymin) / 2, (zmax - zmin) / 2); + return Experimental::DetectorVolumeFactory::construct( + portalGenerator, context, name, transform, bounds, + Experimental::tryAllPortalsAndSurfaces()); + } else if (shape.typeID() == GeoShapeSubtraction::getClassTypeID()) { + // Go down the left side (opA) of the subtraction until we reach a normal + // shape + const GeoShapeSubtraction* subtractionShape = + dynamic_cast(&shape); + const GeoShape* shapeA = subtractionShape->getOpA(); + return convertVolume(context, *shapeA, name, transform, sensitives); + } else if (shape.typeID() == GeoPcon::getClassTypeID()) { + // Will change in future, get bounding box for now + double xmin{0}, xmax{0}, ymin{0}, ymax{0}, zmin{0}, zmax{0}; + const GeoPcon* pcon = dynamic_cast(&shape); + pcon->extent(xmin, ymin, zmin, xmax, ymax, zmax); + std::shared_ptr bounds = + std::make_shared( + (xmax - xmin) / 2, (ymax - ymin) / 2, (zmax - zmin) / 2); + return Experimental::DetectorVolumeFactory::construct( + portalGenerator, context, name, transform, bounds, + Experimental::tryAllPortalsAndSurfaces()); + } + if (shape.typeID() == GeoShapeShift::getClassTypeID()) { + const GeoShapeShift* shiftShape = + dynamic_cast(&shape); + const GeoShape* shapeOp = shiftShape->getOp(); + GeoTrf::Transform3D newTransform = transform * shiftShape->getX(); + return convertVolume(context, *shapeOp, name, newTransform, sensitives); + } + throw std::runtime_error("FATAL: Unsupported GeoModel shape"); +} +} // namespace GeoModel +} // namespace Acts diff --git a/Plugins/GeoModel/src/detail/GeoBoxConverter.cpp b/Plugins/GeoModel/src/detail/GeoBoxConverter.cpp index a1c65c3564a..7fbaf463d3c 100644 --- a/Plugins/GeoModel/src/detail/GeoBoxConverter.cpp +++ b/Plugins/GeoModel/src/detail/GeoBoxConverter.cpp @@ -22,7 +22,7 @@ #include Acts::Result -Acts::detail::GeoBoxConverter::operator()(const GeoFullPhysVol& geoFPV, +Acts::detail::GeoBoxConverter::operator()(PVConstLink geoPV, const GeoBox& geoBox, const Transform3& absTransform, bool sensitive) const { @@ -64,7 +64,7 @@ Acts::detail::GeoBoxConverter::operator()(const GeoFullPhysVol& geoFPV, // Create the element and the surface auto detectorElement = GeoModelDetectorElement::createDetectorElement( - geoFPV, rectangleBounds, transform, + geoPV, rectangleBounds, transform, 2 * unitLength * halfLengths[zIndex]); auto surface = detectorElement->surface().getSharedPtr(); // Return the detector element and surface diff --git a/Plugins/GeoModel/src/detail/GeoIntersectionAnnulusConverter.cpp b/Plugins/GeoModel/src/detail/GeoIntersectionAnnulusConverter.cpp index 5fdaf563db6..855a5570894 100644 --- a/Plugins/GeoModel/src/detail/GeoIntersectionAnnulusConverter.cpp +++ b/Plugins/GeoModel/src/detail/GeoIntersectionAnnulusConverter.cpp @@ -26,7 +26,7 @@ Acts::Result Acts::detail::GeoIntersectionAnnulusConverter::operator()( - const GeoFullPhysVol& geoFPV, const GeoShapeIntersection& geoIntersection, + PVConstLink geoPV, const GeoShapeIntersection& geoIntersection, const Transform3& absTransform, bool sensitive) const { /// auto-calculate the unit length conversion static constexpr ActsScalar unitLength = @@ -85,7 +85,7 @@ Acts::detail::GeoIntersectionAnnulusConverter::operator()( // Create the detector element auto detectorElement = GeoModelDetectorElement::createDetectorElement( - geoFPV, annulusBounds, annulusTransform, thickness); + geoPV, annulusBounds, annulusTransform, thickness); auto surface = detectorElement->surface().getSharedPtr(); return std::make_tuple(detectorElement, surface); } diff --git a/Plugins/GeoModel/src/detail/GeoShiftConverter.cpp b/Plugins/GeoModel/src/detail/GeoShiftConverter.cpp index ffba7e7c011..d7c61d4cb21 100644 --- a/Plugins/GeoModel/src/detail/GeoShiftConverter.cpp +++ b/Plugins/GeoModel/src/detail/GeoShiftConverter.cpp @@ -25,7 +25,7 @@ namespace { template -Result impl(const GeoFullPhysVol& geoFPV, +Result impl(PVConstLink geoPV, const GeoShapeShift& geoShift, const Transform3& absTransform, bool sensitive) { @@ -39,7 +39,7 @@ Result impl(const GeoFullPhysVol& geoFPV, const Transform3& shift = geoShift.getX(); const auto& conversionRes = - Converter{}(geoFPV, *trd, absTransform * shift, sensitive); + Converter{}(geoPV, *trd, absTransform * shift, sensitive); if (!conversionRes.ok()) { return conversionRes.error(); } @@ -66,17 +66,17 @@ Result impl(const GeoFullPhysVol& geoFPV, } // namespace Result GeoShiftConverter::operator()( - const GeoFullPhysVol& geoFPV, const GeoShapeShift& geoShift, + PVConstLink geoPV, const GeoShapeShift& geoShift, const Transform3& absTransform, bool sensitive) const { auto r = impl( - geoFPV, geoShift, absTransform, sensitive); + geoPV, geoShift, absTransform, sensitive); if (r.ok()) { return r; } r = impl( - geoFPV, geoShift, absTransform, sensitive); + geoPV, geoShift, absTransform, sensitive); if (r.ok()) { return r; @@ -84,7 +84,7 @@ Result GeoShiftConverter::operator()( // For now this does straw by default r = impl( - geoFPV, geoShift, absTransform, sensitive); + geoPV, geoShift, absTransform, sensitive); if (r.ok()) { return r; diff --git a/Plugins/GeoModel/src/detail/GeoTrdConverter.cpp b/Plugins/GeoModel/src/detail/GeoTrdConverter.cpp index 9ba9cb29bed..ffdbd6dbf96 100644 --- a/Plugins/GeoModel/src/detail/GeoTrdConverter.cpp +++ b/Plugins/GeoModel/src/detail/GeoTrdConverter.cpp @@ -24,7 +24,7 @@ #include Acts::Result -Acts::detail::GeoTrdConverter::operator()(const GeoFullPhysVol& geoFPV, +Acts::detail::GeoTrdConverter::operator()(PVConstLink geoPV, const GeoTrd& geoTrd, const Transform3& absTransform, bool sensitive) const { @@ -84,8 +84,7 @@ Acts::detail::GeoTrdConverter::operator()(const GeoFullPhysVol& geoFPV, auto trapezoidBounds = std::make_shared(minHalfX, maxHalfX, halfZ); - // std::cout << " TrapezoidBounds: minHalfX=" << minHalfX << ", maxHalfX=" - // << maxHalfX << ", halfz=" << halfZ << std::endl; + if (!sensitive) { auto surface = Surface::makeShared(transform, trapezoidBounds); @@ -93,9 +92,10 @@ Acts::detail::GeoTrdConverter::operator()(const GeoFullPhysVol& geoFPV, } // Create the element and the surface + auto detectorElement = GeoModelDetectorElement::createDetectorElement( - geoFPV, trapezoidBounds, transform, thickness); + geoPV, trapezoidBounds, transform, thickness); auto surface = detectorElement->surface().getSharedPtr(); return std::make_tuple(detectorElement, surface); } diff --git a/Plugins/GeoModel/src/detail/GeoTubeConverter.cpp b/Plugins/GeoModel/src/detail/GeoTubeConverter.cpp index 1ab1bb2233a..d5cf6045865 100644 --- a/Plugins/GeoModel/src/detail/GeoTubeConverter.cpp +++ b/Plugins/GeoModel/src/detail/GeoTubeConverter.cpp @@ -25,7 +25,7 @@ #include Acts::Result -Acts::detail::GeoTubeConverter::operator()(const GeoFullPhysVol& geoFPV, +Acts::detail::GeoTubeConverter::operator()(PVConstLink geoPV, const GeoTube& geoTube, const Transform3& absTransform, bool sensitive) const { @@ -53,7 +53,7 @@ Acts::detail::GeoTubeConverter::operator()(const GeoFullPhysVol& geoFPV, auto detectorElement = GeoModelDetectorElement::createDetectorElement( - geoFPV, lineBounds, transform, 2 * outerRadius); + geoPV, lineBounds, transform, 2 * outerRadius); auto surface = detectorElement->surface().getSharedPtr(); return std::make_tuple(detectorElement, surface); // Next option is translation to disc @@ -68,7 +68,7 @@ Acts::detail::GeoTubeConverter::operator()(const GeoFullPhysVol& geoFPV, // Create the element and the surface auto detectorElement = GeoModelDetectorElement::createDetectorElement( - geoFPV, radialBounds, transform, 2 * halfZ); + geoPV, radialBounds, transform, 2 * halfZ); auto surface = detectorElement->surface().getSharedPtr(); return std::make_tuple(detectorElement, surface); } @@ -80,9 +80,10 @@ Acts::detail::GeoTubeConverter::operator()(const GeoFullPhysVol& geoFPV, return std::make_tuple(nullptr, surface); } // Create the element and the surface + auto detectorElement = GeoModelDetectorElement::createDetectorElement( - geoFPV, cylinderBounds, transform, outerRadius - innerRadius); + geoPV, cylinderBounds, transform, outerRadius - innerRadius); auto surface = detectorElement->surface().getSharedPtr(); return std::make_tuple(detectorElement, surface); } diff --git a/Plugins/GeoModel/src/detail/GeoUnionDoubleTrdConverter.cpp b/Plugins/GeoModel/src/detail/GeoUnionDoubleTrdConverter.cpp index 310c1c07963..0ba56938852 100644 --- a/Plugins/GeoModel/src/detail/GeoUnionDoubleTrdConverter.cpp +++ b/Plugins/GeoModel/src/detail/GeoUnionDoubleTrdConverter.cpp @@ -47,7 +47,7 @@ bool trapezoidsAreMergeable(const std::vector &vtxsa, namespace Acts::detail { Result GeoUnionDoubleTrdConverter::operator()( - const GeoFullPhysVol &geoFPV, const GeoShapeUnion &geoUnion, + PVConstLink geoPV, const GeoShapeUnion &geoUnion, const Transform3 &absTransform, bool sensitive) const { const auto shiftA = dynamic_cast(geoUnion.getOpA()); const auto shiftB = dynamic_cast(geoUnion.getOpB()); @@ -57,12 +57,12 @@ Result GeoUnionDoubleTrdConverter::operator()( } auto shiftARes = - detail::GeoShiftConverter{}(geoFPV, *shiftA, absTransform, sensitive); + detail::GeoShiftConverter{}(geoPV, *shiftA, absTransform, sensitive); if (!shiftARes.ok()) { return shiftARes.error(); } auto shiftBRes = - detail::GeoShiftConverter{}(geoFPV, *shiftB, absTransform, sensitive); + detail::GeoShiftConverter{}(geoPV, *shiftB, absTransform, sensitive); if (!shiftBRes.ok()) { return shiftBRes.error(); } @@ -145,7 +145,7 @@ Result GeoUnionDoubleTrdConverter::operator()( // Create the element and the surface (we assume both have equal thickness) auto detectorElement = GeoModelDetectorElement::createDetectorElement( - geoFPV, trapezoidBounds, transform, elA->thickness()); + geoPV, trapezoidBounds, transform, elA->thickness()); auto surface = detectorElement->surface().getSharedPtr(); return std::make_tuple(detectorElement, surface); diff --git a/Tests/UnitTests/Plugins/GeoModel/CMakeLists.txt b/Tests/UnitTests/Plugins/GeoModel/CMakeLists.txt index b20d8effc8e..61b903d515a 100644 --- a/Tests/UnitTests/Plugins/GeoModel/CMakeLists.txt +++ b/Tests/UnitTests/Plugins/GeoModel/CMakeLists.txt @@ -3,3 +3,4 @@ set(unittest_extra_libraries ActsPluginGeoModel) add_unittest(GeoModelDetectorElement GeoModelDetectorElementTests.cpp) add_unittest(GeoBoxConverter GeoBoxConverterTests.cpp) add_unittest(GeoTrdConverter GeoTrdConverterTests.cpp) +add_unittest(GeoDetectorObjectTest GeoDetectorObjectTest.cpp) diff --git a/Tests/UnitTests/Plugins/GeoModel/GeoBoxConverterTests.cpp b/Tests/UnitTests/Plugins/GeoModel/GeoBoxConverterTests.cpp index f93437a4580..ffd485272ad 100644 --- a/Tests/UnitTests/Plugins/GeoModel/GeoBoxConverterTests.cpp +++ b/Tests/UnitTests/Plugins/GeoModel/GeoBoxConverterTests.cpp @@ -32,7 +32,7 @@ BOOST_AUTO_TEST_SUITE(GeoModelPlugin) // GeoBox conversion test case BOOST_AUTO_TEST_CASE(GeoBoxToSensitiveConversion) { - auto material = new GeoMaterial("Material", 1.0); + auto material = make_intrusive("Material", 1.0); // Let's create a GeoFullPhysVol object // (BOX object) - XY @@ -40,7 +40,10 @@ BOOST_AUTO_TEST_CASE(GeoBoxToSensitiveConversion) { auto logXY = new GeoLogVol("LogVolumeXY", boxXY, material); auto fphysXY = make_intrusive(logXY); - auto converted = Acts::GeoBoxConverter{}.toSensitiveSurface(*fphysXY); + PVConstLink physXY{make_intrusive(logXY)}; + + auto converted = Acts::GeoBoxConverter{}.toSensitiveSurface( + physXY, Acts::Transform3::Identity()); BOOST_CHECK(converted.ok()); @@ -64,7 +67,8 @@ BOOST_AUTO_TEST_CASE(GeoBoxToSensitiveConversion) { auto logYZ = new GeoLogVol("LogVolumeYZ", boxYZ, material); auto fphysYZ = make_intrusive(logYZ); - converted = Acts::GeoBoxConverter{}.toSensitiveSurface(*fphysYZ); + converted = Acts::GeoBoxConverter{}.toSensitiveSurface( + fphysYZ, Acts::Transform3::Identity()); BOOST_CHECK(converted.ok()); @@ -90,7 +94,8 @@ BOOST_AUTO_TEST_CASE(GeoBoxToSensitiveConversion) { auto logXZ = new GeoLogVol("LogVolumeXZ", boxXZ, material); auto fphysXZ = make_intrusive(logXZ); - converted = Acts::GeoBoxConverter{}.toSensitiveSurface(*fphysXZ); + converted = Acts::GeoBoxConverter{}.toSensitiveSurface( + fphysXZ, Acts::Transform3::Identity()); BOOST_CHECK(converted.ok()); diff --git a/Tests/UnitTests/Plugins/GeoModel/GeoDetectorObjectTest.cpp b/Tests/UnitTests/Plugins/GeoModel/GeoDetectorObjectTest.cpp new file mode 100644 index 00000000000..e163b85cb55 --- /dev/null +++ b/Tests/UnitTests/Plugins/GeoModel/GeoDetectorObjectTest.cpp @@ -0,0 +1,104 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2024 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include + +#include "Acts/Plugins/GeoModel/GeoModelDetectorObjectFactory.hpp" +#include "Acts/Plugins/GeoModel/GeoModelReader.hpp" +#include "Acts/Surfaces/LineBounds.hpp" +#include "Acts/Surfaces/PlaneSurface.hpp" +#include "Acts/Surfaces/RectangleBounds.hpp" +#include "Acts/Surfaces/Surface.hpp" +#include "Acts/Utilities/Logger.hpp" + +#include + +#include +#include +#include +#include +#include + +BOOST_AUTO_TEST_SUITE(GeoModelDetObj) + +BOOST_AUTO_TEST_CASE(GeoModelDetectorObjectFactory) { + // define materials + auto material = new GeoMaterial("Material", 1.0); + auto al = new GeoMaterial("Aluminium", 1.0); + + // define dimensions + double gmhlx = 100, gmhly = 200, gmhlz = 2; + double gmrmin = 5, gmrmax = 5, gmhlzt = 100; + double gmhlxs = 100, gmhlys = 200, gmhlzs = 2; + + // create shapes + auto boxXY = new GeoBox(gmhlx, gmhly, gmhlz); + auto tube = new GeoTube(gmrmin, gmrmax, gmhlzt); + auto ssurface = new GeoBox(gmhlxs, gmhlys, gmhlzs); + + // create logvols + auto logXY = new GeoLogVol("LogVolumeXY", boxXY, material); + auto logTube = new GeoLogVol("LogTube", tube, al); + auto logSurface = new GeoLogVol("LogSurface", ssurface, al); + + // create physvols + auto fphysXY = new GeoFullPhysVol(logXY); + auto physTube = new GeoFullPhysVol(logTube); + auto physSurface = new GeoFullPhysVol(logSurface); + + // build hierarchy + fphysXY->add(physTube); + fphysXY->add(physSurface); + + PVConstLink physVol{fphysXY}; + auto rBounds = std::make_shared(100, 200); + + // create pars for conversion + Acts::GeoModelDetectorObjectFactory::Config gmConfig; + gmConfig.convertBox = {"LogVolumeXY"}; + Acts::GeometryContext gContext; + Acts::GeoModelDetectorObjectFactory::Cache gmCache; + + // create factory instance + Acts::GeoModelDetectorObjectFactory factory(gmConfig); + + // convert GeoFullPhysVol + factory.convertFpv("LogVolumeXY", fphysXY, gmCache, gContext); + + // checking the dimension of the converted bounding boxes + for (auto box : gmCache.boundingBoxes) { + const Acts::VolumeBounds& bounds = box->volumeBounds(); + BOOST_CHECK(gmhlx == bounds.values()[0]); + BOOST_CHECK(gmhly == bounds.values()[1]); + BOOST_CHECK(gmhlz == bounds.values()[2]); + std::vector surfaces = box->surfaces(); + + for (auto surface : surfaces) { + const Acts::SurfaceBounds& sbounds = surface->bounds(); + // Straw check outer radius and length without trf + if (surface->type() == Acts::Surface::SurfaceType::Straw) { + BOOST_CHECK(sbounds.values()[0] == gmrmax); + BOOST_CHECK(sbounds.values()[1] == gmhlzt); + } + + // plane Surface check corner position without trf + if (surface->type() == Acts::Surface::SurfaceType::Plane) { + double csxmin = sbounds.values()[0]; + double csymin = sbounds.values()[1]; + double csxmax = sbounds.values()[2]; + double csymax = sbounds.values()[3]; + BOOST_CHECK(gmhlxs == -csxmin); + BOOST_CHECK(gmhlys == -csymin); + BOOST_CHECK(gmhlxs == csxmax); + BOOST_CHECK(gmhlys == csymax); + } + } + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/Tests/UnitTests/Plugins/GeoModel/GeoModelDetectorElementTests.cpp b/Tests/UnitTests/Plugins/GeoModel/GeoModelDetectorElementTests.cpp index 1a5ae649990..389c5641c8b 100644 --- a/Tests/UnitTests/Plugins/GeoModel/GeoModelDetectorElementTests.cpp +++ b/Tests/UnitTests/Plugins/GeoModel/GeoModelDetectorElementTests.cpp @@ -29,9 +29,11 @@ BOOST_AUTO_TEST_CASE(GeoModelDetectorElementConstruction) { auto logXY = new GeoLogVol("LogVolumeXY", boxXY, material); auto fphysXY = new GeoFullPhysVol(logXY); auto rBounds = std::make_shared(100, 200); + + PVConstLink physXY{fphysXY}; auto elementXY = Acts::GeoModelDetectorElement::createDetectorElement( - *fphysXY, rBounds, Acts::Transform3::Identity(), 2.0); + physXY, rBounds, Acts::Transform3::Identity(), 2.0); const Acts::Surface& surface = elementXY->surface(); BOOST_CHECK(surface.type() == Acts::Surface::SurfaceType::Plane); diff --git a/Tests/UnitTests/Plugins/GeoModel/GeoTrdConverterTests.cpp b/Tests/UnitTests/Plugins/GeoModel/GeoTrdConverterTests.cpp index 3fc413a2881..3a6718a629b 100644 --- a/Tests/UnitTests/Plugins/GeoModel/GeoTrdConverterTests.cpp +++ b/Tests/UnitTests/Plugins/GeoModel/GeoTrdConverterTests.cpp @@ -38,7 +38,10 @@ BOOST_AUTO_TEST_CASE(GeoTrfToSensitiveConversion) { auto logYZ = new GeoLogVol("LogVolumeYZ", trapYZ, material); auto fphysYZ = make_intrusive(logYZ); - auto converted = Acts::GeoTrdConverter{}.toSensitiveSurface(*fphysYZ); + PVConstLink physYZ{make_intrusive(logYZ)}; + + auto converted = + Acts::GeoTrdConverter{}.toSensitiveSurface(physYZ, idTransform); BOOST_CHECK(converted.ok()); @@ -74,7 +77,7 @@ BOOST_AUTO_TEST_CASE(GeoTrfToSensitiveConversion) { auto logYZs = new GeoLogVol("LogVolumeYZs", trapYZs, material); auto fphysYZs = make_intrusive(logYZs); - converted = Acts::GeoTrdConverter{}.toSensitiveSurface(*fphysYZs); + converted = Acts::GeoTrdConverter{}.toSensitiveSurface(fphysYZs, idTransform); BOOST_CHECK(converted.ok()); @@ -108,7 +111,7 @@ BOOST_AUTO_TEST_CASE(GeoTrfToSensitiveConversion) { auto logXZ = new GeoLogVol("LogVolumeXZ", trapXZ, material); auto fphysXZ = make_intrusive(logXZ); - converted = Acts::GeoTrdConverter{}.toSensitiveSurface(*fphysXZ); + converted = Acts::GeoTrdConverter{}.toSensitiveSurface(fphysXZ, idTransform); BOOST_CHECK(converted.ok()); @@ -142,7 +145,9 @@ BOOST_AUTO_TEST_CASE(GeoTrfToSensitiveConversion) { auto logXZs = new GeoLogVol("LogVolumeXZs", trapXZs, material); auto fphysXZs = make_intrusive(logXZs); - converted = Acts::GeoTrdConverter{}.toSensitiveSurface(*fphysXZs); + PVConstLink physXZs{make_intrusive(logXZs)}; + + converted = Acts::GeoTrdConverter{}.toSensitiveSurface(physXZs, idTransform); BOOST_CHECK(converted.ok()); @@ -176,8 +181,9 @@ BOOST_AUTO_TEST_CASE(GeoTrfToSensitiveConversion) { auto logDouble = new GeoLogVol("LogVolumeDouble", trapDouble, material); auto fphysDouble = make_intrusive(logDouble); - BOOST_CHECK_THROW(Acts::GeoTrdConverter{}.toSensitiveSurface(*fphysDouble), - std::invalid_argument); + BOOST_CHECK_THROW( + Acts::GeoTrdConverter{}.toSensitiveSurface(fphysDouble, idTransform), + std::invalid_argument); } BOOST_AUTO_TEST_SUITE_END()