1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
|
/****************************************************************************
*
* This is a part of the TOTEM offline software.
* Authors:
* Jan Kašpar (jan.kaspar@gmail.com)
* CMSSW developers (based on GeometricDet class)
*
****************************************************************************/
#include <utility>
#include "Geometry/VeryForwardGeometryBuilder/interface/DetGeomDesc.h"
#include "Geometry/VeryForwardGeometryBuilder/interface/CTPPSDDDNames.h"
#include "CondFormats/PPSObjects/interface/CTPPSRPAlignmentCorrectionData.h"
#include "DetectorDescription/Core/interface/DDSolid.h"
#include "DetectorDescription/DDCMS/interface/DDSolidShapes.h"
#include "DataFormats/CTPPSDetId/interface/TotemRPDetId.h"
#include "DataFormats/CTPPSDetId/interface/TotemTimingDetId.h"
#include "DataFormats/CTPPSDetId/interface/CTPPSPixelDetId.h"
#include "DataFormats/CTPPSDetId/interface/CTPPSDiamondDetId.h"
#include <DD4hep/DD4hepUnits.h>
#include "FWCore/MessageLogger/interface/MessageLogger.h"
/*
* Constructor from old DD DDFilteredView, also using the SpecPars to access 2x2 wafers info.
*/
DetGeomDesc::DetGeomDesc(const DDFilteredView& fv, const bool isRun2)
: m_name(computeNameWithNoNamespace(fv.name())),
m_copy(fv.copyno()),
m_isDD4hep(false),
m_trans(fv.translation()), // mm (legacy)
m_rot(fv.rotation()),
m_params(fv.parameters()), // default unit from old DD (mm)
m_isABox(fv.shape() == DDSolidShape::ddbox),
m_diamondBoxParams(computeDiamondDimensions(m_isABox, m_isDD4hep, m_params)), // mm (legacy)
m_sensorType(computeSensorType(fv.logicalPart().name().fullname())),
m_geographicalID(computeDetID(m_name, fv.copyNumbers(), fv.copyno(), isRun2)),
m_z(fv.translation().z()) // mm (legacy)
{}
/*
* Constructor from DD4hep DDFilteredView, also using the SpecPars to access 2x2 wafers info.
*/
DetGeomDesc::DetGeomDesc(const cms::DDFilteredView& fv, const bool isRun2)
: m_name(computeNameWithNoNamespace(fv.name())),
m_copy(fv.copyNum()),
m_isDD4hep(true),
m_trans(fv.translation() / dd4hep::mm), // converted from DD4hep unit to mm
m_rot(fv.rotation()),
m_params(computeParameters(fv)), // default unit from DD4hep
m_isABox(dd4hep::isA<dd4hep::Box>(fv.solid())),
m_diamondBoxParams(computeDiamondDimensions(m_isABox, m_isDD4hep, m_params)), // converted from DD4hep unit to mm
m_sensorType(computeSensorType(fv.name())),
m_geographicalID(computeDetIDFromDD4hep(m_name, fv.copyNos(), fv.copyNum(), isRun2)),
m_z(fv.translation().z() / dd4hep::mm) // converted from DD4hep unit to mm
{}
DetGeomDesc::DetGeomDesc(const DetGeomDesc& ref, CopyMode cm) {
m_name = ref.m_name;
m_copy = ref.m_copy;
m_isDD4hep = ref.m_isDD4hep;
m_trans = ref.m_trans;
m_rot = ref.m_rot;
m_params = ref.m_params;
m_isABox = ref.m_isABox;
m_diamondBoxParams = ref.m_diamondBoxParams;
m_sensorType = ref.m_sensorType;
m_geographicalID = ref.m_geographicalID;
if (cm == cmWithChildren)
m_container = ref.m_container;
m_z = ref.m_z;
}
// Constructor from DB object PDetGeomDesc::Item
DetGeomDesc::DetGeomDesc(const PDetGeomDesc::Item& item)
: m_name(item.name_),
m_copy(item.copy_),
m_isDD4hep(true),
m_params(item.params_), // default unit from DD4hep
m_sensorType(item.sensorType_),
m_geographicalID(item.geographicalID_),
m_z(item.z_) // converted from DD4hep to mm
{
Translation trans(item.dx_, item.dy_, item.dz_);
m_trans = trans;
RotationMatrix rot(item.axx_, item.axy_, item.axz_, item.ayx_, item.ayy_, item.ayz_, item.azx_, item.azy_, item.azz_);
m_rot = rot;
// Set the m_isABox flag for the box shaped sensors, so that m_params are properly set
if ((m_name == DDD_CTPPS_PIXELS_SENSOR_NAME || m_name == DDD_CTPPS_PIXELS_SENSOR_NAME_2x2 ||
m_name == DDD_CTPPS_DIAMONDS_SEGMENT_NAME || m_name == DDD_CTPPS_UFSD_SEGMENT_NAME ||
m_name.substr(0, 7) == DDD_TOTEM_TIMING_SENSOR_TMPL.substr(0, 7)) &&
m_params.size() > 2)
m_isABox = true;
else
m_isABox = false;
m_diamondBoxParams = computeDiamondDimensions(m_isABox, m_isDD4hep, m_params);
}
DetGeomDesc::DetGeomDesc(const PDetGeomDesc& pd) : m_copy(0), m_isDD4hep(false), m_isABox(false), m_z(0) {
for (const auto& i : pd.container_) {
DetGeomDesc* gd = new DetGeomDesc(i);
this->addComponent(gd);
}
}
DetGeomDesc::~DetGeomDesc() { deepDeleteComponents(); }
void DetGeomDesc::addComponent(DetGeomDesc* det) { m_container.emplace_back(det); }
void DetGeomDesc::applyAlignment(const CTPPSRPAlignmentCorrectionData& t) {
m_rot = t.getRotationMatrix() * m_rot;
m_trans = t.getTranslation() + m_trans;
}
void DetGeomDesc::print() const {
edm::LogVerbatim("DetGeomDesc::print") << "............................." << std::endl;
edm::LogVerbatim("DetGeomDesc::print") << "name = " << m_name << std::endl;
edm::LogVerbatim("DetGeomDesc::print") << "copy = " << m_copy << std::endl;
edm::LogVerbatim("DetGeomDesc::print") << "translation = " << std::fixed << std::setprecision(7) << m_trans
<< std::endl;
edm::LogVerbatim("DetGeomDesc::print") << "rotation = " << std::fixed << std::setprecision(7) << m_rot << std::endl;
if (m_isABox) {
edm::LogVerbatim("DetGeomDesc::print")
<< "getDiamondDimensions() = " << std::fixed << std::setprecision(7) << getDiamondDimensions().xHalfWidth << " "
<< getDiamondDimensions().yHalfWidth << " " << getDiamondDimensions().zHalfWidth << std::endl;
}
edm::LogVerbatim("DetGeomDesc::print") << "sensorType = " << m_sensorType << std::endl;
if (m_geographicalID() != 0) {
edm::LogVerbatim("DetGeomDesc::print") << "geographicalID() = " << m_geographicalID << std::endl;
}
edm::LogVerbatim("DetGeomDesc::print") << "parentZPosition() = " << std::fixed << std::setprecision(7) << m_z
<< std::endl;
}
/*
* PRIVATE FUNCTIONS
*/
void DetGeomDesc::deleteComponents() { m_container.erase(m_container.begin(), m_container.end()); }
void DetGeomDesc::deepDeleteComponents() {
for (auto& it : m_container) {
delete it; // the destructor calls deepDeleteComponents
}
clearComponents();
}
std::string DetGeomDesc::computeNameWithNoNamespace(std::string_view nameFromView) const {
const auto& semiColonPos = nameFromView.find(':');
const std::string name{(semiColonPos != std::string::npos ? nameFromView.substr(semiColonPos + 1) : nameFromView)};
return name;
}
/*
* Compute DD4hep shape parameters.
*/
std::vector<double> DetGeomDesc::computeParameters(const cms::DDFilteredView& fv) const {
auto myShape = fv.solid();
const std::vector<double>& parameters = myShape.dimensions(); // default unit from DD4hep (cm)
return parameters;
}
/*
* Compute diamond dimensions.
* The diamond sensors are represented by the Box shape parameters.
* oldDD: params are already in mm.
* DD4hep: convert params from DD4hep unit to mm (mm is legacy expected by PPS reco software).
*/
DiamondDimensions DetGeomDesc::computeDiamondDimensions(const bool isABox,
const bool isDD4hep,
const std::vector<double>& params) const {
DiamondDimensions boxShapeParameters{};
if (isABox) {
if (!isDD4hep) {
// mm (old DD)
boxShapeParameters = {params.at(0), params.at(1), params.at(2)};
} else {
// convert from DD4hep unit to mm (mm is legacy expected by PPS reco software)
boxShapeParameters = {params.at(0) / dd4hep::mm, params.at(1) / dd4hep::mm, params.at(2) / dd4hep::mm};
}
}
return boxShapeParameters;
}
/*
* old DD DetId computation.
* Relies on name and volumes copy numbers.
*/
DetId DetGeomDesc::computeDetID(const std::string& name,
const std::vector<int>& copyNos,
const unsigned int copyNum,
const bool isRun2) const {
DetId geoID;
// strip sensors
if (name == DDD_TOTEM_RP_SENSOR_NAME) {
// check size of copy numbers vector
if (copyNos.size() < 3)
throw cms::Exception("DDDTotemRPConstruction")
<< "size of copyNumbers for strip sensor is " << copyNos.size() << ". It must be >= 3.";
// extract information
const unsigned int decRPId = copyNos[copyNos.size() - 3];
const unsigned int arm = decRPId / 100;
const unsigned int station = (decRPId % 100) / 10;
const unsigned int rp = decRPId % 10;
const unsigned int detector = copyNos[copyNos.size() - 1];
geoID = TotemRPDetId(arm, station, rp, detector);
}
// strip and pixels RPs
else if (name == DDD_TOTEM_RP_RP_NAME || name == DDD_CTPPS_PIXELS_RP_NAME) {
unsigned int decRPId = copyNum;
// check if it is a pixel RP
if (decRPId >= 10000) {
decRPId = decRPId % 10000;
const unsigned int armIdx = (decRPId / 100) % 10;
const unsigned int stIdx = (decRPId / 10) % 10;
const unsigned int rpIdx = decRPId % 10;
geoID = CTPPSPixelDetId(armIdx, stIdx, rpIdx);
} else {
const unsigned int armIdx = (decRPId / 100) % 10;
const unsigned int stIdx = (decRPId / 10) % 10;
const unsigned int rpIdx = decRPId % 10;
geoID = TotemRPDetId(armIdx, stIdx, rpIdx);
}
}
else if (std::regex_match(name, std::regex(DDD_TOTEM_TIMING_SENSOR_TMPL))) {
// check size of copy numbers vector
if (copyNos.size() < 4)
throw cms::Exception("DDDTotemRPConstruction")
<< "size of copyNumbers for TOTEM timing sensor is " << copyNos.size() << ". It must be >= 4.";
const unsigned int decRPId = copyNos[copyNos.size() - 4];
const unsigned int arm = decRPId / 100, station = (decRPId % 100) / 10, rp = decRPId % 10;
const unsigned int plane = copyNos[copyNos.size() - 2], channel = copyNos[copyNos.size() - 1];
geoID = TotemTimingDetId(arm, station, rp, plane, channel);
}
else if (name == DDD_TOTEM_TIMING_RP_NAME) {
const unsigned int arm = copyNum / 100, station = (copyNum % 100) / 10, rp = copyNum % 10;
geoID = TotemTimingDetId(arm, station, rp);
}
// pixel sensors
else if (name == DDD_CTPPS_PIXELS_SENSOR_NAME || name == DDD_CTPPS_PIXELS_SENSOR_NAME_2x2) {
// check size of copy numbers vector
if (copyNos.size() < 4)
throw cms::Exception("DDDTotemRPConstruction")
<< "size of copyNumbers for pixel sensor is " << copyNos.size() << ". It must be >= 4.";
// extract information
const unsigned int decRPId = copyNos[copyNos.size() - 4] % 10000;
const unsigned int arm = decRPId / 100;
const unsigned int station = (decRPId % 100) / 10;
const unsigned int rp = decRPId % 10;
const unsigned int detector = copyNos[copyNos.size() - 2] - 1;
geoID = CTPPSPixelDetId(arm, station, rp, detector);
}
// diamond/UFSD sensors
else if (name == DDD_CTPPS_DIAMONDS_SEGMENT_NAME || name == DDD_CTPPS_UFSD_SEGMENT_NAME) {
// check size of copy numbers vector
if (copyNos.size() < 2)
throw cms::Exception("DDDTotemRPConstruction")
<< "size of copyNumbers for diamond segments is " << copyNos.size() << ". It must be >= 2.";
const unsigned int decRPId = copyNos[1];
unsigned int arm, station, rp;
if (isRun2) {
arm = decRPId - 1;
station = 1;
rp = 6;
} else {
arm = (decRPId % 1000) / 100;
station = (decRPId % 100) / 10;
rp = decRPId % 10;
}
const unsigned int id = copyNos[copyNos.size() - 1];
const unsigned int plane = id / 100;
const unsigned int channel = id % 100;
geoID = CTPPSDiamondDetId(arm, station, rp, plane, channel);
}
// diamond/UFSD RPs
else if (name == DDD_CTPPS_DIAMONDS_RP_NAME) {
// check size of copy numbers vector
if (copyNos.size() < 2)
throw cms::Exception("DDDTotemRPConstruction")
<< "size of copyNumbers for diamond RP is " << copyNos.size() << ". It must be >= 2.";
const unsigned int decRPId = copyNos[1];
unsigned int arm, station, rp;
if (isRun2) {
arm = decRPId - 1;
station = 1;
rp = 6;
} else {
arm = (decRPId % 1000) / 100;
station = (decRPId % 100) / 10;
rp = decRPId % 10;
}
geoID = CTPPSDiamondDetId(arm, station, rp);
}
return geoID;
}
/*
* DD4hep DetId computation.
*/
DetId DetGeomDesc::computeDetIDFromDD4hep(const std::string& name,
const std::vector<int>& copyNos,
const unsigned int copyNum,
const bool isRun2) const {
std::vector<int> copyNosOldDD = {copyNos.rbegin() + 1, copyNos.rend()};
return computeDetID(name, copyNosOldDD, copyNum, isRun2);
}
/*
* Sensor type computation.
* Find out from the namespace (from DB) or the volume name (from XMLs), whether a sensor type is 2x2.
*/
std::string DetGeomDesc::computeSensorType(std::string_view name) {
std::string sensorType;
// Case A: Construction from DB.
// Namespace is present, and allow identification of 2x2 sensor type: just look for "2x2:RPixWafer" in name.
const auto& foundFromDB = name.find(DDD_CTPPS_PIXELS_SENSOR_TYPE_2x2 + ":" + DDD_CTPPS_PIXELS_SENSOR_NAME);
if (foundFromDB != std::string::npos) {
sensorType = DDD_CTPPS_PIXELS_SENSOR_TYPE_2x2;
}
// Case B: Construction from XMLs.
// Volume name allows identification of 2x2 sensor type: just look whether name is "RPixWafer2x2".
const auto& foundFromXML = name.find(DDD_CTPPS_PIXELS_SENSOR_NAME_2x2);
if (foundFromXML != std::string::npos) {
sensorType = DDD_CTPPS_PIXELS_SENSOR_TYPE_2x2;
}
return sensorType;
}
|