diff --git a/Examples/Python/src/Svg.cpp b/Examples/Python/src/Svg.cpp index 36bec574e22..abb67b1b977 100644 --- a/Examples/Python/src/Svg.cpp +++ b/Examples/Python/src/Svg.cpp @@ -61,7 +61,7 @@ using ViewAndRange = /// @param portalCache is a portal cache to avoid multiple drawings of the same portal /// /// Returns an svg object in the right view -actsvg::svg::object viewDetectorVolume(const Svg::ProtoVolume& pVolume, +actsvg::svg::object drawDetectorVolume(const Svg::ProtoVolume& pVolume, const std::string& identification, const ViewAndRange& viewAndRange, PortalCache& portalCache) { @@ -154,13 +154,13 @@ actsvg::svg::object viewDetectorVolume(const Svg::ProtoVolume& pVolume, } // Helper function to be picked in different access patterns -void viewDetector( +std::vector drawDetector( const Acts::GeometryContext& gctx, const Acts::Experimental::Detector& detector, const std::string& identification, const std::vector>& volumeIdxOpts, - const std::vector& viewAndRanges, const std::string& saveAs) { + const std::vector& viewAndRanges) { PortalCache portalCache; // The svg object to be returned @@ -182,17 +182,13 @@ void viewDetector( for (auto [iv, var] : Acts::enumerate(viewAndRanges)) { auto [view, selection, range] = var; // Get the view and the range - auto svgVolView = viewDetectorVolume( + auto svgVolView = drawDetectorVolume( pVolume, identification + "_vol" + std::to_string(vidx) + "_" + view, var, portalCache); svgDetViews[iv].add_object(svgVolView); } } - - for (auto [iv, var] : Acts::enumerate(viewAndRanges)) { - auto [view, selection, range] = var; - Svg::toFile({svgDetViews[iv]}, saveAs + "_" + view + ".svg"); - } + return svgDetViews; } } // namespace @@ -206,6 +202,20 @@ void addSvg(Context& ctx) { // Some basics py::class_(svg, "object"); + py::class_(svg, "file") + .def(py::init<>()) + .def("addObject", &actsvg::svg::file::add_object) + .def("addObjects", &actsvg::svg::file::add_objects) + .def("clip", + [](actsvg::svg::file& self, std::array box) { + self.set_view_box(box); + }) + .def("write", [](actsvg::svg::file& self, const std::string& filename) { + std::ofstream file(filename); + file << self; + file.close(); + }); + // Core components, added as an acts.svg submodule { auto c = py::class_(svg, "Style").def(py::init<>()); @@ -283,6 +293,42 @@ void addSvg(Context& ctx) { }); } + // Draw primitives + { + svg.def("drawArrow", &actsvg::draw::arrow); + + svg.def("drawText", &actsvg::draw::text); + } + + // Draw Eta Lines + { + svg.def( + "drawEtaLines", + [](const std::string& id, actsvg ::scalar z, actsvg::scalar r, + const std::vector& etaMain, + actsvg::scalar strokeWidthMain, unsigned int sizeMain, + bool labelMain, const std::vector& etaSub, + actsvg::scalar strokeWidthSub, const std::vector strokeDashSub, + unsigned int sizeSub, bool labelSub) { + // The main eta lines + actsvg::style::stroke strokeMain; + strokeMain._width = strokeWidthMain; + actsvg::style::font fontMain; + fontMain._size = sizeMain; + + actsvg::style::stroke strokeSub; + strokeSub._width = strokeWidthSub; + strokeSub._dasharray = strokeDashSub; + actsvg::style::font fontSub; + fontSub._size = sizeSub; + + return actsvg::display::eta_lines( + id, z, r, + {std::tie(etaMain, strokeMain, labelMain, fontMain), + std::tie(etaSub, strokeSub, labelSub, fontSub)}); + }); + } + // How detector volumes are drawn: Svg DetectorVolume options & drawning { auto c = py::class_( @@ -304,11 +350,11 @@ void addSvg(Context& ctx) { svg.def("convertDetectorVolume", &Svg::DetectorVolumeConverter::convert); // Define the view functions - svg.def("viewDetectorVolume", &viewDetectorVolume); + svg.def("drawDetectorVolume", &drawDetectorVolume); } // How a detector is drawn: Svg Detector options & drawning - { svg.def("viewDetector", &viewDetector); } + { svg.def("drawDetector", &drawDetector); } // Legacy geometry drawing { diff --git a/Examples/Scripts/Python/detector_creation.py b/Examples/Scripts/Python/detector_creation.py index 6939ae9cb20..071520b85fc 100644 --- a/Examples/Scripts/Python/detector_creation.py +++ b/Examples/Scripts/Python/detector_creation.py @@ -49,13 +49,13 @@ # OBJ style output surfaces = [] + viewConfig = acts.ViewConfig() + viewConfig.nSegments = 100 for vol in detector.volumePtrs(): for surf in vol.surfacePtrs(): if surf.geometryId().sensitive() > 0: surfaces.append(surf) - acts.examples.writeSurfacesObj( - surfaces, geoContext, [0, 120, 120], "odd-surfaces.obj" - ) + acts.examples.writeSurfacesObj(surfaces, geoContext, viewConfig, "odd-surfaces.obj") # SVG style output surfaceStyle = acts.svg.Style() @@ -69,28 +69,28 @@ volumeOptions = acts.svg.DetectorVolumeOptions() volumeOptions.surfaceOptions = surfaceOptions - for ivol in range(detector.numberVolumes()): - acts.svg.viewDetector( - geoContext, - detector, - "odd-xy", - [[ivol, volumeOptions]], - [["xy", ["sensitives"], viewRange]], - "vol_" + str(ivol), - ) - - xyRange = acts.Extent([[acts.Binning.z, [-50, 50]]]) - zrRange = acts.Extent([[acts.Binning.phi, [-0.1, 0.1]]]) - - acts.svg.viewDetector( + # Transverse view + xyRange = acts.Extent([[acts.BinningValue.binZ, [-50, 50]]]) + xyView = acts.svg.drawDetector( geoContext, detector, "odd", [[ivol, volumeOptions] for ivol in range(detector.numberVolumes())], - [["xy", ["sensitives"], xyRange], ["zr", ["materials"], zrRange]], - "detector", + [["xy", ["sensitives"], xyRange]], ) + xyFile = acts.svg.file() + xyFile.addObjects(xyView) + xyFile.write("odd_xy.svg") - acts.examples.writeDetectorToJsonDetray(geoContext, detector, "odd-detray") - - # det_detector = acts.examples.DetrayConverter(geoContext, detector,"odd-detray") + # Longitudinal view + zrRange = acts.Extent([[acts.BinningValue.binPhi, [-0.1, 0.1]]]) + zrView = acts.svg.drawDetector( + geoContext, + detector, + "odd", + [[ivol, volumeOptions] for ivol in range(detector.numberVolumes())], + [["zr", ["sensitives", "portals"], zrRange]], + ) + zrFile = acts.svg.file() + zrFile.addObjects(zrView) + zrFile.write("odd_zr.svg") diff --git a/Examples/Scripts/Python/geomodel.py b/Examples/Scripts/Python/geomodel.py index 8bc49d59090..d92836949f5 100644 --- a/Examples/Scripts/Python/geomodel.py +++ b/Examples/Scripts/Python/geomodel.py @@ -16,10 +16,6 @@ def main(): 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", @@ -81,34 +77,6 @@ def main(): default=False, ) - 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", @@ -179,90 +147,6 @@ def main(): gmDetectorBuilder = DetectorBuilder(gmDetectorConfig, args.top_node, logLevel) detector = gmDetectorBuilder.construct(gContext) - # 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", ["sensitives", "portals", "materials"], zrRange], - ], - args.output + "_detector", - ) - - 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", ["sensitives", "portals", "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: - segments = 720 - ssurfaces = [ss[1] for ss in gmFactoryCache.sensitiveSurfaces] - acts.examples.writeSurfacesObj( - ssurfaces, - gContext, - [75, 220, 100], - segments, - args.output + "_sensitives.obj", - ) - # Output to a JSON file - if args.output_json: - acts.examples.writeDetectorToJsonDetray(gContext, detector, args.output) - return