CMS 3D CMS Logo

MaterialAccountingGroup.cc
Go to the documentation of this file.
1 #include <sstream>
2 #include <iomanip>
3 #include <string>
4 #include <stdexcept>
5 
6 #include <TFile.h>
7 #include <TH1F.h>
8 #include <TProfile.h>
9 #include <TCanvas.h>
10 #include <TFrame.h>
11 
19 
20 double const MaterialAccountingGroup::s_tolerance = 0.01; // 100um should be small enough that no elements from different layers/groups are so close
21 
23  m_name( name ),
24  m_elements(),
25  m_boundingbox(),
26  m_accounting(),
27  m_errors(),
28  m_tracks( 0 ),
29  m_counted( false ),
30  m_file( 0 )
31 {
32  // retrieve the elements from DDD
33  DDSpecificsMatchesValueFilter filter{DDValue("TrackingMaterialGroup", name)};
34  DDFilteredView fv( geometry,filter );
35  LogTrace("MaterialAccountingGroup") << "Elements within: " << name << std::endl;
36  while (fv.next()) {
37  // DD3Vector and DDTranslation are the same type as math::XYZVector
38  math::XYZVector position = fv.translation() / 10.; // mm -> cm
39  LogTrace("MaterialAccountingGroup") << "Adding element at(r,z): ("
40  << GlobalPoint(position.x(), position.y(), position.z()).perp()
41  << ", " << GlobalPoint(position.x(), position.y(), position.z()).z()
42  << ") cm" << std::endl;
43  LogTrace("MaterialAccountingGroup") << "Name of added element: "
44  << fv.logicalPart().toString() << std::endl;
45  m_elements.push_back( GlobalPoint(position.x(), position.y(), position.z()) );
46  }
47 
48  // grow the bounding box
49  for (unsigned int i = 0; i < m_elements.size(); ++i) {
51  }
53  LogTrace("MaterialAccountingGroup") << "Final BBox r_range: "
54  << m_boundingbox.range_r().first << ", " << m_boundingbox.range_r().second
55  << std::endl
56  << "Final BBox z_range: "
57  << m_boundingbox.range_z().first << ", " << m_boundingbox.range_z().second
58  << std::endl;
59 
60  // initialize the histograms
61  m_dedx_spectrum = new TH1F((m_name + "_dedx_spectrum").c_str(), "Energy loss spectrum", 1000, 0, 1);
62  m_radlen_spectrum = new TH1F((m_name + "_radlen_spectrum").c_str(), "Radiation lengths spectrum", 1000, 0, 1);
63  m_dedx_vs_eta = new TProfile((m_name + "_dedx_vs_eta").c_str(), "Energy loss vs. eta", 600, -3, 3);
64  m_dedx_vs_z = new TProfile((m_name + "_dedx_vs_z").c_str(), "Energy loss vs. Z", 6000, -300, 300);
65  m_dedx_vs_r = new TProfile((m_name + "_dedx_vs_r").c_str(), "Energy loss vs. R", 1200, 0, 120);
66  m_radlen_vs_eta = new TProfile((m_name + "_radlen_vs_eta").c_str(), "Radiation lengths vs. eta", 600, -3, 3);
67  m_radlen_vs_z = new TProfile((m_name + "_radlen_vs_z").c_str(), "Radiation lengths vs. Z", 6000, -300, 300);
68  m_radlen_vs_r = new TProfile((m_name + "_radlen_vs_r").c_str(), "Radiation lengths vs. R", 1200, 0, 120);
69  m_dedx_spectrum->SetDirectory( 0 );
70  m_radlen_spectrum->SetDirectory( 0 );
71  m_dedx_vs_eta->SetDirectory( 0 );
72  m_dedx_vs_z->SetDirectory( 0 );
73  m_dedx_vs_r->SetDirectory( 0 );
74  m_radlen_vs_eta->SetDirectory( 0 );
75  m_radlen_vs_z->SetDirectory( 0 );
76  m_radlen_vs_r->SetDirectory( 0 );
77 }
78 
80 {
81  delete m_dedx_spectrum;
82  delete m_dedx_vs_eta;
83  delete m_dedx_vs_z;
84  delete m_dedx_vs_r;
85  delete m_radlen_spectrum;
86  delete m_radlen_vs_eta;
87  delete m_radlen_vs_z;
88  delete m_radlen_vs_r;
89 }
90 
91 // TODO the inner check could be sped up in many ways
92 // (sorting the m_elements, partitioning the bounding box, ...)
93 // but is it worth?
94 // especially with the segmentation of the layers ?
96 {
97  const GlobalPoint & position = detector.position();
98  // first check to see if the point is inside the bounding box
99  LogTrace("MaterialAccountingGroup") << "Testing position: (x, y, z, r) = "
100  << position.x() << ", " << position.y()
101  << ", " << position.z() << ", " << position.perp()
102  << std::endl;
103  if (not m_boundingbox.inside(position.perp(), position.z())) {
104  LogTrace("MaterialAccountingGroup") << "r outside of: ("
105  << m_boundingbox.range_r().first << ", "
106  << m_boundingbox.range_r().second
107  << "), Z ouside of: ("
108  << m_boundingbox.range_z().first << ", "
109  << m_boundingbox.range_z().second << ")" << std::endl;
110  return false;
111  } else {
112  // now check if the point is actually close enough to any element
113  LogTrace("MaterialAccountingGroup") << "r within: ("
114  << m_boundingbox.range_r().first << ", "
115  << m_boundingbox.range_r().second
116  << "), Z within: ("
117  << m_boundingbox.range_z().first << ", "
118  << m_boundingbox.range_z().second << ")" << std::endl;
119  for (unsigned int i = 0; i < m_elements.size(); ++i) {
120  LogTrace("MaterialAccountingGroup") << "Closest testing agains(x, y, z, r): ("
121  << m_elements[i].x() << ", " << m_elements[i].y()
122  << ", " << m_elements[i].z() << ", " << m_elements[i].perp() << ") --> "
123  << (position - m_elements[i]).mag()
124  << " vs tolerance: " << s_tolerance
125  << std::endl;
126  if ((position - m_elements[i]).mag2() < (s_tolerance * s_tolerance))
127  return true;
128  }
129  return false;
130  }
131 }
132 
134 {
135  if (not inside(detector))
136  return false;
137 
138  // multiple hits in the same layer (overlaps, etc.) from a single track still count as one for averaging,
139  // since the energy deposits from the track have been already split between the different detectors
140  m_buffer += detector.material();
141  m_counted = true;
142 
143  return true;
144 }
145 
147  // add a detector
148  if (m_counted) {
151  ++m_tracks;
152 
153  GlobalPoint average( (m_buffer.in().x() + m_buffer.out().x()) / 2.,
154  (m_buffer.in().y() + m_buffer.out().y()) / 2.,
155  (m_buffer.in().z() + m_buffer.out().z()) / 2. );
156  m_dedx_spectrum->Fill( m_buffer.energyLoss() );
157  m_radlen_spectrum->Fill( m_buffer.radiationLengths() );
158  m_dedx_vs_eta->Fill( average.eta(), m_buffer.energyLoss(), 1. );
159  m_dedx_vs_z->Fill( average.z(), m_buffer.energyLoss(), 1. );
160  m_dedx_vs_r->Fill( average.perp(), m_buffer.energyLoss(), 1. );
161  m_radlen_vs_eta->Fill( average.eta(), m_buffer.radiationLengths(), 1. );
162  m_radlen_vs_z->Fill( average.z(), m_buffer.radiationLengths(), 1. );
163  m_radlen_vs_r->Fill( average.perp(), m_buffer.radiationLengths(), 1. );
164  }
165  m_counted = false;
167 }
168 
170 {
171  TCanvas canvas(name.c_str(), plot->GetTitle(), 1280, 1024);
172  plot->SetFillColor(15); // grey
173  plot->SetLineColor(1); // black
174  plot->Draw("c e");
175  canvas.GetFrame()->SetFillColor(kWhite);
176  canvas.Draw();
177  canvas.SaveAs((name + ".png").c_str(), "");
178 
179  // store te plot into m_file
180  plot->SetDirectory(m_file);
181 }
182 
184 {
185  // Nota Bene:
186  // these "line" plots are not deleted explicitly since
187  // - deleting them before saving them to a TFile will not save them
188  // - deleting them after the TFile they're stored into results in a SEGV
189  // ROOT is probably "taking care" (read: messing things up) somehow...
190  TH1F * line = new TH1F((name + "_par").c_str(), "Parametrization", 1, plot->GetXaxis()->GetXmin(), plot->GetXaxis()->GetXmax());
191  line->SetBinContent(1, average);
192 
193  TCanvas canvas(name.c_str(), plot->GetTitle(), 1280, 1024);
194  plot->SetFillColor(15); // grey
195  plot->SetLineColor(1); // black
196  plot->SetLineWidth(2);
197  plot->Draw("c e6");
198  line->SetLineColor(2); // red
199  line->SetLineWidth(2);
200  line->Draw("same");
201  canvas.GetFrame()->SetFillColor(kWhite);
202  canvas.Draw();
203  canvas.SaveAs((name + ".png").c_str(), "");
204 
205  // store te plots into m_file
206  plot->SetDirectory(m_file);
207  line->SetDirectory(m_file);
208 }
209 
212 {
213  std::stringstream out;
214  out << std::setw(48) << std::left << m_name << std::right << std::fixed;;
215  out << "BBox: " << std::setprecision(1) << std::setw(6) << m_boundingbox.range_z().first << " < Z < " << std::setprecision(1) << std::setw(6) << m_boundingbox.range_z().second;
216  out << ", " << std::setprecision(1) << std::setw(5) << m_boundingbox.range_r().first << " < R < " << std::setprecision(1) << std::setw(5) << m_boundingbox.range_r().second;
217  out << " Elements: " << std::setw(6) << m_elements.size();
218  return out.str();
219 }
220 
221 
223 {
224  m_file = new TFile((m_name + ".root").c_str(), "RECREATE");
225  savePlot(m_dedx_spectrum, m_name + "_dedx_spectrum");
226  savePlot(m_radlen_spectrum, m_name + "_radlen_spectrum");
227  savePlot(m_dedx_vs_eta, averageEnergyLoss(), m_name + "_dedx_vs_eta");
228  savePlot(m_dedx_vs_z, averageEnergyLoss(), m_name + "_dedx_vs_z");
229  savePlot(m_dedx_vs_r, averageEnergyLoss(), m_name + "_dedx_vs_r");
230  savePlot(m_radlen_vs_eta, averageRadiationLengths(), m_name + "_radlen_vs_eta");
233  m_file->Write();
234  m_file->Close();
235 
236  delete m_file;
237 }
const DDLogicalPart & logicalPart() const
The logical-part of the current node in the filtered-view.
MaterialAccountingGroup(const std::string &name, const DDCompactView &geometry)
explicit constructors
T perp() const
Definition: PV3DBase.h:72
double averageRadiationLengths(void) const
return the average normalized number of radiation lengths
void endOfTrack(void)
commit the buffer and reset the "already hit by this track" flag
MaterialAccountingStep m_errors
MaterialAccountingStep m_buffer
T mag() const
The vector magnitude. Equivalent to sqrt(vec.mag2())
std::vector< GlobalPoint > m_elements
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
T y() const
Definition: PV3DBase.h:63
std::pair< double, double > range_r() const
std::string info(void) const
get some infos
type of data representation of DDCompactView
Definition: DDCompactView.h:90
double averageEnergyLoss(void) const
return the average normalized energy loss density factor for Bethe-Bloch
bool next()
set current node to the next node in the filtered tree
void savePlot(TH1F *plot, const std::string &name)
T z() const
Definition: PV3DBase.h:64
MaterialAccountingStep average(void) const
return the average normalized material accounting informations
std::pair< double, double > range_z() const
#define LogTrace(id)
const MaterialAccountingStep & material() const
const std::string & name(void) const
get the layer name
std::string toString() const
Definition: DDBase.h:82
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:30
void savePlots(void)
save the plots
const GlobalPoint & position() const
T eta() const
Definition: PV3DBase.h:76
T perp() const
Magnitude of transverse component.
bool inside(double r, double z) const
static int position[264][3]
Definition: ReadPGInfo.cc:509
def canvas(sub, attr)
Definition: svgfig.py:481
bool addDetector(const MaterialAccountingDetector &detector)
buffer material from a detector, if the detector is inside the DetLayer bounds
~MaterialAccountingGroup(void)
destructor
const DDTranslation & translation() const
The absolute translation of the current node.
MaterialAccountingStep m_accounting
T x() const
Definition: PV3DBase.h:62
bool inside(const MaterialAccountingDetector &detector) const
check if detector is inside any part of this layer