Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-10-29 08:23:13

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 "ActsPlugins/Json/MaterialMapJsonConverter.hpp"
0010 #include "ActsPlugins/Json/TrackingGeometryMaterialJsonConverter.hpp"
0011 #include "ActsPlugins/Json/detail/JsonIo.hpp"
0012 
0013 #ifdef ACTS_MATERIAL_MIGRATE_ROOT
0014 #include "ActsPlugins/Root/RootMaterialDecorator.hpp"
0015 #endif
0016 
0017 #include <charconv>
0018 #include <filesystem>
0019 #include <iostream>
0020 #include <stdexcept>
0021 #include <string>
0022 #include <string_view>
0023 
0024 namespace {
0025 constexpr std::string_view usage =
0026     "Usage: ActsMaterialMapMigrate INPUT OUTPUT [OPTIONS]\n"
0027     "Migrate legacy surface material maps to the version 1 format.\n"
0028     "ROOT input (.root) requires ACTS_BUILD_PLUGIN_ROOT=ON.\n"
0029     "Input: JSON or CBOR, optionally zstd compressed (detected from content).\n"
0030     "Output: .json, .cbor, .json.zst or .cbor.zst.\n"
0031     "Volume material is not supported by version 1.\n\n"
0032     "Options:\n"
0033     "  --material-fraction-bits N  Retained fraction bits, 0-23 (default 23)\n"
0034     "  --compression-level N       zstd level (default 9)\n"
0035     "  --indentation N             JSON indentation (default 4)\n"
0036     "  --help                      Show this help\n";
0037 
0038 template <typename T>
0039 T number(std::string_view text) {
0040   T result{};
0041   const auto [end, error] =
0042       std::from_chars(text.data(), text.data() + text.size(), result);
0043   if (error != std::errc{} || end != text.data() + text.size()) {
0044     throw std::invalid_argument("Invalid numeric option: " + std::string(text));
0045   }
0046   return result;
0047 }
0048 
0049 Acts::TrackingGeometryMaterial readMaterial(
0050     const std::filesystem::path& input) {
0051   if (input.extension() == ".root") {
0052 #ifdef ACTS_MATERIAL_MIGRATE_ROOT
0053     ActsPlugins::RootMaterialDecorator::Config config;
0054     config.fileName = input.string();
0055     auto material =
0056         ActsPlugins::RootMaterialDecorator(config, Acts::Logging::WARNING)
0057             .materialMaps();
0058     if (material.surfaceMaterials.empty() && material.volumeMaterials.empty()) {
0059       throw std::invalid_argument("No material maps found in ROOT input");
0060     }
0061     return material;
0062 #else
0063     throw std::invalid_argument(
0064         "ROOT input is unavailable in this build; rebuild with "
0065         "ACTS_BUILD_PLUGIN_ROOT=ON");
0066 #endif
0067   }
0068   const auto document = Acts::detail::readJsonFile(input);
0069   // Check the envelope before calling the legacy reader, which uses [].
0070   if (!document.contains("Surfaces") || !document.contains("Volumes")) {
0071     throw std::invalid_argument(
0072         "Expected a legacy material map with Surfaces and Volumes");
0073   }
0074   Acts::MaterialMapJsonConverter legacy({}, Acts::Logging::WARNING);
0075   return legacy.jsonToMaterialMaps(document);
0076 }
0077 
0078 }  // namespace
0079 
0080 int main(int argc, char* argv[]) {
0081   for (int i = 1; i < argc; ++i) {
0082     if (std::string_view(argv[i]) == "--help") {
0083       std::cout << usage;
0084       return 0;
0085     }
0086   }
0087   if (argc < 3) {
0088     std::cerr << usage;
0089     return 1;
0090   }
0091   try {
0092     Acts::TrackingGeometryMaterialJsonConverter::Options options;
0093     for (int i = 3; i < argc; i += 2) {
0094       const std::string_view option = argv[i];
0095       if (i + 1 == argc) {
0096         throw std::invalid_argument("Missing value for " + std::string(option));
0097       }
0098       if (option == "--material-fraction-bits") {
0099         options.materialFractionBits = number<unsigned int>(argv[i + 1]);
0100       } else if (option == "--compression-level") {
0101         options.compressionLevel = number<int>(argv[i + 1]);
0102       } else if (option == "--indentation") {
0103         options.indentation = number<unsigned int>(argv[i + 1]);
0104       } else {
0105         throw std::invalid_argument("Unknown option: " + std::string(option));
0106       }
0107     }
0108     const std::filesystem::path input = argv[1];
0109     const std::filesystem::path output = argv[2];
0110     if (std::filesystem::exists(output) &&
0111         std::filesystem::equivalent(input, output)) {
0112       throw std::invalid_argument("Input and output must be different files");
0113     }
0114     const auto material = readMaterial(input);
0115     Acts::TrackingGeometryMaterialJsonConverter().toFile(material, output,
0116                                                          options);
0117     std::cout << "Migrated "
0118               << material.surfaceMaterials.size() +
0119                      material.keyedSurfaces.size()
0120               << " surface assignments to " << output << '\n';
0121     return 0;
0122   } catch (const std::exception& error) {
0123     std::cerr << "Material migration failed: " << error.what() << '\n';
0124     return 1;
0125   }
0126 }