forked from acts-project/acts
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Geant4 Gdml surface provider + Unit Test (acts-project#2906)
Adding a Surface Provider that is able to read Gdml files and extract surfaces based on Geant4PhysicalVolumeSelector criteria. Optional range-based selection of a subset of surfaces from the preselected, based on these criteria, set is available. KDTree is used to implement the range-based subset selection. Unit test showing examples of interfacing between the volume selectors and internal structure builders with the surface provider is implemented. New selector that accepts G4 volumes based on their position is shipped to show the more memory-efficient preselection->KDTree selection pipeline. Converter to BinningValue to Geant4 axis is added and can be used to implement more sophisticated Volume Selectors. Minor changes made to KdtSurfacesProvider and Range1D. In the former one of the internal variables is renamed to resolve shadowed declaration conflict with one of the necessary Geant4 includes. In the latter constructor is changed to be consistent with its description and provide a way to deduce uninitialized ranges based on the "degenerate" method.
- Loading branch information
Showing
6 changed files
with
519 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
162 changes: 162 additions & 0 deletions
162
Plugins/Geant4/include/Acts/Plugins/Geant4/Geant4SurfaceProvider.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
// This file is part of the Acts project. | ||
// | ||
// Copyright (C) 2023 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/KdtSurfacesProvider.hpp" | ||
#include "Acts/Detector/interface/ISurfacesProvider.hpp" | ||
#include "Acts/Plugins/Geant4/Geant4DetectorSurfaceFactory.hpp" | ||
|
||
#include "G4GDMLParser.hh" | ||
#include "G4LogicalVolume.hh" | ||
#include "G4VPhysicalVolume.hh" | ||
|
||
namespace Acts { | ||
namespace Experimental { | ||
|
||
/// @brief A surface provider that extracts surfaces from a gdml file | ||
/// | ||
/// This provider extracts volumes from a gdml file based on | ||
/// the preselection criteria and converts them to surfaces. | ||
/// By default, all the volumes are converted. | ||
/// | ||
/// Optionally, it can be configured to return a range-based | ||
/// subset of all the preselected surfaces. This is done | ||
/// by setting the range and binning values in the kdtOptions | ||
/// | ||
/// @note if the KDTree selection is not needed, the | ||
/// template parameters can be left to their default values | ||
/// as they will not affect the result. | ||
/// | ||
/// @tparam kDim The number of dimensions for the KDTree | ||
/// @tparam bSize The maximum number of surfaces per KDTree leaf | ||
/// @tparam reference_generator The reference generator for the KDTree | ||
template <std::size_t kDim = 2u, std::size_t bSize = 100u, | ||
typename reference_generator = | ||
detail::PolyhedronReferenceGenerator<1u, false>> | ||
class Geant4SurfaceProvider : public Acts::Experimental::ISurfacesProvider { | ||
public: | ||
/// Nested configuration struct | ||
struct Config { | ||
/// The path of the gdml file | ||
std::string gdmlPath = ""; | ||
|
||
/// Convert the length scale | ||
ActsScalar scaleConversion = 1.; | ||
|
||
/// Convert the material | ||
bool convertMaterial = true; | ||
|
||
/// Converted material thickness (< 0 indicates keeping original thickness) | ||
ActsScalar convertedMaterialThickness = -1; | ||
|
||
/// A selector for passive surfaces | ||
std::shared_ptr<IGeant4PhysicalVolumeSelector> surfacePreselector = | ||
std::make_shared<Acts::Geant4PhysicalVolumeSelectors::AllSelector>(); | ||
}; | ||
|
||
/// Optional configuration for the KDTree | ||
struct kdtOptions { | ||
/// A set of ranges to separate the surfaces | ||
Acts::RangeXD<kDim, Acts::ActsScalar> range; | ||
|
||
/// A set of binning values to perform the separation | ||
std::array<Acts::BinningValue, kDim> binningValues; | ||
|
||
/// The maximum number of surfaces per leaf | ||
std::size_t leafSize = bSize; | ||
|
||
/// The reference generator for the KDTree | ||
reference_generator rgen; | ||
|
||
/// Initialize range to be degenerate by default | ||
kdtOptions() { | ||
for (std::size_t i = 0; i < kDim; ++i) { | ||
range[i].set(1, -1); | ||
} | ||
} | ||
}; | ||
|
||
/// Constructor | ||
///@param config The configuration struct | ||
///@param options The optional configuration for KDTree | ||
Geant4SurfaceProvider(const Config& config, | ||
const kdtOptions& options = kdtOptions()) { | ||
if (config.gdmlPath.empty()) { | ||
throw std::invalid_argument( | ||
"Geant4SurfaceProvider: no gdml file provided"); | ||
} | ||
if (config.surfacePreselector == nullptr) { | ||
throw std::invalid_argument( | ||
"Geant4SurfaceProvider: no preselection criteria provided"); | ||
} | ||
|
||
m_cfg = config; | ||
m_kdtOptions = options; | ||
|
||
/// Read the gdml file and get the world volume | ||
G4GDMLParser parser; | ||
parser.Read(m_cfg.gdmlPath); | ||
m_g4World = parser.GetWorldVolume(); | ||
|
||
if (m_g4World == nullptr) { | ||
throw std::invalid_argument( | ||
"Geant4SurfaceProvider: No g4World initialized"); | ||
} | ||
}; | ||
|
||
/// Destructor | ||
~Geant4SurfaceProvider() override = default; | ||
|
||
std::vector<std::shared_ptr<Acts::Surface>> surfaces( | ||
[[maybe_unused]] const Acts::GeometryContext& gctx) const override { | ||
/// Surface factory options | ||
Acts::Geant4DetectorSurfaceFactory::Options g4SurfaceOptions; | ||
|
||
/// Copy the configuration | ||
/// This is done to avoid checking nullptrs | ||
/// in the factory | ||
g4SurfaceOptions.scaleConversion = m_cfg.scaleConversion; | ||
g4SurfaceOptions.convertMaterial = m_cfg.convertMaterial; | ||
g4SurfaceOptions.convertedMaterialThickness = | ||
m_cfg.convertedMaterialThickness; | ||
g4SurfaceOptions.passiveSurfaceSelector = m_cfg.surfacePreselector; | ||
|
||
/// Generate the surface cache | ||
Acts::Geant4DetectorSurfaceFactory::Cache g4SurfaceCache; | ||
G4Transform3D g4ToWorld; | ||
|
||
/// Find and store surfaces in the cache object | ||
Acts::Geant4DetectorSurfaceFactory{}.construct( | ||
g4SurfaceCache, g4ToWorld, *m_g4World, g4SurfaceOptions); | ||
|
||
auto surfaces = g4SurfaceCache.passiveSurfaces; | ||
|
||
/// If range is degenerate, return all surfaces | ||
if (m_kdtOptions.range.degenerate()) { | ||
return surfaces; | ||
} | ||
|
||
/// Otherwise, select the surfaces based on the range | ||
auto kdtSurfaces = | ||
Acts::Experimental::KdtSurfaces<kDim, bSize, reference_generator>( | ||
gctx, surfaces, m_kdtOptions.binningValues); | ||
|
||
return kdtSurfaces.surfaces(m_kdtOptions.range); | ||
}; | ||
|
||
private: | ||
Config m_cfg; | ||
|
||
kdtOptions m_kdtOptions; | ||
|
||
G4VPhysicalVolume* m_g4World = nullptr; | ||
}; | ||
|
||
} // namespace Experimental | ||
} // namespace Acts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.