ATLAS Offline Software
Loading...
Searching...
No Matches
TrackingVolumeDisplayer.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 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// constructor
36Trk::TrackingVolumeDisplayer::TrackingVolumeDisplayer(const std::string& t, const std::string& n, const IInterface* p) :
39 m_fileVolumeOutputName("TrackingGeometryVolumeDisplay.C"),
41 m_fileLayerOutputName("TrackingGeometryLayerDisplay.C"),
43 m_fileSurfaceOutputName("TrackingGeometrySurfaceDisplay.C"),
46{
47 // set name and output type
48 declareProperty("TrackingVolumeOutputFile", m_fileVolumeOutputName);
49 declareProperty("TrackingVolumeOutput", m_fileVolumeOutputMode);
50 declareProperty("LayerOutputFile", m_fileLayerOutputName);
52 declareProperty("SurfaceOutputFile", m_fileSurfaceOutputName);
54 declareProperty("SurfaceOutputSplit", m_fileSurfaceOutputSplit);
55}
56
57// destructor
59= default;
60
61
62// the interface methods
64{
65
66 ATH_MSG_INFO( "initialize()" );
67
69 ATH_MSG_FATAL("Could not initialize base tool. Aborting.");
70 return StatusCode::FAILURE;
71 }
72
73 // open the file for writing
76 // open the file for writing
79 // open the file for writing
82
83 return StatusCode::SUCCESS;
84
85}
86
88{
89 ATH_MSG_INFO( "finalize() successful" );
90
91 // open the file for writing
94 // open the file for writing
97 // open the file for writing
100
101 return StatusCode::SUCCESS;
102}
103
104
105void Trk::TrackingVolumeDisplayer::openFile(std::ofstream& out, const std::string& filename)
106{
107 // open the file
108 out.open(filename.c_str());
109 // write the header
110 out << "{" << '\n';
111 out << "tg = new TCanvas(\"tg\",\"Geometry Shapes\",200,10,700,500);" <<'\n';
112 out << " world = new TBRIK(\"BRIK\",\"BRIK\",\"void\",2,2,2);" << '\n';
113 out << " worldnode = new TNode(\"NODE1\",\"NODE1\",\"BRIK\");" << '\n';
114 out << " worldnode->cd();" << '\n';
115}
116
117
119{
120 out << "worldnode->cd();" << '\n';
121 out << "worldnode->Draw(\"ogl\");" << '\n';
122 out << "tg->Update();" << '\n';
123 out << "}" << '\n';
124 out.close();
125}
126
127
129{
130
131 ATH_MSG_VERBOSE("Writing display information for TrackingVolume.");
132
133 // make a dynamic cast to the CylinderVolumeBounds
134 const Trk::CylinderVolumeBounds* cvol = dynamic_cast<const Trk::CylinderVolumeBounds*>(&tvol.volumeBounds());
135
136 double rMin = 0.;
137 double rMax = 0.;
138 double halfZ = 0.;
139
140 if (cvol) {
141 // from the color code one can determine if its a gap volume
142 // set the boundaries
143 rMin = cvol->innerRadius();
144 rMax = cvol->outerRadius();
145 halfZ = cvol->halflengthZ();
146 }
147
148 // get the name
149 const std::string& volumeName = tvol.volumeName();
150 // write a debug line
151 m_fileVolumeOutput << "// Processing TrackingVolume '" << volumeName << "'. " << '\n';
152 m_fileVolumeOutput << "CylinderVolume" << m_volumeCounter << " = new TTUBE(\"" << volumeName << "\",\"" << volumeName << "\",\"void\",";
153 m_fileVolumeOutput << int(rMin)+1 << "," << int(rMax)-1 << "," << int(halfZ)-1 << ");" << '\n';
154 m_fileVolumeOutput << "CylinderVolume" << m_volumeCounter << "->SetLineColor(" << tvol.colorCode() << ");" << '\n';
155 double zPos = tvol.center().z();
156 m_fileVolumeOutput << "CylinderNode" << m_volumeCounter << " = new TNode(\"" << volumeName << "Node\",\"" << volumeName << "Node\",\"";
157 m_fileVolumeOutput << volumeName << "\"," << 0 << "," << 0 << "," << int(zPos) << ");" << '\n';
158 m_fileVolumeOutput <<'\n';
160
161 // return successful
162 return StatusCode::SUCCESS;
163}
164
165
166StatusCode Trk::TrackingVolumeDisplayer::processNode(const Trk::Layer& lay, size_t) const
167{
168
169 ATH_MSG_VERBOSE("Writing display information for Layer.");
170 // get the identifier
171 int layerIndex = lay.layerIndex().value();
172 int layerIndexStr = (layerIndex < 0) ? (-layerIndex)+1 : layerIndex;
173 // the layer position
174 const Amg::Vector3D& layerPosition = lay.surfaceRepresentation().center();
175 double layerPositionZ = layerPosition.z();
176 // output mode
178 std::stringstream ss;
179 std::string str;
180 ss << "Layer" << layerIndexStr << "_" << m_fileSurfaceOutputName;
181 ss >> str;
183 m_fileSurfaceOutput<<"// Enclosing Volume: "<<lay.enclosingTrackingVolume()->volumeName()<<std::endl;
184 }
185
187 const Trk::SurfaceArray* surfArray = lay.surfaceArray();
188 if (surfArray) {
189 const auto & layerSurfaces = surfArray->arrayObjects();
190 // loop over the surfaces and draw them
191 for (const auto & laySurfIter : layerSurfaces) {
192 if ( laySurfIter && processNode(*laySurfIter).isFailure()){
193 ATH_MSG_FATAL("Failed to call processNode(const Surface& sf) on sub surface. Abort.");
194 return StatusCode::FAILURE;
195 }
196 }
197 }
198 }
201
202 const Trk::Surface& lSurface = lay.surfaceRepresentation();
203 int layerColor = lay.enclosingTrackingVolume() ? lay.enclosingTrackingVolume()->colorCode() : 22;
204
205 // CYLINDER SECTION
206 if (lSurface.type() == Trk::SurfaceType::Cylinder && layerIndex > 0) {
207 // get the Bounds
208 const Trk::CylinderBounds* cylBo = dynamic_cast<const Trk::CylinderBounds*>(&lSurface.bounds());
209 if (!cylBo) {
210 m_fileLayerOutput << "ERROR Cylinder surface without CylinderBounds\n";
211 return StatusCode::FAILURE;
212 }
213 else {
214 // set the boundaries
215 double radius = cylBo->r();
216 double halfZ = cylBo->halflengthZ();
217 m_fileLayerOutput << "Cylinder" << layerIndexStr << " = new TTUBE(\"CylinderLayer";
218 m_fileLayerOutput << layerIndexStr << "\",\"CylinderLayer" << layerIndex << "\",\"void\",";
219 m_fileLayerOutput << int(radius-5) << "," << int(radius+5) << "," << int(halfZ) << ");" << '\n';
220 // get the line color
221 m_fileLayerOutput << "Cylinder" << layerIndexStr << "->SetLineColor(" << layerColor << ");" << '\n';
222 // write the node
223 m_fileLayerOutput <<"Node" << layerIndexStr << " = new TNode(\"CylinderNode" << layerIndex;
224 m_fileLayerOutput << "\",\"CylinderNode" << layerIndexStr << "\",\"CylinderLayer";
225 m_fileLayerOutput << layerIndexStr << "\"," << 0 << "," << 0 << "," << int(layerPositionZ) << ");" << '\n';
226 m_fileLayerOutput <<'\n';
227
228 return StatusCode::SUCCESS;
229 }
230 } else if (lSurface.type() == Trk::SurfaceType::Disc && layerIndex > 0) {
231 // get the Bounds
232 const Trk::DiscBounds* discBo = dynamic_cast<const Trk::DiscBounds*>(&lSurface.bounds());
233 if (!discBo) {
234 m_fileLayerOutput << "ERROR Disc surface without DiscBounds\n";
235 return StatusCode::FAILURE;
236 }
237 else {
238
239 // set the boundaries
240 double rMin = discBo->rMin();
241 double rMax = discBo->rMax();
242
243 m_fileLayerOutput << "Disc" << layerIndexStr << " = new TTUBE(\"DiscLayer" << layerIndexStr << "\",\"DiscLayer" << layerIndex << "\",\"void\",";
244 m_fileLayerOutput << int(rMin+1.) << "," << int(rMax-1.) << ",10);" << '\n';
245 // get the line color
246 m_fileLayerOutput << "Disc" << layerIndexStr << "->SetLineColor(" << layerColor << ");" << '\n';
247 // write the node
248 m_fileLayerOutput << "DiscNode" << layerIndexStr << " = new TNode(\"DiscNode" << layerIndex;
249 m_fileLayerOutput << "\",\"DiscNode" << layerIndexStr << "\",\"DiscLayer";
250 m_fileLayerOutput << layerIndexStr << "\"," << 0 << "," << 0 << "," << int(layerPositionZ) << ");" << '\n';
251 m_fileLayerOutput <<'\n';
252 return StatusCode::SUCCESS;
253 }
254 }
255 return StatusCode::SUCCESS;
256}
257
258
260{
261
263
264 ATH_MSG_VERBOSE("Writing display information for Surface.");
265
266
267 m_fileSurfaceOutput << "// ---------------------- Surface -------------------------------// " << std::endl;
268
269 // surface center
270 double surfX = sf.center().x();
271 double surfY = sf.center().y();
272 double surfZ = sf.center().z();
273 // rotation matrix
274 const Amg::RotationMatrix3D sfRot = sf.transform().rotation();
275
276 // ROOT wants the angles in degrees
277 const double convFac = 180./M_PI;
278 double xPhi = sfRot.col(0).phi()*convFac;
279 double xTheta = sfRot.col(0).theta()*convFac;
280 double yPhi = sfRot.col(1).phi()*convFac;
281 double yTheta = sfRot.col(1).theta()*convFac;
282 double zPhi = sfRot.col(2).phi()*convFac;
283 double zTheta = sfRot.col(2).theta()*convFac;
284
285 // surface
286 TString surfaceString = "Surface_";
287 surfaceString += s_displaySurfaces;
288 TString rotationString = "Rotation_";
289 rotationString += s_displaySurfaces;
290 TString nodeString = "Node";
291 nodeString += s_displaySurfaces;
292 // test version just with planar bounds
293 const Trk::RectangleBounds* recBo = dynamic_cast<const Trk::RectangleBounds*>(&(sf.bounds()));
294 const Trk::TrapezoidBounds* traBo = recBo ? nullptr : dynamic_cast<const Trk::TrapezoidBounds*>(&(sf.bounds()));
295 const Trk::DiscTrapezoidalBounds* disctraBo = (recBo || traBo) ? nullptr : dynamic_cast<const Trk::DiscTrapezoidalBounds*>(&(sf.bounds()));
296 if (recBo) {
297 // it is a rectangle surface
298 double halfX = recBo->halflengthX();
299 double halfY = recBo->halflengthY();
300 // prepare the surface
301 m_fileSurfaceOutput << surfaceString << " = new TBRIK(\""<< surfaceString << "\",\"" << surfaceString<< "\",\"void\",";
302 m_fileSurfaceOutput << halfX << ","<< halfY <<" ,2);" << '\n';
303
304 m_fileSurfaceOutput << surfaceString << "->SetLineColor(80);" << std::endl;
305
306 // the rotation
307 m_fileSurfaceOutput << rotationString << "= new TRotMatrix(\" "<< rotationString << " \",\" " << rotationString << " \", ";
308 m_fileSurfaceOutput << xTheta << "," << xPhi << "," << yTheta << "," << yPhi << ", " << zTheta << "," << zPhi << ");" << std::endl;
309
310 } else if (traBo) {
311 //example
312 //TGTRA gtra = new TGTRA("GTRA","GTRA","void",390,0,0,20,60,40,90,15120,80180,15);
313 // prepare the surface (swap Y and Z)
314 m_fileSurfaceOutput << surfaceString << " = new TTRD1(\""<< surfaceString << "\",\"" << surfaceString<< "\",\"void\",";
315 m_fileSurfaceOutput << traBo->minHalflengthX() << "," << traBo->maxHalflengthX() << ",2," << traBo->halflengthY() << ");" << '\n';
316
317 m_fileSurfaceOutput << surfaceString << "->SetLineColor(80);" << std::endl;
318
319 // the rotation (swap Y and Z)
320 m_fileSurfaceOutput << rotationString << "= new TRotMatrix(\" "<< rotationString << " \",\" " << rotationString << " \", ";
321 m_fileSurfaceOutput << xTheta << "," << xPhi << ", " << zTheta << "," << zPhi << "," << yTheta << "," << yPhi << ");" << std::endl;
322 } else if (disctraBo) {
323 //double rMedium = disctraBo->rCenter();
324 //double Rc = (sf.center()).perp();
325 //double side = (sf.normal()).z();
326 //double stereo = side*2.*asin(Rc/(2.*rMedium));
327 //double avePhi = (side>0) ? disctraBo->averagePhi()+stereo : -disctraBo->averagePhi()+M_PI+stereo;
328
329 double stereo = disctraBo->stereo();
330 double rMedium = disctraBo->rCenter();
331 double avePhi = disctraBo->averagePhi()+stereo;
332
333 surfX = rMedium*cos(avePhi);
334 surfY = rMedium*sin(avePhi);
335 surfZ = (sf.center()).z();
336
337 Amg::RotationMatrix3D rotation;
338 rotation = Amg::AngleAxis3D(0., Amg::Vector3D::UnitX())*
339 Amg::AngleAxis3D(0., Amg::Vector3D::UnitY())*
340 Amg::AngleAxis3D(-M_PI/2.+avePhi-surfZ/fabs(surfZ)*stereo, Amg::Vector3D::UnitZ());
341
342 // ROOT wants the angles in degrees
343 xPhi = rotation.col(0).phi()*convFac;
344 xTheta = rotation.col(0).theta()*convFac;
345 yPhi = rotation.col(1).phi()*convFac;
346 yTheta = rotation.col(1).theta()*convFac;
347 zPhi = rotation.col(2).phi()*convFac;
348 zTheta = rotation.col(2).theta()*convFac;
349
350 //example
351 //TGTRA gtra = new TGTRA("GTRA","GTRA","void",390,0,0,20,60,40,90,15120,80180,15);
352 // prepare the surface (swap Y and Z)
353 m_fileSurfaceOutput << surfaceString << " = new TTRD1(\""<< surfaceString << "\",\"" << surfaceString<< "\",\"void\",";
354 m_fileSurfaceOutput << disctraBo->minHalflengthX() << "," << disctraBo->maxHalflengthX() << ",2," << disctraBo->halflengthY() << ");" << '\n';
355
356 m_fileSurfaceOutput << surfaceString << "->SetLineColor(80);" << std::endl;
357
358 // the rotation (swap Y and Z)
359 m_fileSurfaceOutput << rotationString << "= new TRotMatrix(\" "<< rotationString << " \",\" " << rotationString << " \", ";
360 m_fileSurfaceOutput << xTheta << "," << xPhi << ", " << zTheta << "," << zPhi << "," << yTheta << "," << yPhi << ");" << std::endl;
361 }
362
363 // the node
364 m_fileSurfaceOutput << nodeString << " = new TNode(\"" << nodeString << "\",\"" << nodeString << "\"," << surfaceString;
365 m_fileSurfaceOutput << "," << surfX << ", " << surfY << "," << surfZ << ", " << rotationString << ");" << std::endl;
366
367 return StatusCode::SUCCESS;
368
369}
370
371
373{
374 if (!prop) return 6;
375 // start from 100 and reduce by radiation length
376 int color = 100;
377 double tInX0 = prop->thicknessInX0();
378 // write out a comment line
379 output << "// MaterialProperties : t/X0 = " << tInX0 << std::endl;
380 output << "// zOverAtimesRho : Z/A*rho = " << prop->zOverAtimesRho() << std::endl;
381 // 0 % : --> color code 100
382 // 4 % : --> color code 52
383 color -= int(tInX0 * 1200);
384 return color;
385}
386
387
#define M_PI
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
static Double_t ss
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
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.
float thicknessInX0() const
Return the radiationlength fraction.
float zOverAtimesRho() const
Return the .
Bounds for a rectangular, planar surface.
double halflengthX() const
for consistant naming
double halflengthY() const
for consitant naming
RecursiveGeometryProcessor(const std::string &, const std::string &, const IInterface *)
Constructor.
StatusCode initialize()
AlgTool initialize method.
Abstract Base Class for tracking surfaces.
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
virtual ~TrackingVolumeDisplayer()
Destructor.
StatusCode finalize()
AlgTool finalize method.
std::ofstream m_fileLayerOutput
file output for visualization action
TrackingVolumeDisplayer(const std::string &, const std::string &, const IInterface *)
Constructor.
bool m_fileSurfaceOutputSplit
use one file for each layer
static int colorCodeFromMaterial(const Trk::MaterialProperties *prop, std::ofstream &output)
calculate the color code from the Material
std::string m_fileSurfaceOutputName
file name for visualization action
std::string m_fileLayerOutputName
file name for visualization action
static void closeFile(std::ofstream &output)
File handling: write footer + close.
StatusCode initialize()
AlgTool initialize method.
std::string m_fileVolumeOutputName
file name for visualization action
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
Ensure that the ATLAS eigen extensions are properly loaded.
BinnedArray< Surface > SurfaceArray
Definition Layer.h:40