Skip to content

Commit

Permalink
first steps twoards ODD with Acts::Detector, unit test infrastructure…
Browse files Browse the repository at this point in the history
… for DD4hep conversion
  • Loading branch information
asalzburger committed Aug 24, 2023
1 parent b69a47b commit c68ec76
Show file tree
Hide file tree
Showing 28 changed files with 1,269 additions and 32 deletions.
2 changes: 2 additions & 0 deletions Core/include/Acts/Detector/LayerStructureBuilder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ class LayerStructureBuilder : public IInternalStructureBuilder {
unsigned int splits = 1u;
/// The (optional) layer transform
std::optional<Transform3> transform = std::nullopt;
/// Alternatively - the support surface can already be provided
std::shared_ptr<Surface> surface = nullptr;
};

/// @brief Configuration struct for the LayerStructureBuilder
Expand Down
1 change: 1 addition & 0 deletions Examples/Python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pybind11_add_module(ActsPythonBindings
src/Input.cpp
src/Propagation.cpp
src/Generators.cpp
src/Obj.cpp
src/TruthTracking.cpp
src/TrackFitting.cpp
src/TrackFinding.cpp
Expand Down
54 changes: 54 additions & 0 deletions Examples/Python/src/DD4hepComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
// 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/DD4hep/DD4hepDetectorElement.hpp"
#include "Acts/Plugins/DD4hep/DD4hepDetectorSurfaceFactory.hpp"
#include "Acts/Plugins/Python/Utilities.hpp"
#include "ActsExamples/DD4hepDetector/DD4hepDetector.hpp"
#include "ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp"
Expand Down Expand Up @@ -63,4 +65,56 @@ PYBIND11_MODULE(ActsPythonBindingsDD4hep, m) {
std::shared_ptr<const Acts::IMaterialDecorator>>(
&DD4hep::DD4hepDetector::finalize));
}

{
py::class_<Acts::DD4hepDetectorElement,
std::shared_ptr<Acts::DD4hepDetectorElement>>(
m, "DD4hepDetectorElement");
}

