39 const std::vector<const Acts::Experimental::DetectorVolume*>&
volumes) {
40 auto candidate = std::find(volumes.begin(), volumes.end(), volume);
41 if (candidate != volumes.end()) {
50 const std::vector<const Experimental::DetectorVolume*>&
detectorVolumes,
53 nlohmann::json jPortal;
59 nlohmann::json jLinks;
60 for (
const auto& vLink : volumeLinks) {
61 nlohmann::json jLink =
toJson(vLink, detectorVolumes);
62 jLinks.push_back(jLink);
64 jPortal[
"volume_links"] = jLinks;
73 const std::vector<const Experimental::DetectorVolume*>&
detectorVolumes,
76 std::vector<nlohmann::json> jPortals = {};
81 std::size_t outside = 1
u;
85 if (surface.
type() != Acts::Surface::SurfaceType::Cylinder) {
87 const auto volumeCenter = volume.
transform(gctx).translation();
88 const auto surfaceCenter = surface.
center(gctx);
89 const auto surfaceNormal = surface.
normal(gctx);
91 const auto volumeToSurface = surfaceCenter - volumeCenter;
92 if (volumeToSurface.dot(surfaceNormal) < 0) {
102 const auto& outsideLink = volumeLinks[outside];
105 const auto* instance = outsideLink.instance();
111 auto [surfaceAdjusted, insidePointer] = orientedSurfaces[ip];
114 surfaceOptions.
portal =
true;
117 if (singleLink !=
nullptr) {
119 std::size_t vLink = findVolume(singleLink->dVolume, detectorVolumes);
123 jPortals.push_back(jPortal);
128 if (multiLink1D !=
nullptr) {
132 const auto&
cast = multiLink1D->indexedUpdator.casts[0
u];
133 const auto&
transform = multiLink1D->indexedUpdator.transform;
134 const auto& volumes = multiLink1D->indexedUpdator.extractor.dVolumes;
135 if (not
transform.isApprox(Transform3::Identity())) {
137 "PortalJsonConverter: transformed boundary link implementation not "
142 auto surfaceType = surfaceAdjusted->type();
143 std::vector<unsigned int> vIndices = {};
144 for (
const auto&
v : volumes) {
145 vIndices.push_back(findVolume(
v, detectorVolumes));
149 std::array<ActsScalar, 2u> clipRange = {0., 0.};
150 std::vector<ActsScalar> boundValues = surfaceAdjusted->bounds().values();
151 if (surfaceType == Surface::SurfaceType::Cylinder and
cast ==
binZ) {
152 ActsScalar zPosition = surfaceAdjusted->center(gctx).z();
154 zPosition - boundValues[CylinderBounds::BoundValues::eHalfLengthZ],
155 zPosition + boundValues[CylinderBounds::BoundValues::eHalfLengthZ]};
156 }
else if (surfaceType == Surface::SurfaceType::Disc and
cast ==
binR) {
157 clipRange = {boundValues[RadialBounds::BoundValues::eMinR],
158 boundValues[RadialBounds::BoundValues::eMaxR]};
160 throw std::runtime_error(
161 "PortalJsonConverter: surface type not (yet) supported for detray "
162 "conversion, only cylinder and disc are currently supported.");
166 std::vector<unsigned int> clippedIndices = {};
167 std::vector<ActsScalar> clippedBoundaries = {};
168 clippedBoundaries.push_back(clipRange[0
u]);
171 unsigned int vI = vIndices[
ib - 1
u];
173 if (boundaries[
ib - 1] >= clipRange[1u]) {
176 if (highEdge <= clipRange[0u]) {
179 if (highEdge > clipRange[1u]) {
180 highEdge = clipRange[1
u];
182 clippedIndices.push_back(vI);
183 clippedBoundaries.push_back(highEdge);
190 if (surfaceType == Surface::SurfaceType::Cylinder) {
194 std::array<ActsScalar, CylinderBounds::BoundValues::eSize>
196 for (
auto [ibv, bv] :
enumerate(boundValues)) {
197 subBoundValues[ibv] = bv;
199 subBoundValues[CylinderBounds::BoundValues::eHalfLengthZ] =
200 0.5 * (
b - clippedBoundaries[
ib - 1
u]);
201 auto subBounds = std::make_shared<CylinderBounds>(subBoundValues);
202 auto subTransform = Transform3::Identity();
203 subTransform.pretranslate(
Vector3(
205 clippedBoundaries[
ib - 1u] +
206 subBoundValues[CylinderBounds::BoundValues::eHalfLengthZ]));
208 Surface::makeShared<CylinderSurface>(subTransform, subBounds);
212 clippedIndices[
ib - 1u]);
213 jPortals.push_back(jPortal);
220 std::array<ActsScalar, RadialBounds::BoundValues::eSize>
222 for (
auto [ibv, bv] :
enumerate(boundValues)) {
223 subBoundValues[ibv] = bv;
225 subBoundValues[RadialBounds::BoundValues::eMinR] =
226 clippedBoundaries[
ib - 1
u];
227 subBoundValues[RadialBounds::BoundValues::eMaxR] =
b;
228 auto subBounds = std::make_shared<RadialBounds>(subBoundValues);
229 auto subSurface = Surface::makeShared<DiscSurface>(
234 clippedIndices[
ib - 1u]);
235 jPortals.push_back(jPortal);
246 jPortal[
"mask"], std::numeric_limits<std::uint_least16_t>::max());
247 jPortals.push_back(jPortal);
255 const std::vector<const Experimental::DetectorVolume*>&
detectorVolumes) {
256 nlohmann::json jLink;
257 if (updator.connected()) {
258 const auto instance = updator.instance();
263 if (singleLink !=
nullptr) {
264 auto vIndex = findVolume(singleLink->dVolume, detectorVolumes);
266 throw std::runtime_error(
267 "PortalJsonConverter: volume not found in the list of volumes.");
269 jLink[
"single"] = vIndex;
274 if (multiLink1D !=
nullptr) {
275 nlohmann::json jMultiLink;
276 const auto& volumes = multiLink1D->indexedUpdator.extractor.dVolumes;
277 const auto& casts = multiLink1D->indexedUpdator.casts;
279 multiLink1D->indexedUpdator.transform);
280 std::vector<unsigned int> vIndices = {};
281 for (
const auto&
v : volumes) {
282 vIndices.push_back(findVolume(
v, detectorVolumes));
284 jMultiLink[
"boundaries"] =
285 multiLink1D->indexedUpdator.grid.axes()[0
u]->getBinEdges();
286 jMultiLink[
"binning"] = casts[0
u];
287 jMultiLink[
"targets"] = vIndices;
288 jMultiLink[
"transform"] = jTransform;
289 jLink[
"multi_1D"] = jMultiLink;
297 const std::vector<std::shared_ptr<Experimental::DetectorVolume>>&
301 auto portal = Experimental::Portal::makeShared(
surface);
303 std::array<Acts::Direction, 2> normalDirs = {Direction::Backward,
306 auto jLinks = jPortal[
"volume_links"];
307 for (
auto [ivl, vl] :
enumerate(jLinks)) {
308 if (vl.contains(
"single")) {
309 const auto vIndex = vl[
"single"].get<
unsigned int>();
312 }
else if (vl.contains(
"multi_1D")) {
314 auto jMultiLink = vl[
"multi_1D"];
315 auto boundaries = jMultiLink[
"boundaries"].get<std::vector<double>>();
316 auto binning = jMultiLink[
"binning"].get<
BinningValue>();
317 auto targets = jMultiLink[
"targets"].get<std::vector<unsigned int>>();
318 std::vector<std::shared_ptr<Experimental::DetectorVolume>> targetVolumes;
319 for (
const auto t : targets) {
323 gctx, *portal, targetVolumes, normalDirs[ivl], boundaries, binning);