Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:10:14

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2022 CERN for the benefit of the Acts project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
0008 
0009 #include "Acts/Plugins/ActSVG/SurfaceArraySvgConverter.hpp"
0010 
0011 #include "Acts/Plugins/ActSVG/SurfaceSvgConverter.hpp"
0012 #include "Acts/Surfaces/Surface.hpp"
0013 #include "Acts/Surfaces/SurfaceArray.hpp"
0014 #include "Acts/Surfaces/SurfaceBounds.hpp"
0015 
0016 std::tuple<std::vector<Acts::Svg::ProtoSurfaces>, Acts::Svg::ProtoGrid,
0017            std::vector<Acts::Svg::ProtoAssociations> >
0018 Acts::Svg::SurfaceArrayConverter::convert(
0019     const GeometryContext& gctx, const SurfaceArray& surfaceArray,
0020     const SurfaceArrayConverter::Options& cOptions) {
0021   // Prepare the return objects
0022   ProtoSurfaces pSurfaces;
0023   ProtoGrid pGrid;
0024   ProtoAssociations pAssociations;
0025 
0026   const auto& surfaces = surfaceArray.surfaces();
0027 
0028   // The edges of the grid
0029   auto binning = surfaceArray.binningValues();
0030   auto axes = surfaceArray.getAxes();
0031 
0032   enum ViewType { cylinder, polar, planar, none };
0033   ViewType vType = none;
0034 
0035   if (!binning.empty() && binning.size() == 2 && axes.size() == 2) {
0036     // The endges values
0037     std::vector<Acts::ActsScalar> edges0;
0038     std::vector<Acts::ActsScalar> edges1;
0039     // Helper method to convert from ACTS to Grid edges
0040     auto convertGridEdges = [](const std::vector<Acts::ActsScalar>& actsEdges)
0041         -> std::vector<actsvg::scalar> {
0042       std::vector<actsvg::scalar> svgEdges;
0043       svgEdges.reserve(actsEdges.size());
0044       for (const auto ae : actsEdges) {
0045         svgEdges.push_back(static_cast<actsvg::scalar>(ae));
0046       }
0047       return svgEdges;
0048     };
0049 
0050     // Walk through the binning and translate
0051     if (binning[0] == binPhi && binning[1] == binZ) {
0052       vType = cylinder;
0053       //  flip to fit with actsvg convention
0054       edges1 = axes[0]->getBinEdges();
0055       edges0 = axes[1]->getBinEdges();
0056       pGrid._type = actsvg::proto::grid::e_z_phi;
0057     } else if (binning[0] == binPhi && binning[1] == binR) {
0058       vType = polar;
0059       //  flip to fit with actsvg convention
0060       edges1 = axes[0]->getBinEdges();
0061       edges0 = axes[1]->getBinEdges();
0062       pGrid._type = actsvg::proto::grid::e_r_phi;
0063     } else if (binning[0] == binZ && binning[1] == binPhi) {
0064       // good
0065       vType = cylinder;
0066       edges0 = axes[0]->getBinEdges();
0067       edges1 = axes[1]->getBinEdges();
0068       pGrid._type = actsvg::proto::grid::e_z_phi;
0069     } else if (binning[0] == binR && binning[1] == binPhi) {
0070       // good
0071       vType = polar;
0072       edges0 = axes[0]->getBinEdges();
0073       edges1 = axes[1]->getBinEdges();
0074       pGrid._type = actsvg::proto::grid::e_r_phi;
0075     }
0076     // Assign
0077     pGrid._edges_0 = convertGridEdges(edges0);
0078     pGrid._edges_1 = convertGridEdges(edges1);
0079   }
0080 
0081   // Find the template surfaces & prepare template objects to be assigned
0082   std::vector<actsvg::svg::object> templateObjects;
0083   std::vector<const SurfaceBounds*> templateBounds;
0084 
0085   for (const auto& sf : surfaces) {
0086     // Get bounds and check them
0087     const SurfaceBounds& sBounds = sf->bounds();
0088     // Helper to find bounds
0089     auto sameBounds = [&](const SurfaceBounds* test) {
0090       return ((*test) == sBounds);
0091     };
0092     // Check if you have this template object already
0093     auto tBounds =
0094         std::find_if(templateBounds.begin(), templateBounds.end(), sameBounds);
0095     // New reference bounds and new reference object
0096     if (tBounds == templateBounds.end()) {
0097       // Let's get the right style
0098       SurfaceConverter::Options sOptions;
0099       sOptions.templateSurface = true;
0100       // Find a corresponding file in the playbook
0101       auto sfStyle = cOptions.surfaceStyles.find(sf->geometryId());
0102       if (sfStyle != cOptions.surfaceStyles.end()) {
0103         sOptions.style = *sfStyle;
0104       }
0105 
0106       // Create a referese surface and reference object from it
0107       auto referenceSurface = SurfaceConverter::convert(gctx, *sf, sOptions);
0108       auto referenceObject =
0109           View::xy(referenceSurface,
0110                    "Template_" + std::to_string(templateObjects.size()));
0111       templateBounds.push_back(&sBounds);
0112       templateObjects.push_back(referenceObject);
0113     }
0114   }
0115 
0116   // Estimate a reference radius
0117   ActsScalar radius = 0.;
0118 
0119   // Now draw the surfaces from the correct template
0120   for (const auto& sf : surfaces) {
0121     radius += Acts::VectorHelpers::perp(sf->center(gctx));
0122 
0123     // Let's get the right style
0124     SurfaceConverter::Options sOptions;
0125     sOptions.templateSurface = vType != cylinder;
0126     // Find a corresponding file in the playbook
0127     auto sfStyle = cOptions.surfaceStyles.find(sf->geometryId());
0128     if (sfStyle != cOptions.surfaceStyles.end()) {
0129       sOptions.style = *sfStyle;
0130     }
0131 
0132     // Convert the surface from ACTS to actsvg
0133     auto cSurface = Acts::Svg::SurfaceConverter::convert(gctx, *sf, sOptions);
0134     cSurface._name = "Module_n_" + std::to_string(pSurfaces.size());
0135 
0136     cSurface._aux_info["grid_info"] = {
0137         "* module " + std::to_string(pSurfaces.size()) +
0138         ", surface = " + std::to_string(sf->geometryId().sensitive())};
0139     // Assign the template for cylinder layers
0140     if (vType == cylinder) {
0141       const SurfaceBounds& sBounds = sf->bounds();
0142       // Helper to find bounds
0143       auto sameBounds = [&](const SurfaceBounds* test) {
0144         return ((*test) == sBounds);
0145       };
0146       // Check if you have this template object already
0147       auto tBounds = std::find_if(templateBounds.begin(), templateBounds.end(),
0148                                   sameBounds);
0149       // New reference bounds and new reference object
0150       if (tBounds != templateBounds.end()) {
0151         std::size_t tObject = std::distance(templateBounds.begin(), tBounds);
0152         cSurface._template_object = templateObjects[tObject];
0153       }
0154     }
0155     // Correct view transform for disc/planar layers
0156     if (vType == planar || vType == polar) {
0157       // Get the transform and estimate the rotation of phi
0158       // Assumes x/y view
0159       const auto& sTransform = sf->transform(gctx);
0160       Vector3 localA = sTransform.rotation().col(0);
0161       Vector3 localZ = sTransform.rotation().col(2);
0162       // Find out orientation w.r.t. global transform
0163       ActsScalar projZ = localZ.dot(Vector3(0., 0., 1.));
0164       ActsScalar alpha = std::atan2(localA[1], localA[0]) / M_PI * 180.;
0165       if (projZ < 0.) {
0166         alpha += 180.;
0167       }
0168       auto surfaceCenter = sf->center(gctx);
0169       // Set the transform for an eventual placement
0170       cSurface._transform._tr = {static_cast<actsvg::scalar>(surfaceCenter[0]),
0171                                  static_cast<actsvg::scalar>(surfaceCenter[1])};
0172       cSurface._transform._rot = {static_cast<actsvg::scalar>(alpha), 0., 0.};
0173     }
0174 
0175     pSurfaces.push_back(cSurface);
0176   }
0177   radius /= surfaces.size();
0178 
0179   // Create the bin associations
0180   for (unsigned int il0 = 1; il0 < pGrid._edges_0.size(); ++il0) {
0181     ActsScalar p0 = 0.5 * (pGrid._edges_0[il0] + pGrid._edges_0[il0 - 1]);
0182     for (unsigned int il1 = 1; il1 < pGrid._edges_1.size(); ++il1) {
0183       ActsScalar p1 = 0.5 * (pGrid._edges_1[il1] + pGrid._edges_1[il1 - 1]);
0184       // Create the fitting bin center estimates
0185       Vector3 bCenter;
0186       if (vType == polar) {
0187         bCenter = Vector3(p0 * std::cos(p1), p0 * std::sin(p1), 0.);
0188       } else if (vType == cylinder) {
0189         bCenter = Vector3(radius * std::cos(p1), radius * std::sin(p1), p0);
0190       }
0191       // Get all the bin entries and members
0192       auto bSurfaces = surfaceArray.neighbors(bCenter);
0193       std::vector<std::size_t> binnAssoc;
0194       for (const auto& bs : bSurfaces) {
0195         auto candidate = std::find(surfaces.begin(), surfaces.end(), bs);
0196         if (candidate != surfaces.end()) {
0197           binnAssoc.push_back(std::distance(surfaces.begin(), candidate));
0198         }
0199       }
0200       pAssociations.push_back(binnAssoc);
0201     }
0202   }
0203   // Return the surfaces and the grid
0204   std::vector<ProtoSurfaces> pSurfaceBatches = {pSurfaces};
0205   std::vector<ProtoAssociations> pAssociationBatchs = {pAssociations};
0206   return std::tie(pSurfaceBatches, pGrid, pAssociationBatchs);
0207 }