Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-29 08:24:12

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 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 https://mozilla.org/MPL/2.0/.
0008 
0009 #include <boost/test/unit_test.hpp>
0010 
0011 #include "Acts/Definitions/Units.hpp"
0012 #include "Acts/Geometry/GeometryIdentifier.hpp"
0013 #include "Acts/Material/BinnedSurfaceMaterial.hpp"
0014 #include "Acts/Material/GridSurfaceMaterial.hpp"
0015 #include "Acts/Material/HomogeneousSurfaceMaterial.hpp"
0016 #include "Acts/Material/HomogeneousVolumeMaterial.hpp"
0017 #include "Acts/Material/MaterialSlab.hpp"
0018 #include "Acts/Material/TrackingGeometryMaterial.hpp"
0019 #include "Acts/Utilities/AxisDefinitions.hpp"
0020 #include "Acts/Utilities/BinUtility.hpp"
0021 #include "Acts/Utilities/IAxis.hpp"
0022 #include "Acts/Utilities/Logger.hpp"
0023 #include "ActsPlugins/Json/MaterialMapJsonConverter.hpp"
0024 #include "ActsTests/CommonHelpers/PredefinedMaterials.hpp"
0025 
0026 #include <cstdlib>
0027 #include <fstream>
0028 #include <iterator>
0029 #include <memory>
0030 #include <string>
0031 #include <vector>
0032 
0033 #include <nlohmann/json.hpp>
0034 
0035 using namespace Acts;
0036 using namespace Acts::UnitLiterals;
0037 
0038 namespace ActsTests {
0039 
0040 namespace {
0041 
0042 /// The one real material of the example, reused wherever material is needed
0043 MaterialSlab exampleSlab() {
0044   return {makeSilicon(), 0.15_mm};
0045 }
0046 
0047 /// The store the index grid points into. Vacuum sits at index 0 so the example
0048 /// shows both an empty slab and an index that is not the bin number.
0049 std::vector<MaterialSlab> exampleSlabStore() {
0050   return {MaterialSlab::Nothing(), exampleSlab()};
0051 }
0052 
0053 /// The material of the documented example.
0054 ///
0055 /// This is not a coverage test -- that the encoder handles every material type
0056 /// is checked by SurfaceMaterialJsonConverterTests. The example only has to
0057 /// show the structure, so it carries the three surface payloads that differ in
0058 /// shape (a plain slab, a binned matrix, a grid) plus one volume entry, and
0059 /// every count is the smallest the format allows. The result is included
0060 /// verbatim in the documentation, so every line of it is a line someone reads.
0061 TrackingGeometryMaterial exampleMaterialMaps() {
0062   SurfaceMaterialMaps surfaces;
0063   VolumeMaterialMaps volumes;
0064 
0065   const GeometryIdentifier volume1 = GeometryIdentifier().withVolume(1);
0066   const GeometryIdentifier volume2 = GeometryIdentifier().withVolume(2);
0067 
0068   // A single slab covering the whole surface
0069   surfaces[volume1.withBoundary(1)] =
0070       std::make_shared<const HomogeneousSurfaceMaterial>(
0071           exampleSlab(), 1., MappingType::PreMapping);
0072 
0073   // The classic binned material: a BinUtility plus a slab matrix. The second
0074   // bin is left empty to show how an uncovered bin is written.
0075   BinUtility binUtility(2, -100., 100., open, AxisDirection::AxisZ);
0076   MaterialSlabMatrix matrix{
0077       MaterialSlabVector{exampleSlab(), MaterialSlab::Nothing()}};
0078   surfaces[volume1.withLayer(2).withApproach(1)] =
0079       std::make_shared<const BinnedSurfaceMaterial>(binUtility,
0080                                                     std::move(matrix));
0081 
0082   // Grid material, bins index into a slab store. The other two storage
0083   // backends, and the proto materials, differ from this only in the keys
0084   // listed in the docs. The grid is always two dimensional.
0085   {
0086     auto axis0 =
0087         IAxis::createEquidistant(AxisBoundaryType::Bound, -100., 100., 1);
0088     auto axis1 =
0089         IAxis::createEquidistant(AxisBoundaryType::Bound, -100., 100., 1);
0090     surfaces[volume2.withLayer(4)] = GridSurfaceMaterial::createIndexed(
0091         *axis0, *axis1, exampleSlabStore(),
0092         std::vector<std::vector<std::size_t>>{std::vector<std::size_t>{1u}});
0093   }
0094 
0095   volumes[volume1] =
0096       std::make_shared<const HomogeneousVolumeMaterial>(makeSilicon());
0097 
0098   return {std::move(surfaces), std::move(volumes)};
0099 }
0100 
0101 /// The documented example file to check against, passed on the command line by
0102 /// ctest so the test does not have to know where the source tree lives.
0103 std::string exampleFilePath() {
0104   const auto& master = boost::unit_test::framework::master_test_suite();
0105   BOOST_REQUIRE_MESSAGE(master.argc == 2,
0106                         "Expected exactly one argument, the example file path");
0107   return master.argv[1];
0108 }
0109 
0110 }  // namespace
0111 
0112 BOOST_AUTO_TEST_SUITE(JsonSuite)
0113 
0114 /// Writes the material map example that the JSON plugin documentation shows,
0115 /// and fails if the committed file no longer matches what the converter
0116 /// produces. Set ACTS_UPDATE_DOC_EXAMPLES=1 to refresh the file in place.
0117 BOOST_AUTO_TEST_CASE(MaterialMapDocumentationExample) {
0118   MaterialMapJsonConverter::Config converterCfg;
0119   MaterialMapJsonConverter converter(converterCfg, Logging::WARNING);
0120 
0121   nlohmann::json jMap = converter.materialMapsToJson(exampleMaterialMaps());
0122 
0123   // The documented example has to be something the plugin can read back
0124   nlohmann::json jRoundTrip =
0125       converter.materialMapsToJson(converter.jsonToMaterialMaps(jMap));
0126   BOOST_CHECK_EQUAL(jMap, jRoundTrip);
0127 
0128   const std::string path = exampleFilePath();
0129   // Four spaces and a trailing newline, so the file survives the
0130   // repository's json formatting hook unchanged
0131   const std::string encoded = jMap.dump(4) + "\n";
0132 
0133   if (const char* update = std::getenv("ACTS_UPDATE_DOC_EXAMPLES");
0134       update != nullptr && std::string(update) != "0") {
0135     std::ofstream out(path);
0136     BOOST_REQUIRE_MESSAGE(out.is_open(), "Cannot write " << path);
0137     out << encoded;
0138     return;
0139   }
0140 
0141   std::ifstream in(path);
0142   BOOST_REQUIRE_MESSAGE(in.is_open(), "Cannot read " << path);
0143   const std::string committed{std::istreambuf_iterator<char>(in),
0144                               std::istreambuf_iterator<char>()};
0145 
0146   BOOST_CHECK_MESSAGE(
0147       committed == encoded,
0148       path << " is out of date, regenerate it by running this test with "
0149               "ACTS_UPDATE_DOC_EXAMPLES=1");
0150 }
0151 
0152 BOOST_AUTO_TEST_SUITE_END()
0153 
0154 }  // namespace ActsTests