Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GeometryHierarchyMapJsonConverter.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file GeometryHierarchyMapJsonConverter.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2020-2023 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #pragma once
10 
13 
14 #include <stdexcept>
15 #include <string>
16 #include <type_traits>
17 
18 namespace Acts {
19 
35 template <typename value_t,
36  class decorator_t = void /* e.g. ITrackingGeometryJsonDecorator */>
38  public:
39  using Value = value_t;
41 
46  : m_valueIdentifier(std::move(valueIdentifier)) {
47  if (m_valueIdentifier.empty()) {
48  throw std::invalid_argument("Value identifier must be non-empty");
49  }
50  }
51 
58  nlohmann::json toJson(const Container& container,
59  const decorator_t* decorator) const;
60 
66  Container fromJson(const nlohmann::json& encoded) const;
67 
70  static nlohmann::json encodeIdentifier(const GeometryIdentifier& id) {
71  nlohmann::json encoded;
72  // only store non-zero identifiers
73  if (id.volume() != 0u) {
74  encoded["volume"] = id.volume();
75  }
76  if (id.boundary() != 0u) {
77  encoded["boundary"] = id.boundary();
78  }
79  if (id.layer() != 0u) {
80  encoded["layer"] = id.layer();
81  }
82  if (id.approach() != 0u) {
83  encoded["approach"] = id.approach();
84  }
85  if (id.sensitive() != 0u) {
86  encoded["sensitive"] = id.sensitive();
87  }
88  if (id.extra() != 0u) {
89  encoded["extra"] = id.extra();
90  }
91  return encoded;
92  }
93 
97  static GeometryIdentifier decodeIdentifier(const nlohmann::json& encoded) {
98  return GeometryIdentifier()
99  .setVolume(encoded.value("volume", GeometryIdentifier::Value(0u)))
100  .setBoundary(encoded.value("boundary", GeometryIdentifier::Value(0u)))
101  .setLayer(encoded.value("layer", GeometryIdentifier::Value(0u)))
102  .setApproach(encoded.value("approach", GeometryIdentifier::Value(0u)))
103  .setSensitive(encoded.value("sensitive", GeometryIdentifier::Value(0u)))
104  .setExtra(encoded.value("extra", GeometryIdentifier::Value(0u)));
105  }
106 
107  private:
108  static constexpr const char* kHeaderKey = "acts-geometry-hierarchy-map";
109  static constexpr const char* kEntriesKey = "entries";
112  static constexpr int kFormatVersion = 0;
113 
115 };
116 
117 // implementations
118 
119 // auxiliary struct to indicate a missing specialization of a template which
120 // requires specialisation
121 template <typename T, class decorator_t>
123 
124 // methods to adapt type decorations for the given decorator
125 template <class T, class decorator_t>
126 void decorateJson([[maybe_unused]] const decorator_t* decorator,
127  [[maybe_unused]] const T& src,
128  [[maybe_unused]] nlohmann::json& dest) {
129  // this needs to be specialised
130  static_assert(
132  "Explicit specialization needed for each decorator_t and src T");
133 }
134 template <class T, class decorator_t>
135 void decorateJson([[maybe_unused]] const decorator_t* decorator,
136  [[maybe_unused]] const T* src,
137  [[maybe_unused]] nlohmann::json& dest) {
138  // this needs to be specialised
139  static_assert(
141  "Explicit specialization needed for each decorator_t and src T");
142 }
143 
144 template <typename value_t, class decorator_t>
146  const Container& container,
147  [[maybe_unused]] const decorator_t* decorator) const {
148  // encode header
149  nlohmann::json encoded = nlohmann::json::object();
150  encoded[kHeaderKey] = nlohmann::json::object();
151  encoded[kHeaderKey]["format-version"] = kFormatVersion;
152  encoded[kHeaderKey]["value-identifier"] = m_valueIdentifier;
153  // encode entries
154  nlohmann::json entries = nlohmann::json::array();
155  for (std::size_t i = 0; i < container.size(); ++i) {
156  auto entry = encodeIdentifier(container.idAt(i));
157  auto value_json = nlohmann::json(container.valueAt(i));
158  if constexpr (not std::is_same<decorator_t, void>::value) {
159  decorateJson(decorator, container.valueAt(i), value_json);
160  }
161  entry["value"] = std::move(value_json);
162  entries.push_back(std::move(entry));
163  }
164  encoded[kEntriesKey] = std::move(entries);
165  return encoded;
166 }
167 
168 template <typename value_t, class decorator_t>
170  const nlohmann::json& encoded) const -> Container {
171  // verify json format header
172  auto header = encoded.find(kHeaderKey);
173  if (header == encoded.end()) {
174  throw std::invalid_argument(
175  "Missing header entry in json geometry hierarchy map");
176  }
177  if (header->at("format-version").get<int>() != kFormatVersion) {
178  throw std::invalid_argument(
179  "Invalid format version in json geometry hierarchy map");
180  }
181  if (header->at("value-identifier").get<std::string>() != m_valueIdentifier) {
182  throw std::invalid_argument(
183  "Inconsistent value identifier in Json geometry hierarchy map");
184  }
185  // decode json entries
186  if (not encoded.contains(kEntriesKey)) {
187  throw std::invalid_argument(
188  "Missing entries in json geometry hierarchy map");
189  }
190  std::vector<std::pair<GeometryIdentifier, Value>> elements;
191  for (const auto& entry : encoded.at(kEntriesKey)) {
192  auto id = decodeIdentifier(entry);
193  auto value = entry.at("value").get<Value>();
194  elements.emplace_back(id, std::move(value));
195  }
196  return elements;
197 }
198 
199 } // namespace Acts