CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
DTGeometryValidate.cc
Go to the documentation of this file.
7 
11 
13 
16 
17 #include <TFile.h>
18 #include <TH1.h>
19 
20 #include <cmath>
21 #include <limits>
22 #include <string>
23 #include <type_traits>
24 #include <algorithm>
25 
26 using namespace std;
27 
28 template <class T>
29 typename enable_if<!numeric_limits<T>::is_integer, bool>::type almost_equal(T x, T y, int ulp) {
30  // the machine epsilon has to be scaled to the magnitude of the values used
31  // and multiplied by the desired precision in ULPs (units in the last place)
32  return abs(x - y) <= numeric_limits<T>::epsilon() * abs(x + y) * ulp
33  // unless the result is subnormal
34  || abs(x - y) < numeric_limits<T>::min();
35 }
36 
37 using namespace edm;
38 
39 class DTGeometryValidate : public one::EDAnalyzer<> {
40 public:
41  explicit DTGeometryValidate(const ParameterSet&);
42  ~DTGeometryValidate() override {}
43 
44 private:
45  void beginJob() override;
46  void analyze(const edm::Event&, const edm::EventSetup&) override;
47  void endJob() override;
48 
49  void validateDTChamberGeometry();
50  void validateDTLayerGeometry();
51 
52  void compareTransform(const GlobalPoint&, const TGeoMatrix*);
53  void compareShape(const GeomDet*, const float*);
54 
55  float getDistance(const GlobalPoint&, const GlobalPoint&);
56  float getDiff(const float, const float);
57 
58  void makeHistograms(const char*);
59  void makeHistogram(const string&, vector<float>&);
60 
61  void clearData() {
62  globalDistances_.clear();
63  topWidths_.clear();
64  bottomWidths_.clear();
65  lengths_.clear();
66  thicknesses_.clear();
67  }
68 
72  TFile* outFile_;
73  vector<float> globalDistances_;
74  vector<float> topWidths_;
75  vector<float> bottomWidths_;
76  vector<float> lengths_;
77  vector<float> thicknesses_;
78  string infileName_;
79  string outfileName_;
81 };
82 
84  : dtGeometryToken_{esConsumes<DTGeometry, MuonGeometryRecord>(edm::ESInputTag{})},
86  iConfig.getUntrackedParameter<string>("infileName", "Geometry/DTGeometryBuilder/data/cmsRecoGeom-2021.root")),
87  outfileName_(iConfig.getUntrackedParameter<string>("outfileName", "validateDTGeometry.root")),
88  tolerance_(iConfig.getUntrackedParameter<int>("tolerance", 6)) {
90  fwGeometry_.loadMap(fp.fullPath().c_str());
91  outFile_ = TFile::Open(outfileName_.c_str(), "RECREATE");
92 }
93 
96 
97  if (dtGeometry_.isValid()) {
98  LogVerbatim("DTGeometry") << "Validating DT chamber geometry";
100  LogVerbatim("DTGeometry") << "Validating DT layer geometry";
102  } else
103  LogVerbatim("DTGeometry") << "Invalid DT geometry";
104 }
105 
107  clearData();
108 
109  for (auto const& it : dtGeometry_->chambers()) {
110  DTChamberId chId = it->id();
111  GlobalPoint gp = it->surface().toGlobal(LocalPoint(0.0, 0.0, 0.0));
112 
113  const TGeoMatrix* matrix = fwGeometry_.getMatrix(chId.rawId());
114 
115  if (!matrix) {
116  LogVerbatim("DTGeometry") << "Failed to get matrix of DT chamber with detid: " << chId.rawId();
117  continue;
118  }
119 
120  compareTransform(gp, matrix);
121 
122  auto const& shape = fwGeometry_.getShapePars(chId.rawId());
123 
124  if (!shape) {
125  LogVerbatim("DTGeometry") << "Failed to get shape of DT chamber with detid: " << chId.rawId();
126  continue;
127  }
128 
129  compareShape(it, shape);
130  }
131 
132  makeHistograms("DT Chamber");
133 }
134 
136  clearData();
137 
138  vector<float> wire_positions;
139 
140  for (auto const& it : dtGeometry_->layers()) {
141  DTLayerId layerId = it->id();
142  GlobalPoint gp = it->surface().toGlobal(LocalPoint(0.0, 0.0, 0.0));
143 
144  const TGeoMatrix* matrix = fwGeometry_.getMatrix(layerId.rawId());
145 
146  if (!matrix) {
147  LogVerbatim("DTGeometry") << "Failed to get matrix of DT layer with detid: " << layerId.rawId();
148  continue;
149  }
150 
151  compareTransform(gp, matrix);
152 
153  auto const& shape = fwGeometry_.getShapePars(layerId.rawId());
154 
155  if (!shape) {
156  LogVerbatim("DTGeometry") << "Failed to get shape of DT layer with detid: " << layerId.rawId();
157  continue;
158  }
159 
160  compareShape(it, shape);
161 
162  auto const& parameters = fwGeometry_.getParameters(layerId.rawId());
163 
164  if (parameters == nullptr) {
165  LogVerbatim("DTGeometry") << "Parameters empty for DT layer with detid: " << layerId.rawId();
166  continue;
167  }
168 
169  float width = it->surface().bounds().width();
170  assert(width == parameters[6]);
171 
172  float thickness = it->surface().bounds().thickness();
173  assert(thickness == parameters[7]);
174 
175  float length = it->surface().bounds().length();
176  assert(length == parameters[8]);
177 
178  int firstChannel = it->specificTopology().firstChannel();
179  assert(firstChannel == parameters[3]);
180 
181  int lastChannel = it->specificTopology().lastChannel();
182  int nChannels = parameters[5];
183  assert(nChannels == (lastChannel - firstChannel) + 1);
184 
185  for (int wireN = firstChannel; wireN - lastChannel <= 0; ++wireN) {
186  float localX1 = it->specificTopology().wirePosition(wireN);
187  float localX2 = (wireN - (firstChannel - 1) - 0.5f) * parameters[0] - nChannels / 2.0f * parameters[0];
188  wire_positions.emplace_back(getDiff(localX1, localX2));
189  }
190  }
191 
192  makeHistogram("DT Layer Wire localX", wire_positions);
193  makeHistograms("DT Layer");
194 }
195 
197  double local[3] = {0.0, 0.0, 0.0};
198  double global[3];
199 
200  matrix->LocalToMaster(local, global);
201 
202  float distance = getDistance(GlobalPoint(global[0], global[1], global[2]), gp);
203  globalDistances_.push_back(distance);
204 }
205 
206 void DTGeometryValidate::compareShape(const GeomDet* det, const float* shape) {
207  float shapeTopWidth;
208  float shapeBottomWidth;
209  float shapeLength;
210  float shapeThickness;
211 
212  if (shape[0] == 1) {
213  shapeTopWidth = shape[2];
214  shapeBottomWidth = shape[1];
215  shapeLength = shape[4];
216  shapeThickness = shape[3];
217  } else if (shape[0] == 2) {
218  shapeTopWidth = shape[1];
219  shapeBottomWidth = shape[1];
220  shapeLength = shape[2];
221  shapeThickness = shape[3];
222  } else {
223  LogVerbatim("DTGeometry") << "Failed to get box or trapezoid from shape";
224  return;
225  }
226 
227  float topWidth, bottomWidth;
228  float length, thickness;
229 
230  const Bounds* bounds = &(det->surface().bounds());
231 
232  if (const TrapezoidalPlaneBounds* tpbs = dynamic_cast<const TrapezoidalPlaneBounds*>(bounds)) {
233  array<const float, 4> const& ps = tpbs->parameters();
234 
235  assert(ps.size() == 4);
236 
237  bottomWidth = ps[0];
238  topWidth = ps[1];
239  thickness = ps[2];
240  length = ps[3];
241  } else if ((dynamic_cast<const RectangularPlaneBounds*>(bounds))) {
242  length = det->surface().bounds().length() * 0.5;
243  topWidth = det->surface().bounds().width() * 0.5;
244  bottomWidth = topWidth;
245  thickness = det->surface().bounds().thickness() * 0.5;
246  } else {
247  LogVerbatim("DTGeometry") << "Failed to get bounds";
248  return;
249  }
250  topWidths_.push_back(fabs(shapeTopWidth - topWidth));
251  bottomWidths_.push_back(fabs(shapeBottomWidth - bottomWidth));
252  lengths_.push_back(fabs(shapeLength - length));
253  thicknesses_.push_back(fabs(shapeThickness - thickness));
254 }
255 
257  return sqrt((p1.x() - p2.x()) * (p1.x() - p2.x()) + (p1.y() - p2.y()) * (p1.y() - p2.y()) +
258  (p1.z() - p2.z()) * (p1.z() - p2.z()));
259 }
260 
261 float DTGeometryValidate::getDiff(const float val1, const float val2) {
262  if (almost_equal(val1, val2, tolerance_))
263  return 0.0f;
264  else
265  return (val1 - val2);
266 }
267 
268 void DTGeometryValidate::makeHistograms(const char* detector) {
269  outFile_->cd();
270 
271  string d(detector);
272 
273  string gdn = d + ": distance between points in global coordinates";
275 
276  string twn = d + ": absolute difference between top widths (along X)";
278 
279  string bwn = d + ": absolute difference between bottom widths (along X)";
281 
282  string ln = d + ": absolute difference between lengths (along Y)";
283  makeHistogram(ln, lengths_);
284 
285  string tn = d + ": absolute difference between thicknesses (along Z)";
287 }
288 
289 void DTGeometryValidate::makeHistogram(const string& name, vector<float>& data) {
290  if (data.empty())
291  return;
292 
293  const auto [minE, maxE] = minmax_element(begin(data), end(data));
294 
295  TH1D hist(name.c_str(), name.c_str(), 100, *minE * (1 + 0.10), *maxE * (1 + 0.10));
296 
297  for (auto const& it : data)
298  hist.Fill(it);
299 
300  hist.GetXaxis()->SetTitle("[cm]");
301  hist.Write();
302 }
303 
305 
307  LogVerbatim("DTGeometry") << "Done.";
308  LogVerbatim("DTGeometry") << "Results written to " << outfileName_;
309  outFile_->Close();
310 }
311 
Log< level::Info, true > LogVerbatim
T getUntrackedParameter(std::string const &, T const &) const
Point3DBase< Scalar, LocalTag > LocalPoint
Definition: Definitions.h:30
virtual float length() const =0
const TString p2
Definition: fwPaths.cc:13
~DTGeometryValidate() override
const float * getParameters(unsigned int id) const
Definition: FWGeometry.cc:472
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
float getDistance(const GlobalPoint &, const GlobalPoint &)
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
DTGeometryValidate(const ParameterSet &)
constexpr uint32_t rawId() const
get the raw id
Definition: DetId.h:57
T y() const
Definition: PV3DBase.h:60
float getDiff(const float, const float)
const Bounds & bounds() const
Definition: Surface.h:87
void makeHistograms(const char *)
void endJob() override
const TGeoMatrix * getMatrix(unsigned int id) const
Definition: FWGeometry.cc:225
assert(be >=bs)
const Plane & surface() const
The nominal surface of the GeomDet.
Definition: GeomDet.h:37
example_stream void analyze(const edm::Event &, const edm::EventSetup &) override
void compareShape(const GeomDet *, const float *)
void beginJob()
Definition: Breakpoints.cc:14
virtual float thickness() const =0
tuple d
Definition: ztail.py:151
const float * getShapePars(unsigned int id) const
Definition: FWGeometry.cc:483
void compareTransform(const GlobalPoint &, const TGeoMatrix *)
edm::ESGetToken< DTGeometry, MuonGeometryRecord > dtGeometryToken_
vector< float > globalDistances_
edm::ESHandle< DTGeometry > dtGeometry_
void loadMap(const char *fileName)
Definition: FWGeometry.cc:103
T sqrt(T t)
Definition: SSEVec.h:19
T z() const
Definition: PV3DBase.h:61
vector< float > topWidths_
const TString p1
Definition: fwPaths.cc:12
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
T min(T a, T b)
Definition: MathUtil.h:58
vector< float > lengths_
vector< float > thicknesses_
__shared__ Hist hist
enable_if<!numeric_limits< T >::is_integer, bool >::type almost_equal(T x, T y, int ulp)
void beginJob() override
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:79
string end
Definition: dataset.py:937
vector< float > bottomWidths_
Definition: Bounds.h:18
ESHandle< T > getHandle(const ESGetToken< T, R > &iToken) const
Definition: EventSetup.h:157
bool isValid() const
Definition: ESHandle.h:44
void makeHistogram(const string &, vector< float > &)
long double T
T x() const
Definition: PV3DBase.h:59
virtual float width() const =0
void analyze(const edm::Event &, const edm::EventSetup &) override