ATLAS Offline Software
Loading...
Searching...
No Matches
TrackingVolumeDisplayer.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6// TrackingVolumeDisplayer.cxx, (c) ATLAS Detector software
8
9// Trk include
12
18#include "TrkSurfaces/Surface.h"
19#include "TrkVolumes/Volume.h"
27// Root
28#include "TString.h"
29#include <sstream>
30// Amg
32
34
35
36// the interface methods
38{
39
40 ATH_MSG_INFO( "initialize()" );
41
42 if (Trk::RecursiveGeometryProcessor::initialize().isFailure()){
43 ATH_MSG_FATAL("Could not initialize base tool. Aborting.");
44 return StatusCode::FAILURE;
45 }
46
47 // open the file for writing
50 // open the file for writing
53 // open the file for writing
56
57 return StatusCode::SUCCESS;
58
59}
60
62{
63 ATH_MSG_INFO( "finalize() successful" );
64
65 // open the file for writing
68 // open the file for writing
71 // open the file for writing
74
75 return StatusCode::SUCCESS;
76}
77
78
79void Trk::TrackingVolumeDisplayer::openFile(std::ofstream& out, const std::string& filename)
80{
81 // open the file
82 out.open(filename.c_str());
83 // write the header
84 out << "{" << '\n';
85 out << "tg = new TCanvas(\"tg\",\"Geometry Shapes\",200,10,700,500);" <<'\n';
86 out << " world = new TBRIK(\"BRIK\",\"BRIK\",\"void\",2,2,2);" << '\n';
87 out << " worldnode = new TNode(\"NODE1\",\"NODE1\",\"BRIK\");" << '\n';
88 out << " worldnode->cd();" << '\n';
89}
90
91
93{
94 out << "worldnode->cd();" << '\n';
95 out << "worldnode->Draw(\"ogl\");" << '\n';
96 out << "tg->Update();" << '\n';
97 out << "}" << '\n';
98 out.close();
99}
100
101
103{
104
105 ATH_MSG_VERBOSE("Writing display information for TrackingVolume.");
106
107 // make a dynamic cast to the CylinderVolumeBounds
108 const Trk::CylinderVolumeBounds* cvol = dynamic_cast<const Trk::CylinderVolumeBounds*>(&tvol.volumeBounds());
109
110 double rMin = 0.;
111 double rMax = 0.;
112 double halfZ = 0.;
113
114 if (cvol) {
115 // from the color code one can determine if its a gap volume
116 // set the boundaries
117 rMin = cvol->innerRadius();
118 rMax = cvol->outerRadius();
119 halfZ = cvol->halflengthZ();
120 }
121
122 // get the name
123 const std::string& volumeName = tvol.volumeName();
124 // write a debug line
125 m_fileVolumeOutput << "// Processing TrackingVolume '" << volumeName << "'. " << '\n';
126 m_fileVolumeOutput << "CylinderVolume" << m_volumeCounter << " = new TTUBE(\"" << volumeName << "\",\"" << volumeName << "\",\"void\",";
127 m_fileVolumeOutput << int(rMin)+1 << "," << int(rMax)-1 << "," << int(halfZ)-1 << ");" << '\n';
128 m_fileVolumeOutput << "CylinderVolume" << m_volumeCounter << "->SetLineColor(" << tvol.colorCode() << ");" << '\n';
129 double zPos = tvol.center().z();
130 m_fileVolumeOutput << "CylinderNode" << m_volumeCounter << " = new TNode(\"" << volumeName << "Node\",\"" << volumeName << "Node\",\"";
131 m_fileVolumeOutput << volumeName << "\"," << 0 << "," << 0 << "," << int(zPos) << ");" << '\n';
132 m_fileVolumeOutput <<'\n';
134
135 // return successful
136 return StatusCode::SUCCESS;
137}
138
139
140StatusCode Trk::TrackingVolumeDisplayer::processNode(const Trk::Layer& lay, size_t) const
141{
142
143 ATH_MSG_VERBOSE("Writing display information for Layer.");
144 // get the identifier
145 int layerIndex = lay.layerIndex().value();
146 int layerIndexStr = (layerIndex < 0) ? (-layerIndex)+1 : layerIndex;
147 // the layer position
148 const Amg::Vector3D& layerPosition = lay.surfaceRepresentation().center();
149 double layerPositionZ = layerPosition.z();
150 // output mode
152 std::stringstream ss;
153 std::string str;
154 ss << "Layer" << layerIndexStr << "_" << m_fileSurfaceOutputName;
155 ss >> str;
157 m_fileSurfaceOutput<<"// Enclosing Volume: "<<lay.enclosingTrackingVolume()->volumeName()<<std::endl;
158 }
159
161 const Trk::SurfaceArray* surfArray = lay.surfaceArray();
162 if (surfArray) {
163 const auto & layerSurfaces = surfArray->arrayObjects();
164 // loop over the surfaces and draw them
165 for (const auto & laySurfIter : layerSurfaces) {
166 if ( laySurfIter && processNode(*laySurfIter).isFailure()){
167 ATH_MSG_FATAL("Failed to call processNode(const Surface& sf) on sub surface. Abort.");
168 return StatusCode::FAILURE;
169 }
170 }
171 }
172 }
175
176 const Trk::Surface& lSurface = lay.surfaceRepresentation();
177 int layerColor = lay.enclosingTrackingVolume() ? lay.enclosingTrackingVolume()->colorCode() : 22;
178
179 // CYLINDER SECTION
180 if (lSurface.type() == Trk::SurfaceType::Cylinder && layerIndex > 0) {
181 // get the Bounds
182 const Trk::CylinderBounds* cylBo = dynamic_cast<const Trk::CylinderBounds*>(&lSurface.bounds());
183 if (!cylBo) {
184 m_fileLayerOutput << "ERROR Cylinder surface without CylinderBounds\n";
185 return StatusCode::FAILURE;
186 }
187 else {
188 // set the boundaries
189 double radius = cylBo->r();
190 double halfZ = cylBo->halflengthZ();
191 m_fileLayerOutput << "Cylinder" << layerIndexStr << " = new TTUBE(\"CylinderLayer";
192 m_fileLayerOutput << layerIndexStr << "\",\"CylinderLayer" << layerIndex << "\",\"void\",";
193 m_fileLayerOutput << int(radius-5) << "," << int(radius+5) << "," << int(halfZ) << ");" << '\n';
194 // get the line color
195 m_fileLayerOutput << "Cylinder" << layerIndexStr << "->SetLineColor(" << layerColor << ");" << '\n';
196 // write the node
197 m_fileLayerOutput <<"Node" << layerIndexStr << " = new TNode(\"CylinderNode" << layerIndex;
198 m_fileLayerOutput << "\",\"CylinderNode" << layerIndexStr << "\",\"CylinderLayer";
199 m_fileLayerOutput << layerIndexStr << "\"," << 0 << "," << 0 << "," << int(layerPositionZ) << ");" << '\n';
200 m_fileLayerOutput <<'\n';
201
202 return StatusCode::SUCCESS;
203 }
204 } else if (lSurface.type() == Trk::SurfaceType::Disc && layerIndex > 0) {
205 // get the Bounds
206 const Trk::DiscBounds* discBo = dynamic_cast<const Trk::DiscBounds*>(&lSurface.bounds());
207 if (!discBo) {
208 m_fileLayerOutput << "ERROR Disc surface without DiscBounds\n";
209 return StatusCode::FAILURE;
210 }
211 else {
212
213 // set the boundaries
214 double rMin = discBo->rMin();
215 double rMax = discBo->rMax();
216
217 m_fileLayerOutput << "Disc" << layerIndexStr << " = new TTUBE(\"DiscLayer" << layerIndexStr << "\",\"DiscLayer" << layerIndex << "\",\"void\",";
218 m_fileLayerOutput << int(rMin+1.) << "," << int(rMax-1.) << ",10);" << '\n';
219 // get the line color
220 m_fileLayerOutput << "Disc" << layerIndexStr << "->SetLineColor(" << layerColor << ");" << '\n';
221 // write the node
222 m_fileLayerOutput << "DiscNode" << layerIndexStr << " = new TNode(\"DiscNode" << layerIndex;
223 m_fileLayerOutput << "\",\"DiscNode" << layerIndexStr << "\",\"DiscLayer";
224 m_fileLayerOutput << layerIndexStr << "\"," << 0 << "," << 0 << "," << int(layerPositionZ) << ");" << '\n';
225 m_fileLayerOutput <<'\n';
226 return StatusCode::SUCCESS;
227 }
228 }
229 return StatusCode::SUCCESS;
230}
231
232
234{
235
237
238 ATH_MSG_VERBOSE("Writing display information for Surface.");
239
240
241 m_fileSurfaceOutput << "// ---------------------- Surface -------------------------------// " << std::endl;
242
243 // surface center
244 double surfX = sf.center().x();
245 double surfY = sf.center().y();
246 double surfZ = sf.center().z();
247 // rotation matrix
248 const Amg::RotationMatrix3D sfRot = sf.transform().rotation();
249
250 // ROOT wants the angles in degrees
251 const double convFac = 180./M_PI;
252 double xPhi = sfRot.col(0).phi()*convFac;
253 double xTheta = sfRot.col(0).theta()*convFac;
254 double yPhi = sfRot.col(1).phi()*convFac;
255 double yTheta = sfRot.col(1).theta()*convFac;
256 double zPhi = sfRot.col(2).phi()*convFac;
257 double zTheta = sfRot.col(2).theta()*convFac;
258
259 // surface
260 TString surfaceString = "Surface_";
261 surfaceString += s_displaySurfaces;
262 TString rotationString = "Rotation_";
263 rotationString += s_displaySurfaces;
264 TString nodeString = "Node";
265 nodeString += s_displaySurfaces;
266 // test version just with planar bounds
267 const Trk::RectangleBounds* recBo = dynamic_cast<const Trk::RectangleBounds*>(&(sf.bounds()));
268 const Trk::TrapezoidBounds* traBo = recBo ? nullptr : dynamic_cast<const Trk::TrapezoidBounds*>(&(sf.bounds()));
269 const Trk::DiscTrapezoidalBounds* disctraBo = (recBo || traBo) ? nullptr : dynamic_cast<const Trk::DiscTrapezoidalBounds*>(&(sf.bounds()));
270 if (recBo) {
271 // it is a rectangle surface
272 double halfX = recBo->halflengthX();
273 double halfY = recBo->halflengthY();
274 // prepare the surface
275 m_fileSurfaceOutput << surfaceString << " = new TBRIK(\""<< surfaceString << "\",\"" << surfaceString<< "\",\"void\",";
276 m_fileSurfaceOutput << halfX << ","<< halfY <<" ,2);" << '\n';
277
278 m_fileSurfaceOutput << surfaceString << "->SetLineColor(80);" << std::endl;
279
280 // the rotation
281 m_fileSurfaceOutput << rotationString << "= new TRotMatrix(\" "<< rotationString << " \",\" " << rotationString << " \", ";
282 m_fileSurfaceOutput << xTheta << "," << xPhi << "," << yTheta << "," << yPhi << ", " << zTheta << "," << zPhi << ");" << std::endl;
283
284 } else if (traBo) {
285 //example
286 //TGTRA gtra = new TGTRA("GTRA","GTRA","void",390,0,0,20,60,40,90,15120,80180,15);
287 // prepare the surface (swap Y and Z)
288 m_fileSurfaceOutput << surfaceString << " = new TTRD1(\""<< surfaceString << "\",\"" << surfaceString<< "\",\"void\",";
289 m_fileSurfaceOutput << traBo->minHalflengthX() << "," << traBo->maxHalflengthX() << ",2," << traBo->halflengthY() << ");" << '\n';
290
291 m_fileSurfaceOutput << surfaceString << "->SetLineColor(80);" << std::endl;
292
293 // the rotation (swap Y and Z)
294 m_fileSurfaceOutput << rotationString << "= new TRotMatrix(\" "<< rotationString << " \",\" " << rotationString << " \", ";
295 m_fileSurfaceOutput << xTheta << "," << xPhi << ", " << zTheta << "," << zPhi << "," << yTheta << "," << yPhi << ");" << std::endl;
296 } else if (disctraBo) {
297 //double rMedium = disctraBo->rCenter();
298 //double Rc = (sf.center()).perp();
299 //double side = (sf.normal()).z();
300 //double stereo = side*2.*asin(Rc/(2.*rMedium));
301 //double avePhi = (side>0) ? disctraBo->averagePhi()+stereo : -disctraBo->averagePhi()+M_PI+stereo;
302
303 double stereo = disctraBo->stereo();
304 double rMedium = disctraBo->rCenter();
305 double avePhi = disctraBo->averagePhi()+stereo;
306
307 surfX = rMedium*cos(avePhi);
308 surfY = rMedium*sin(avePhi);
309 surfZ = (sf.center()).z();
310
311 Amg::RotationMatrix3D rotation;
312 rotation = Amg::AngleAxis3D(0., Amg::Vector3D::UnitX())*
313 Amg::AngleAxis3D(0., Amg::Vector3D::UnitY())*
314 Amg::AngleAxis3D(-M_PI/2.+avePhi-surfZ/fabs(surfZ)*stereo, Amg::Vector3D::UnitZ());
315
316 // ROOT wants the angles in degrees
317 xPhi = rotation.col(0).phi()*convFac;
318 xTheta = rotation.col(0).theta()*convFac;
319 yPhi = rotation.col(1).phi()*convFac;
320 yTheta = rotation.col(1).theta()*convFac;
321 zPhi = rotation.col(2).phi()*convFac;
322 zTheta = rotation.col(2).theta()*convFac;
323
324 //example
325 //TGTRA gtra = new TGTRA("GTRA","GTRA","void",390,0,0,20,60,40,90,15120,80180,15);
326 // prepare the surface (swap Y and Z)
327 m_fileSurfaceOutput << surfaceString << " = new TTRD1(\""<< surfaceString << "\",\"" << surfaceString<< "\",\"void\",";
328 m_fileSurfaceOutput << disctraBo->minHalflengthX() << "," << disctraBo->maxHalflengthX() << ",2," << disctraBo->halflengthY() << ");" << '\n';
329
330 m_fileSurfaceOutput << surfaceString << "->SetLineColor(80);" << std::endl;
331
332 // the rotation (swap Y and Z)
333 m_fileSurfaceOutput << rotationString << "= new TRotMatrix(\" "<< rotationString << " \",\" " << rotationString << " \", ";
334 m_fileSurfaceOutput << xTheta << "," << xPhi << ", " << zTheta << "," << zPhi << "," << yTheta << "," << yPhi << ");" << std::endl;
335 }
336
337 // the node
338 m_fileSurfaceOutput << nodeString << " = new TNode(\"" << nodeString << "\",\"" << nodeString << "\"," << surfaceString;
339 m_fileSurfaceOutput << "," << surfX << ", " << surfY << "," << surfZ << ", " << rotationString << ");" << std::endl;
340
341 return StatusCode::SUCCESS;
342
343}
344
345
347{
348 if (!prop) return 6;
349 // start from 100 and reduce by radiation length
350 int color = 100;
351 double tInX0 = prop->thicknessInX0();
352 // write out a comment line
353 output << "// MaterialProperties : t/X0 = " << tInX0 << std::endl;
354 output << "// zOverAtimesRho : Z/A*rho = " << prop->zOverAtimesRho() << std::endl;
355 // 0 % : --> color code 100
356 // 4 % : --> color code 52
357 color -= int(tInX0 * 1200);
358 return color;
359}
360
361
#define M_PI
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
static Double_t ss
virtual std::span< T *const > arrayObjects()=0
Return all objects of the Array non-const we can still modify the T.
Bounds for a cylindrical Surface.
virtual double r() const override final
This method returns the radius.
double halflengthZ() const
This method returns the halflengthZ.
Bounds for a cylindrical Volume, the decomposeToSurfaces method creates a vector of up to 6 surfaces:
double innerRadius() const
This method returns the inner radius.
double halflengthZ() const
This method returns the halflengthZ.
double outerRadius() const
This method returns the outer radius.
Class to describe the bounds for a planar DiscSurface.
Definition DiscBounds.h:44
double rMax() const
This method returns outer radius.
double rMin() const
This method returns inner radius.
Class to describe the bounds for a planar DiscSurface.
double halflengthY() const
This method returns the halflength in Y (this is Rmax -Rmin).
double averagePhi() const
This method returns the average phi.
double maxHalflengthX() const
This method returns the maximal halflength in X.
double minHalflengthX() const
This method returns the minimal halflength in X.
double stereo() const
This method returns the stereo angle.
double rCenter() const
This method returns the center radius.
int value() const
layerIndex expressed in an integer
Definition LayerIndex.h:71
Base Class for a Detector Layer in the Tracking realm.
Definition Layer.h:72
virtual const Surface & surfaceRepresentation() const =0
Transforms the layer into a Surface representation for extrapolation.
const SurfaceArray * surfaceArray() const
Return the entire SurfaceArray, returns nullptr if no SurfaceArray.
const LayerIndex & layerIndex() const
get the layerIndex
const TrackingVolume * enclosingTrackingVolume() const
get the confining TrackingVolume
Material with information about thickness of material.
Bounds for a rectangular, planar surface.
double halflengthX() const
for consistant naming
double halflengthY() const
for consitant naming
Abstract Base Class for tracking surfaces.
Definition Surface.h:79
virtual constexpr SurfaceType type() const =0
Returns the Surface type to avoid dynamic casts.
virtual const SurfaceBounds & bounds() const =0
Surface Bounds method.
const Amg::Vector3D & center() const
Returns the center position of the Surface.
StatusCode processNode(const TrackingVolume &tvol, size_t level=0) const
Current implementation: write root visualization to file stream.
std::ofstream m_fileVolumeOutput
file output for visualization action
static int s_displaySurfaces
static surface counter
static void openFile(std::ofstream &output, const std::string &filename)
File handling: open + write header.
std::ofstream m_fileSurfaceOutput
file output for visualization action
Gaudi::Property< bool > m_fileVolumeOutputMode
StatusCode finalize()
AlgTool finalize method.
std::ofstream m_fileLayerOutput
file output for visualization action
Gaudi::Property< std::string > m_fileVolumeOutputName
Gaudi::Property< bool > m_fileSurfaceOutputMode
static int colorCodeFromMaterial(const Trk::MaterialProperties *prop, std::ofstream &output)
calculate the color code from the Material
Gaudi::Property< bool > m_fileLayerOutputMode
Gaudi::Property< bool > m_fileSurfaceOutputSplit
Gaudi::Property< std::string > m_fileLayerOutputName
Gaudi::Property< std::string > m_fileSurfaceOutputName
static void closeFile(std::ofstream &output)
File handling: write footer + close.
StatusCode initialize()
AlgTool initialize method.
Full Volume description used in Tracking, it inherits from Volume to get the geometrical structure,...
const std::string & volumeName() const
Returns the VolumeName - for debug reason, might be depreciated later.
unsigned int colorCode() const
Get the color code.
Bounds for a trapezoidal, planar Surface.
double halflengthY() const
This method returns the halflength in Y (second coordinate of local surface frame).
double minHalflengthX() const
This method returns the minimal halflength in X (first coordinate of local surface frame).
double maxHalflengthX() const
This method returns the maximal halflength in X (first coordinate of local surface frame).
const Amg::Vector3D & center() const
returns the center of the volume
Definition Volume.h:90
const VolumeBounds & volumeBounds() const
returns the volumeBounds()
Definition Volume.h:96
Eigen::AngleAxisd AngleAxis3D
Eigen::Matrix< double, 3, 3 > RotationMatrix3D
Eigen::Matrix< double, 3, 1 > Vector3D
BinnedArray< Surface > SurfaceArray
Definition Layer.h:40