Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ProtoDetector.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ProtoDetector.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2022-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 
10 
12 
13 #include <cstddef>
14 #include <sstream>
15 #include <stdexcept>
16 
18  ptVolume.extent.extend(extent);
19  if (container.has_value()) {
20  for (auto& cv : container.value().constituentVolumes) {
21  ptVolume.extent.extend(cv.extent);
22  cv.extendUp(ptVolume);
23  }
24  }
25 }
26 
28  if (container.has_value()) {
29  for (auto& cv : container.value().constituentVolumes) {
30  cv.extent.set(bValue, extent.min(bValue), cv.extent.max(bValue));
31  cv.propagateMinDown(bValue);
32  }
33  }
34 }
35 
37  if (container.has_value()) {
38  for (auto& cv : container.value().constituentVolumes) {
39  cv.extent.set(bValue, cv.extent.min(bValue), extent.max(bValue));
40  cv.propagateMaxDown(bValue);
41  }
42  }
43 }
44 
46  extent.addConstrain(ptVolume.extent);
47  if (container.has_value()) {
48  for (auto& cv : container.value().constituentVolumes) {
49  cv.extent.addConstrain(extent);
50  }
51  }
52 }
53 
54 void Acts::ProtoVolume::harmonize(bool legacy) {
55  std::vector<BinningValue> otherConstrains;
56 
57  // Deal with the constituents
58  if (container.has_value() and
59  not container.value().constituentVolumes.empty()) {
60  auto& cts = container.value();
61 
62  if (cts.constituentBinning.empty()) {
63  std::string errorMsg = std::string("ProtoVolume '") + name +
64  std::string("' with constituents, but no binning");
65  throw std::runtime_error(errorMsg);
66  }
67 
68  // Check if there are any layers present
69  bool layersPresent = false;
70  for (const auto& cv : cts.constituentVolumes) {
71  if (cv.internal.has_value()) {
72  layersPresent = true;
73  break;
74  }
75  }
76 
77  // If layers are present, it can't be a container in the legacy style
78  auto binValue = cts.constituentBinning[0].binvalue;
79  // Set the first last
80  auto& fVolume = cts.constituentVolumes.front();
81  auto& lVolume = cts.constituentVolumes.back();
82 
83  std::vector<float> borders = {};
84 
85  // The volumes should be harmonized in all other constraining values
86  for (auto obValue : s_binningValues) {
87  if (obValue != binValue and extent.constrains(obValue)) {
88  otherConstrains.push_back(obValue);
89  }
90  }
91 
92  // Legacy conversion - layers are kept untouched
93  if (not layersPresent) {
94  // Set the outer boundaries
95  fVolume.extent.set(binValue, extent.min(binValue),
96  fVolume.extent.max(binValue));
97  lVolume.extent.set(binValue, lVolume.extent.min(binValue),
98  extent.max(binValue));
99  // Align the containers
100  borders.push_back(static_cast<float>(fVolume.extent.min(binValue)));
101  for (unsigned int iv = 1; iv < cts.constituentVolumes.size(); ++iv) {
102  auto& lv = cts.constituentVolumes[iv - 1u];
103  ActsScalar zero = lv.extent.min(binValue);
104  ActsScalar low = lv.extent.max(binValue);
105 
106  auto& hv = cts.constituentVolumes[iv];
107  ActsScalar high = hv.extent.min(binValue);
108  ActsScalar mid = 0.5 * (low + high);
109  ActsScalar max = hv.extent.max(binValue);
110  lv.extent.set(binValue, zero, mid);
111  hv.extent.set(binValue, mid, max);
112  borders.push_back(mid);
113  }
114  borders.push_back(cts.constituentVolumes.back().extent.max(binValue));
115 
116  } else if (layersPresent and not legacy) {
117  // Count the gaps
118  std::size_t gaps = 0;
119  std::vector<float> boundaries = {};
120  // New container vector
121  std::vector<ProtoVolume> updatedConstituents;
122  ActsScalar containerMin = extent.min(binValue);
123  if (fVolume.extent.min(binValue) > containerMin) {
125  gap.name = name + "-gap-" + std::to_string(gaps++);
126  gap.extent.set(binValue, containerMin, fVolume.extent.min(binValue));
127  updatedConstituents.push_back(gap);
128  borders.push_back(static_cast<float>(containerMin));
129  }
130  // Fill the gaps
131  for (unsigned int iv = 1; iv < cts.constituentVolumes.size(); ++iv) {
132  auto& lv = cts.constituentVolumes[iv - 1u];
133  // This volume is one to save
134  updatedConstituents.push_back(lv);
135  borders.push_back(static_cast<float>(lv.extent.min(binValue)));
136  // check if a gap to the next is needed
137  ActsScalar low = lv.extent.max(binValue);
138  auto& hv = cts.constituentVolumes[iv];
139  ActsScalar high = hv.extent.min(binValue);
140  if (high > low) {
142  gap.name = name + "-gap-" + std::to_string(gaps++);
143  gap.extent.set(binValue, low, high);
144  updatedConstituents.push_back(gap);
145  borders.push_back(static_cast<float>(low));
146  }
147  }
148  ActsScalar constituentsMax = lVolume.extent.max(binValue);
149  updatedConstituents.push_back(lVolume);
150  borders.push_back(static_cast<float>(constituentsMax));
151  // Check the container min/max setting
152  ActsScalar containerMax = extent.max(binValue);
153  if (constituentsMax < containerMax) {
155  gap.name = name + "-gap-" + std::to_string(gaps++);
156  gap.extent.set(binValue, constituentsMax, containerMax);
157  updatedConstituents.push_back(gap);
158  borders.push_back(static_cast<float>(containerMax));
159  }
160  cts.constituentVolumes = updatedConstituents;
161  } else if (legacy and layersPresent) {
162  borders = {0., 1.};
163  }
164  cts.constituentBinning = {
165  BinningData(cts.constituentBinning[0].option, binValue, borders)};
166 
167  // Harmonize downwards
168  for (auto& cv : cts.constituentVolumes) {
169  cv.extent.extend(extent, otherConstrains);
170  cv.harmonize(legacy);
171  }
172  }
173 }
174 
176  std::string subIndent(" ");
177  std::stringstream ss;
178  ss << indent << "> volume: " << name << '\n';
179  ss << indent << " extent: ";
180  ss << extent.toString(indent) << '\n';
181  if (container.has_value()) {
182  auto& cts = container.value();
183  if (not cts.constituentVolumes.empty()) {
184  ss << indent << " container of " << cts.constituentVolumes.size()
185  << " constituents. " << '\n';
186  ss << indent << " constituent binning:" << '\n';
187  for (const auto& cb : cts.constituentBinning) {
188  ss << cb.toString(indent) << '\n';
189  }
190  ss << indent << " constituents are:" << '\n';
191  for (const auto& cv : cts.constituentVolumes) {
192  ss << cv.toString(indent + subIndent) << '\n';
193  }
194  }
195  }
196  return ss.str();
197 }
198 
200  std::string subIndent(" ");
201  std::stringstream ss;
202  ss << indent << "> detector: " << name << '\n';
203  ss << worldVolume.toString(indent + subIndent) << '\n';
204  return ss.str();
205 }