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