Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:13:11

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/Geometry/GeometryHierarchyMap.hpp"
0012 #include "Acts/Geometry/GeometryIdentifier.hpp"
0013 #include "Acts/Plugins/Json/GeometryHierarchyMapJsonConverter.hpp"
0014 #include "Acts/Tests/CommonHelpers/DataDirectory.hpp"
0015 
0016 #include <algorithm>
0017 #include <fstream>
0018 #include <initializer_list>
0019 #include <stdexcept>
0020 #include <string>
0021 #include <vector>
0022 
0023 #include <nlohmann/json.hpp>
0024 
0025 namespace {
0026 
0027 using Acts::GeometryIdentifier;
0028 using nlohmann::json;
0029 
0030 // helper function to create geometry ids.
0031 GeometryIdentifier makeId(int volume = 0, int layer = 0, int sensitive = 0) {
0032   return GeometryIdentifier().setVolume(volume).setLayer(layer).setSensitive(
0033       sensitive);
0034 }
0035 
0036 // example element for the container
0037 
0038 struct Thing {
0039   double x = 1.0;
0040   int y = 23;
0041 
0042   friend constexpr bool operator==(const Thing& lhs, const Thing& rhs) {
0043     return (lhs.x == rhs.x) && (lhs.y == rhs.y);
0044   }
0045 };
0046 
0047 // custom Json encoder/decoder. naming is mandated by nlohmann::json and thus
0048 // can not match our naming guidelines.
0049 
0050 void to_json(json& j, const Thing& t) {
0051   j = json{{"x", t.x}, {"y", t.y}};
0052 }
0053 
0054 void from_json(const json& j, Thing& t) {
0055   j.at("x").get_to(t.x);
0056   j.at("y").get_to(t.y);
0057 }
0058 
0059 std::ostream& operator<<(std::ostream& os, const Thing& t) {
0060   os << nlohmann::json(t);
0061   return os;
0062 }
0063 
0064 class ThingDecorator {
0065  public:
0066   void decorate(const Thing* a_thing, nlohmann::json& a_json) const {
0067     if (a_thing != nullptr) {
0068       a_json["product"] = a_thing->x * a_thing->y;
0069     }
0070   }
0071 };
0072 
0073 using Container = Acts::GeometryHierarchyMap<Thing>;
0074 using Converter =
0075     Acts::GeometryHierarchyMapJsonConverter<Thing, ThingDecorator>;
0076 
0077 }  // namespace
0078 
0079 template <>
0080 void Acts::decorateJson<Thing>(const ThingDecorator* decorator,
0081                                const Thing& src, nlohmann::json& dest) {
0082   if (decorator != nullptr) {
0083     decorator->decorate(&src, dest);
0084   }
0085 }
0086 
0087 BOOST_TEST_DONT_PRINT_LOG_VALUE(json::iterator)
0088 BOOST_TEST_DONT_PRINT_LOG_VALUE(Container::Iterator)
0089 
0090 BOOST_AUTO_TEST_SUITE(GeometryHierarchyMapJsonConverter)
0091 
0092 BOOST_AUTO_TEST_CASE(ToJson) {
0093   ThingDecorator decorator;
0094   Container c = {
0095       {makeId(1), {2.0, -3}},
0096       {makeId(2, 3), {-4.5, 5}},
0097       {makeId(4, 5, 6), {7.25, -8}},
0098   };
0099   json j = Converter("thing").toJson(c, &decorator);
0100 
0101   BOOST_CHECK(j.is_object());
0102   // check header
0103   auto header = j.find("acts-geometry-hierarchy-map");
0104   BOOST_CHECK_NE(header, j.end());
0105   BOOST_CHECK(header->is_object());
0106   BOOST_CHECK(header->at("format-version").is_number_integer());
0107   BOOST_CHECK_EQUAL(header->at("format-version").get<int>(), 0);
0108   BOOST_CHECK(header->at("value-identifier").is_string());
0109   BOOST_CHECK_EQUAL(header->at("value-identifier").get<std::string>(), "thing");
0110   // check entries
0111   auto entries = j.find("entries");
0112   BOOST_CHECK_NE(entries, j.end());
0113   BOOST_CHECK(entries->is_array());
0114   BOOST_CHECK_EQUAL(entries->size(), 3u);
0115 }
0116 
0117 BOOST_AUTO_TEST_CASE(FromJson) {
0118   json j = {
0119       {
0120           "acts-geometry-hierarchy-map",
0121           {
0122               {"format-version", 0},
0123               {"value-identifier", "thing"},
0124           },
0125       },
0126       {
0127           "entries",
0128           {
0129               {
0130                   {"volume", 2},
0131                   {"layer", 3},
0132                   {"value", {{"x", 4.0}, {"y", 4}}},
0133               },
0134               {
0135                   {"volume", 5},
0136                   {"layer", 6},
0137                   {"sensitive", 7},
0138                   {"value", {{"x", 3.0}, {"y", 3}}},
0139               },
0140           },
0141       },
0142   };
0143   Container c = Converter("thing").fromJson(j);
0144 
0145   BOOST_CHECK(!c.empty());
0146   BOOST_CHECK_EQUAL(c.size(), 2);
0147   {
0148     auto it = c.find(makeId(2, 3));
0149     BOOST_CHECK_NE(it, c.end());
0150     BOOST_CHECK_EQUAL(it->x, 4.0);
0151     BOOST_CHECK_EQUAL(it->y, 4);
0152   }
0153   {
0154     auto it = c.find(makeId(5, 6, 7));
0155     BOOST_CHECK_NE(it, c.end());
0156     BOOST_CHECK_EQUAL(it->x, 3.0);
0157     BOOST_CHECK_EQUAL(it->y, 3);
0158   }
0159 }
0160 
0161 BOOST_AUTO_TEST_CASE(FromJsonMissingHeader) {
0162   json j = {
0163       {"entries", {}},
0164   };
0165   BOOST_CHECK_THROW(Converter("an-identifier").fromJson(j),
0166                     std::invalid_argument);
0167 }
0168 
0169 BOOST_AUTO_TEST_CASE(FromJsonInvalidFormatVersion) {
0170   json j = {
0171       {
0172           "acts-geometry-hierarchy-map",
0173           {
0174               {"format-version", -1},
0175               {"value-identifier", "an-identifier"},
0176           },
0177       },
0178       {"entries", {}},
0179   };
0180   BOOST_CHECK_THROW(Converter("an-identifier").fromJson(j),
0181                     std::invalid_argument);
0182 }
0183 
0184 BOOST_AUTO_TEST_CASE(FromJsonInvalidValueIdentifier) {
0185   json j = {
0186       {
0187           "acts-geometry-hierarchy-map",
0188           {
0189               {"format-version", 0},
0190               {"value-identifier", "an-identifier"},
0191           },
0192       },
0193       {"entries", {}},
0194   };
0195   BOOST_CHECK_THROW(Converter("not-the-identifier").fromJson(j),
0196                     std::invalid_argument);
0197 }
0198 
0199 BOOST_AUTO_TEST_CASE(FromJsonMissingEntries) {
0200   json j = {
0201       {
0202           "acts-geometry-hierarchy-map",
0203           {
0204               {"format-version", 0},
0205               {"value-identifier", "an-identifier"},
0206           },
0207       },
0208   };
0209   BOOST_CHECK_THROW(Converter("an-identifier").fromJson(j),
0210                     std::invalid_argument);
0211 }
0212 
0213 BOOST_AUTO_TEST_CASE(Roundtrip) {
0214   ThingDecorator decorator;
0215   Container c0 = {
0216       {makeId(1), {2.0, -3}},
0217       {makeId(2, 3), {-4.5, 5}},
0218       {makeId(4, 5, 6), {7.25, -8}},
0219   };
0220   auto j = Converter("the-identifier").toJson(c0, &decorator);
0221   auto c1 = Converter("the-identifier").fromJson(j);
0222 
0223   BOOST_CHECK_EQUAL(c0.size(), c1.size());
0224   for (auto i = std::min(c0.size(), c1.size()); 0 < i--;) {
0225     BOOST_CHECK_EQUAL(c0.idAt(i), c1.idAt(i));
0226     BOOST_CHECK_EQUAL(c0.valueAt(i), c1.valueAt(i));
0227   }
0228 }
0229 
0230 BOOST_AUTO_TEST_CASE(FromFile) {
0231   // read json data from file
0232   auto path = Acts::Test::getDataPath("geometry-hierarchy-map.json");
0233   auto file = std::ifstream(path, std::ifstream::in | std::ifstream::binary);
0234   BOOST_CHECK(file.good());
0235   json j;
0236   file >> j;
0237   BOOST_CHECK(file.good());
0238   // convert json to container
0239   Container c = Converter("thing").fromJson(j);
0240   // check container content
0241   BOOST_CHECK(!c.empty());
0242   BOOST_CHECK_EQUAL(c.size(), 4);
0243   BOOST_CHECK_NE(c.find(makeId()), c.end());
0244   BOOST_CHECK_NE(c.find(makeId(1, 2)), c.end());
0245   BOOST_CHECK_NE(c.find(makeId(3)), c.end());
0246   BOOST_CHECK_NE(c.find(makeId(3, 4)), c.end());
0247 }
0248 
0249 BOOST_AUTO_TEST_SUITE_END()