LDMX Software
TrackingGeometry.cxx
1
2#include "Tracking/geo/TrackingGeometry.h"
3
4#include "G4RunManager.hh"
5#include "G4UIsession.hh"
6#include "G4strstreambuf.hh"
7#include "Tracking/geo/GeoUtils.h"
8
9namespace tracking::geo {
10
16class SilentG4 : public G4UIsession {
17 public:
18 SilentG4() = default;
19 ~SilentG4() = default;
20 G4UIsession* SessionStart() { return nullptr; }
21 G4int ReceiveG4cout(const G4String&) { return 0; }
22 G4int ReceiveG4cerr(const G4String&) { return 0; }
23};
24
25TrackingGeometry::TrackingGeometry(const std::string& name,
26 const Acts::GeometryContext& gctx,
27 const std::string& gdml, bool debug)
28 : framework::ConditionsObject(name),
29 gctx_{gctx},
30 gdml_{gdml},
31 debug_{debug} {
32 // Build The rotation matrix to the tracking frame
33 // Rotate the sensors to be orthogonal to X
34 double rotationAngle = M_PI * 0.5;
35
36 // 0 0 -1
37 // 0 1 0
38 // 1 0 0
39
40 // This rotation is needed to have the plane orthogonal to the X direction.
41 // Rotation of the surfaces
42 Acts::Vector3 xPos1(cos(rotationAngle), 0., sin(rotationAngle));
43 Acts::Vector3 yPos1(0., 1., 0.);
44 Acts::Vector3 zPos1(-sin(rotationAngle), 0., cos(rotationAngle));
45
46 y_rot_.col(0) = xPos1;
47 y_rot_.col(1) = yPos1;
48 y_rot_.col(2) = zPos1;
49
50 // Rotate the sensors to put them in the proper orientation in Z
51 Acts::Vector3 xPos2(1., 0., 0.);
52 Acts::Vector3 yPos2(0., cos(rotationAngle), sin(rotationAngle));
53 Acts::Vector3 zPos2(0., -sin(rotationAngle), cos(rotationAngle));
54
55 x_rot_.col(0) = xPos2;
56 x_rot_.col(1) = yPos2;
57 x_rot_.col(2) = zPos2;
58
70 std::unique_ptr<SilentG4> silence;
71 if (G4RunManager::GetRunManager() == nullptr) {
72 // no run manager ==> no simulation
73 silence = std::make_unique<SilentG4>();
74 // these lines compied from G4UImanager::SetCoutDestination
75 // to avoid creating G4UImanager unnecessarily
76 G4coutbuf.SetDestination(silence.get());
77 G4cerrbuf.SetDestination(silence.get());
78 }
79
80 // Get the world volume
81 G4GDMLParser parser;
82
83 // Validation requires internet
84 parser.Read(gdml_, false);
85
86 fWorldPhysVol_ = parser.GetWorldVolume();
87
88 if (silence) {
89 // we created the session and silenced G4
90 // undo that now incase others have use for G4
91 // nullptr => standard (std::cout and std::cerr)
92 G4coutbuf.SetDestination(nullptr);
93 G4cerrbuf.SetDestination(nullptr);
94 }
95}
96
97G4VPhysicalVolume* TrackingGeometry::findDaughterByName(G4VPhysicalVolume* pvol,
98 G4String name) {
99 G4LogicalVolume* lvol = pvol->GetLogicalVolume();
100 for (G4int i = 0; i < lvol->GetNoDaughters(); i++) {
101 G4VPhysicalVolume* fDaughterPhysVol = lvol->GetDaughter(i);
102 std::string dName = fDaughterPhysVol->GetName();
103 if (dName.find(name) != std::string::npos) return fDaughterPhysVol;
104 // if (fDaughterPhysVol->GetName() == name) return fDaughterPhysVol;
105 }
106
107 return nullptr;
108}
109
110void TrackingGeometry::getAllDaughters(G4VPhysicalVolume* pvol) {
111 G4LogicalVolume* lvol = pvol->GetLogicalVolume();
112
113 if (debug_)
114 std::cout << "Checking daughters of ::" << pvol->GetName() << std::endl;
115
116 for (G4int i = 0; i < lvol->GetNoDaughters(); i++) {
117 G4VPhysicalVolume* fDaughterPhysVol = lvol->GetDaughter(i);
118
119 if (debug_) {
120 std::cout << "name::" << fDaughterPhysVol->GetName() << std::endl;
121 std::cout << "pos::" << fDaughterPhysVol->GetTranslation() << std::endl;
122 std::cout << "n_dau::"
123 << fDaughterPhysVol->GetLogicalVolume()->GetNoDaughters()
124 << std::endl;
125 std::cout << "replica::" << fDaughterPhysVol->IsReplicated() << std::endl;
126 std::cout << "copyNR::" << fDaughterPhysVol->GetCopyNo() << std::endl;
127
128 getAllDaughters(fDaughterPhysVol);
129 }
130 }
131}
132
133// Retrieve the layers from a physical volume
134// void TrackingGeometry::getComponentLayer(G4VPhysicalVolume* pvol,
135// std::string layer_name,
136// std::string component_type,
137// std::vector<std::reference_wrapper<G4PhysicalVolume>>
138// & components) {
139
140// G4LogicalVolume* l_vol = pvol->GetLogicalVolume();
141// for (G4int i=0; i<l_vol->GetNoDaughters(); i++) {
142
143// }
144
145//}
146
147void TrackingGeometry::dumpGeometry(const std::string& outputDir,
148 const Acts::GeometryContext& gctx) const {
149 if (!tGeometry_) return;
150
151 if (debug_) {
152 std::cout << __PRETTY_FUNCTION__ << std::endl;
153
154 for (auto const& surfaceId : layer_surface_map_) {
155 std::cout << " " << surfaceId.first << std::endl;
156 std::cout << " Check the surface" << std::endl;
157 // surfaceId.second->toStream(gctx, std::cout);
158 surfaceId.second->toStream(gctx);
159 std::cout << " GeometryID::" << surfaceId.second->geometryId()
160 << std::endl;
161 std::cout << " GeometryID::" << surfaceId.second->geometryId().value()
162 << std::endl;
163 }
164 }
165
166 // Should fail if already exists
167 boost::filesystem::create_directory(outputDir);
168
169 double outputScalor = 1.0;
170 size_t outputPrecision = 6;
171
172 Acts::ObjVisualization3D objVis(outputPrecision, outputScalor);
173 Acts::ViewConfig containerView = Acts::ViewConfig({220, 220, 220});
174 Acts::ViewConfig volumeView = Acts::ViewConfig({220, 220, 0});
175 Acts::ViewConfig sensitiveView = Acts::ViewConfig({0, 180, 240});
176 Acts::ViewConfig passiveView = Acts::ViewConfig({240, 280, 0});
177 Acts::ViewConfig gridView = Acts::ViewConfig({220, 0, 0});
178
179 Acts::GeometryView3D::drawTrackingVolume(
180 objVis, *(tGeometry_->highestTrackingVolume()), gctx, containerView,
181 volumeView, passiveView, sensitiveView, gridView, true, "", ".");
182}
183
184// This method gets the transform from the physical volume to the tracking frame
185Acts::Transform3 TrackingGeometry::GetTransform(const G4VPhysicalVolume& phex,
186 bool toTrackingFrame) const {
187 Acts::Vector3 pos(phex.GetTranslation().x(), phex.GetTranslation().y(),
188 phex.GetTranslation().z());
189
190 Acts::RotationMatrix3 rotation;
191 ConvertG4Rot(phex.GetRotation(), rotation);
192
193 // rotate to the tracking frame
194 if (toTrackingFrame) {
195 pos(0) = phex.GetTranslation().z();
196 pos(1) = phex.GetTranslation().x();
197 pos(2) = phex.GetTranslation().y();
198 rotation = x_rot_ * y_rot_ * rotation;
199 }
200
201 Acts::Translation3 translation(pos);
202
203 Acts::Transform3 transform(translation * rotation);
204
205 return transform;
206}
207
208// This method returns the transformation to the tracker coordinates z->x x->y
209// y->z
210Acts::Transform3 TrackingGeometry::toTracker(
211 const Acts::Transform3& trans) const {
212 Acts::Vector3 pos{trans.translation()(2), trans.translation()(0),
213 trans.translation()(1)};
214
215 Acts::RotationMatrix3 rotation = trans.rotation();
216 rotation = x_rot_ * y_rot_ * rotation;
217
218 Acts::Translation3 translation(pos);
219 Acts::Transform3 transform(translation * rotation);
220
221 return transform;
222}
223
224// Convert rotation
225void TrackingGeometry::ConvertG4Rot(const G4RotationMatrix* g4rot,
226 Acts::RotationMatrix3& rot) const {
227 // If the rotation is the identity then g4rot will be a null ptr.
228 // So then check it and fill rot accordingly
229
230 rot = Acts::RotationMatrix3::Identity();
231
232 if (g4rot) {
233 rot(0, 0) = g4rot->xx();
234 rot(0, 1) = g4rot->xy();
235 rot(0, 2) = g4rot->xz();
236
237 rot(1, 0) = g4rot->yx();
238 rot(1, 1) = g4rot->yy();
239 rot(1, 2) = g4rot->yz();
240
241 rot(2, 0) = g4rot->zx();
242 rot(2, 1) = g4rot->zy();
243 rot(2, 2) = g4rot->zz();
244 }
245}
246
247// Convert translation
248
249Acts::Vector3 TrackingGeometry::ConvertG4Pos(const G4ThreeVector& g4pos) const {
250 Acts::Vector3 trans{g4pos.x(), g4pos.y(), g4pos.z()};
251
252 if (debug_) {
253 std::cout << std::endl;
254 std::cout << "g4pos::" << g4pos << std::endl;
255 std::cout << trans << std::endl;
256 }
257
258 return trans;
259}
260
261void TrackingGeometry::getSurfaces(
262 std::vector<const Acts::Surface*>& surfaces) const {
263 if (!tGeometry_)
264 throw std::runtime_error("TrackingGeometry::getSurfaces tGeometry is null");
265
266 const Acts::TrackingVolume* tVolume = tGeometry_->highestTrackingVolume();
267 if (tVolume->confinedVolumes()) {
268 for (auto volume : tVolume->confinedVolumes()->arrayObjects()) {
269 if (volume->confinedLayers()) {
270 for (const auto& layer : volume->confinedLayers()->arrayObjects()) {
271 if (layer->layerType() == Acts::navigation) continue;
272 for (auto surface : layer->surfaceArray()->surfaces()) {
273 if (surface) {
274 surfaces.push_back(surface);
275
276 } // surface exists
277 } // surfaces
278 } // layers objects
279 } // confined layers
280 } // volumes objects
281 } // confined volumes
282}
283
284void TrackingGeometry::makeLayerSurfacesMap() {
285 std::vector<const Acts::Surface*> surfaces;
286 getSurfaces(surfaces);
287
288 for (auto& surface : surfaces) {
289 // Layers from 1 to 14 - for the tagger
290 // unsigned int layerId = (surface->geometryId().layer() / 2) ; // Old 1
291 // sensor per layer
292
293 unsigned int volumeId = surface->geometryId().volume();
294 unsigned int layerId = (surface->geometryId().layer() /
295 2); // set layer ID from 1 to 7 for the tagger and
296 // from 1 to 6 for the recoil
297 unsigned int sensorId =
298 surface->geometryId().sensitive() -
299 1; // set sensor ID from 0 to 1 for the tagger and from 0 to 9 for the
300 // axial sensors in the back layers of the recoil
301
302 if (debug_)
303 std::cout << "VolumeID " << volumeId << " LayerId " << layerId
304 << " sensorId " << sensorId << std::endl;
305
306 // surface ID = vol * 1000 + ly * 100 + sensor
307 unsigned int surfaceId = volumeId * 1000 + layerId * 100 + sensorId;
308
309 layer_surface_map_[surfaceId] = surface;
310
311 } // surfaces loop
312}
313
314} // namespace tracking::geo
This class throws away all of the messages from Geant4.
TrackingGeometry(const std::string &name, const Acts::GeometryContext &gctx, const std::string &gdml, bool debug)
All classes in the ldmx-sw project use this namespace.
Definition PerfDict.cxx:45
Visualization.