{
/// This method allows to test conversion of DD4hep surfaces to Acts
/// surfaces as a first check for detector conversion
m.def("convertSurfaces", [](const std::vector<std::string>& xmlFileNames,
Acts::Logging::Level logLevel) {
ActsExamples::DD4hep::DD4hepGeometryService::Config cfg;
cfg.dd4hepLogLevel = logLevel;
cfg.xmlFileNames = xmlFileNames;
cfg.name = "DD4hepConvertSurfacesTestService";

ActsExamples::DD4hep::DD4hepGeometryService dd4HepService(cfg);
auto dd4HepGeometry = dd4HepService.geometry();

Acts::DD4hepDetectorSurfaceFactory::Cache cache;
Acts::DD4hepDetectorSurfaceFactory dd4HepSurfaceFactory(
Acts::getDefaultLogger("DD4hepDetectorSurfaceFactory", logLevel));
dd4HepSurfaceFactory.construct(cache, dd4HepGeometry);

// Capture the sensitive elements and the surfaces
using Elements =
std::vector<std::shared_ptr<Acts::DD4hepDetectorElement>>;
Elements detectorElements;
detectorElements.reserve(cache.sensitiveSurfaces.size());
using Surfaces = std::vector<std::shared_ptr<Acts::Surface>>;
Surfaces surfaces;
surfaces.reserve(cache.sensitiveSurfaces.size());
std::for_each(cache.sensitiveSurfaces.begin(),
cache.sensitiveSurfaces.end(), [&](const auto& sensitive) {
detectorElements.push_back(std::get<0>(sensitive));
surfaces.push_back(std::get<1>(sensitive));
});

// Capture the passive surfaces
Surfaces passiveSurfaces;
passiveSurfaces.reserve(cache.passiveSurfaces.size());
for (const auto& passive : cache.passiveSurfaces) {
passiveSurfaces.push_back(passive);
}

// Return a convenient tuple for drawing
return std::tuple<Elements, Surfaces, Surfaces>(
std::move(detectorElements), std::move(surfaces),
std::move(passiveSurfaces));
});
}
}
2 changes: 2 additions & 0 deletions Examples/Python/src/ModuleEntry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ void addHepMC3(Context& ctx);
void addExaTrkXTrackFinding(Context& ctx);
void addEDM4hep(Context& ctx);
void addSvg(Context& ctx);
void addObj(Context& ctx);
void addOnnx(Context& ctx);
void addOnnxMlpack(Context& ctx);
void addOnnxNeuralCalibrator(Context& ctx);
Expand Down Expand Up @@ -399,6 +400,7 @@ PYBIND11_MODULE(ActsPythonBindings, m) {
addHepMC3(ctx);
addExaTrkXTrackFinding(ctx);
addEDM4hep(ctx);
addObj(ctx);
addSvg(ctx);
addOnnx(ctx);
addOnnxMlpack(ctx);
Expand Down
55 changes: 55 additions & 0 deletions Examples/Python/src/Obj.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// 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/.

#include <Acts/Definitions/Algebra.hpp>
#include <Acts/Geometry/GeometryContext.hpp>
#include <Acts/Plugins/Python/Utilities.hpp>
#include <Acts/Surfaces/Surface.hpp>
#include <Acts/Visualization/GeometryView3D.hpp>
#include <Acts/Visualization/ObjVisualization3D.hpp>
#include <Acts/Visualization/ViewConfig.hpp>

#include <memory>

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

namespace py = pybind11;
using namespace pybind11::literals;

using namespace Acts;

namespace Acts::Python {
void addObj(Context& ctx) {
auto [m, mex] = ctx.get("main", "examples");

{
/// Write a collection of surfaces to an '.obj' file
///
/// @param surfaces is the collection of surfaces
/// @param viewContext is the geometry context
/// @param viewRgb is the color of the surfaces
/// @param fileName is the name of the output file
///
mex.def("writeSurfacesObj",
[](const std::vector<std::shared_ptr<Surface>>& surfaces,
const GeometryContext& viewContext,
const std::array<int, 3>& viewRgb, const std::string& fileName) {
Acts::ViewConfig sConfig = Acts::ViewConfig{viewRgb};
Acts::GeometryView3D view3D;
Acts::ObjVisualization3D obj;

for (const auto& surface : surfaces) {
view3D.drawSurface(obj, *surface, viewContext,
Acts::Transform3::Identity(), sConfig);
}
obj.write(fileName);
});
}
}
} // namespace Acts::Python
8 changes: 8 additions & 0 deletions Examples/Scripts/Python/select_surfaces_odd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env python3
import os, argparse, pathlib, acts, acts.examples
from acts.examples import dd4hep as acts_dd4hep


viewContext = acts.GeometryContext()
viewRgb = [ 120, 55, 0 ]

1 change: 1 addition & 0 deletions Plugins/DD4hep/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ add_library(
ActsPluginDD4hep SHARED
src/ConvertDD4hepDetector.cpp
src/ConvertDD4hepMaterial.cpp
src/DD4hepDetectorSurfaceFactory.cpp
src/DD4hepDetectorElement.cpp
src/DD4hepLayerBuilder.cpp
src/DD4hepVolumeBuilder.cpp)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
#include "Acts/Geometry/GeometryContext.hpp"
#include "Acts/Geometry/GeometryIdentifier.hpp"
#include "Acts/Geometry/TrackingGeometry.hpp"
#include "Acts/Plugins/DD4hep/DD4hepConversionHelpers.hpp"
#include "Acts/Utilities/BinningType.hpp"
#include "Acts/Utilities/Logger.hpp"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,19 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#pragma once

#include "Acts/Geometry/GeometryContext.hpp"
#include "Acts/Plugins/TGeo/TGeoDetectorElement.hpp"

#include <map>
#include <memory>
#include <string>
#include <vector>

#include "DD4hep/DetElement.h"
#include "DD4hep/Segmentations.h"
#include <DD4hep/DetElement.h>

namespace Acts {

/// Forward declaration of Digitization module is enough
class DigitizationModule;
class ISurfaceMaterial;

/// @class DD4hepDetectorElement
///
Expand All @@ -33,7 +31,7 @@ class ISurfaceMaterial;
/// The full geometrical information is provided by the TGeoDetectorElement.
/// The DD4hepDetectorElement extends the TGeoDetectorElement by containing a
/// segmentation for the readout.
/// @todo what if shape conversion fails? add implementation of more than one
/// @todo what if shape conversion failes? add implementation of more than one
/// surface per module, implementing also for other shapes->Cone,ConeSeg,Tube?
/// what
/// if not used with DD4hep?
Expand All @@ -44,6 +42,10 @@ class DD4hepDetectorElement : public TGeoDetectorElement {
/// Broadcast the context type
using ContextType = GeometryContext;

/// Define a string based story
using Store = std::map<std::string,
std::vector<std::shared_ptr<DD4hepDetectorElement>>>;

/// Constructor
/// @param detElement The DD4hep DetElement which should be linked to a
/// surface
Expand All @@ -53,7 +55,7 @@ class DD4hepDetectorElement : public TGeoDetectorElement {
/// capital and lower case
/// characters :
/// - capital -> positive orientation of the axis
/// - lower case -> negative orientation of the axis
/// - lower case -> negative oriantation of the axis
///
///
/// Example options are:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// This file is part of the Acts project.
//
// Copyright (C) 2022 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/Definitions/Algebra.hpp"
#include "Acts/Definitions/Common.hpp"
#include "Acts/Definitions/Units.hpp"
#include "Acts/Detector/LayerStructureBuilder.hpp"
#include "Acts/Detector/ProtoBinning.hpp"
#include "Acts/Surfaces/Surface.hpp"

#include <tuple>
#include <vector>

#include <DD4hep/DD4hepUnits.h>

class TGeoMatrix;

namespace dd4hep {
class DetElement;
}

namespace Acts {

class DD4hepDetectorElement;

/// A factory to convert DD4hep DetectorElements into sensitive
/// of passive surfaces
///
class DD4hepDetectorSurfaceFactory {
public:
/// Collect the senstive surface & detector element
using DD4hepSensitiveSurface =
std::tuple<std::shared_ptr<DD4hepDetectorElement>,
std::shared_ptr<Surface>>;

/// Collect the passive surfaces
using DD4hepPassiveSurface = std::shared_ptr<Surface>;

/// Collect passive surface proxies
struct DD4hepPassiveSurfaceProxy {
std::string placement = "";
};

/// Nested cache that records the conversion status
struct Cache {
/// The created detector elements - for the detector store
std::vector<DD4hepSensitiveSurface> sensitiveSurfaces;
/// The created non-const surfaces - for further processing,
std::vector<DD4hepPassiveSurface> passiveSurfaces;
/// The created Proxies for the support surfaces
std::vector<DD4hepPassiveSurfaceProxy> passiveSurfaceProxies;
/// matching and conversion statics: surfaces
std::size_t convertedSurfaces = 0;
/// matching and conversion statistics: materials
std::size_t convertedMaterials = 0;
/// The collected binnings
std::vector<Experimental::ProtoBinning> binnings = {};
/// The collected supports
std::vector<Experimental::LayerStructureBuilder::Support> supports = {};
};

/// The DD4hep detector element factory
///
/// @param cfg the configuration struct
/// @param logger a screen output logger
DD4hepDetectorSurfaceFactory(
std::unique_ptr<const Logger> mlogger = getDefaultLogger(
"DD4hepDetectorSurfaceFactory", Acts::Logging::INFO));

/// Construction method of the detector elements
///
/// @param cache [in,out] into which the Elements are filled
/// @param dd4hepElement the detector element representing the super structure
///
/// @note this method will call the recursive construction
void construct(Cache& cache, const dd4hep::DetElement& dd4hepElement);

private:
/// @brief auto-calculate the unit length conversion
static constexpr ActsScalar unitLength =
Acts::UnitConstants::mm / dd4hep::millimeter;

/// Logging instance
std::unique_ptr<const Logger> m_logger;

// The allows passive proxy positions
std::vector<std::string> allowedPassiveProxies = {
"inner", "outer", "negative", "positive", "representing"};

/// Private access to the logger
const Logger& logger() const { return *m_logger; }

/// Construction method of the detector elements - recursive walk down
///
/// @param cache [in,out] into which the Elements are filled
/// @param dd4hepElement the detector element representing the super structure
/// @param level the current level of the tree, used for log message output
///
/// @note this method is called recursively
void recursiveConstruct(Cache& cache, const dd4hep::DetElement& dd4hepElement,
int level);

/// Method to conver a single senstive detector element
///
/// @param dd4hepElement the detector element
///
/// @return a created detector element and surface
DD4hepSensitiveSurface constructSensitiveElement(
const dd4hep::DetElement& dd4hepElement) const;

/// Method to conver a single senstive detector element
///
/// @param options the factory creation option
/// @param dd4hepElement the detector element
///
/// @return a created surface
DD4hepPassiveSurface constructPassiveElement(
const dd4hep::DetElement& dd4hepElement) const;
};

} // namespace Acts
Loading

0 comments on commit c68ec76

Please sign in to comment.