CMS 3D CMS Logo

CSCGeometryBuilder.cc
Go to the documentation of this file.
1 #include "CSCGeometryBuilder.h"
2 
4 
8 
10 
11 #include <vector>
12 
13 CSCGeometryBuilder::CSCGeometryBuilder() : myName("CSCGeometryBuilder") {}
14 
16 
18  const RecoIdealGeometry& rig,
19  const CSCRecoDigiParameters& cscpars) {
20  std::vector<float> fpar;
21  std::vector<float> gtran;
22  std::vector<float> grmat;
23  std::vector<float> fupar;
24  std::vector<double>::const_iterator it, endIt;
25  const std::vector<DetId>& detids(rig.detIds());
26 
27  for (size_t idt = 0; idt < detids.size(); ++idt) {
28  CSCDetId detid = CSCDetId(detids[idt]);
29  int jstation = detid.station();
30  int jring = detid.ring();
31 
32  endIt = rig.shapeEnd(idt);
33  fpar.clear();
34  for (it = rig.shapeStart(idt); it != endIt; ++it) {
35  fpar.emplace_back((float)(*it));
36  }
37 
38  gtran.clear();
39  endIt = rig.tranEnd(idt);
40  for (it = rig.tranStart(idt); it != endIt; ++it) {
41  gtran.emplace_back((float)(*it));
42  }
43  grmat.clear();
44  endIt = rig.rotEnd(idt);
45  for (it = rig.rotStart(idt); it != endIt; ++it) {
46  grmat.emplace_back((float)(*it));
47  }
48 
49  // get the chamber type from existing info
50  int chamberType = CSCChamberSpecs::whatChamberType(jstation, jring);
51  size_t cs = 0;
52  assert(!cscpars.pChamberType.empty());
53  while (cs < cscpars.pChamberType.size() && chamberType != cscpars.pChamberType[cs]) {
54  ++cs;
55  }
56  assert(cs != cscpars.pChamberType.size());
57 
58  // check the existence of the specs for this type WHY? Remove it...
59  size_t fu, numfuPars;
61  fu = cscpars.pUserParOffset[cs];
62  numfuPars = fu + 1 + size_t(cscpars.pfupars[fu]);
63 
64  // upars from db are now uparvals + wg info so we need to unwrap only part here first...
65  LogTrace(myName) << myName << ": I think I have " << cscpars.pUserParSize[cs] << " values in pfupars (uparvals)."
66  << std::endl;
67  LogTrace(myName) << myName << ": For fupar I will start at " << cscpars.pUserParOffset[cs] + 1
68  << " in pfupars and go to " << numfuPars << "." << std::endl;
69  for (++fu; fu < numfuPars; ++fu) {
70  LogTrace(myName) << myName << ": pfupars[" << fu << "]=" << cscpars.pfupars[fu] << std::endl;
71  fupar.emplace_back(cscpars.pfupars[fu]);
72  }
73  // now, we need to start from "here" at fu to go on and build wg...
74  wg.wireSpacing = cscpars.pfupars[fu++];
75  wg.alignmentPinToFirstWire = cscpars.pfupars[fu++];
76  wg.numberOfGroups = int(cscpars.pfupars[fu++]);
77  wg.narrowWidthOfWirePlane = cscpars.pfupars[fu++];
78  wg.wideWidthOfWirePlane = cscpars.pfupars[fu++];
79  wg.lengthOfWirePlane = cscpars.pfupars[fu++];
80  size_t numgrp = static_cast<size_t>(cscpars.pfupars[fu]);
81  size_t maxFu = fu + 1 + numgrp;
82  fu++;
83  for (; fu < maxFu; ++fu) {
84  wg.wiresInEachGroup.emplace_back(int(cscpars.pfupars[fu]));
85  }
86  maxFu = fu + numgrp;
87  for (; fu < maxFu; ++fu) {
88  wg.consecutiveGroups.emplace_back(int(cscpars.pfupars[fu]));
89  }
90 
91  if (wg.numberOfGroups != 0) {
92  LogTrace(myName) << myName << ": TotNumWireGroups = " << wg.numberOfGroups;
93  LogTrace(myName) << myName << ": WireSpacing = " << wg.wireSpacing;
94  LogTrace(myName) << myName << ": AlignmentPinToFirstWire = " << wg.alignmentPinToFirstWire;
95  LogTrace(myName) << myName << ": Narrow width of wire plane = " << wg.narrowWidthOfWirePlane;
96  LogTrace(myName) << myName << ": Wide width of wire plane = " << wg.wideWidthOfWirePlane;
97  LogTrace(myName) << myName << ": Length in y of wire plane = " << wg.lengthOfWirePlane;
98  LogTrace(myName) << myName << ": wg.consecutiveGroups.size() = " << wg.consecutiveGroups.size();
99  LogTrace(myName) << myName << ": wg.wiresInEachGroup.size() = " << wg.wiresInEachGroup.size();
100  LogTrace(myName) << myName << ": \tNumGroups\tWiresInGroup";
101  for (size_t i = 0; i < wg.consecutiveGroups.size(); i++) {
102  LogTrace(myName) << myName << " \t" << wg.consecutiveGroups[i] << "\t\t" << wg.wiresInEachGroup[i];
103  }
104  } else {
105  LogTrace(myName) << myName << ": DDD is MISSING SpecPars for wire groups";
106  }
107  LogTrace(myName) << myName << ": end of wire group info. ";
108 
109  // Are we going to apply centre-to-intersection offsets, even if values exist in the specs file?
110  if (!theGeometry.centreTIOffsets())
111  fupar[30] = 0.; // reset to zero if flagged 'off'
112 
113  buildChamber(theGeometry, detid, fpar, fupar, gtran, grmat, wg); //, cscpars.pWGPs[cs] );
114  fupar.clear();
115  }
116 }
117 
118 void CSCGeometryBuilder::buildChamber(CSCGeometry& theGeometry, // the geometry container
119  CSCDetId chamberId, // the DetId for this chamber
120  const std::vector<float>& fpar, // volume parameters hB, hT. hD, hH
121  const std::vector<float>& fupar, // user parameters
122  const std::vector<float>& gtran, // translation vector
123  const std::vector<float>& grmat, // rotation matrix
124  const CSCWireGroupPackage& wg // wire group info
125 ) {
126  LogTrace(myName) << myName << ": entering buildChamber";
127 
128  int jend = chamberId.endcap();
129  int jstat = chamberId.station();
130  int jring = chamberId.ring();
131  int jch = chamberId.chamber();
132  int jlay = chamberId.layer();
133 
134  if (jlay != 0)
135  edm::LogWarning(myName) << "Error! CSCGeometryBuilderFromDDD was fed layer id = " << jlay << "\n";
136 
137  const size_t kNpar = 4;
138  if (fpar.size() != kNpar)
139  edm::LogError(myName) << "Error, expected npar=" << kNpar << ", found npar=" << fpar.size() << std::endl;
140 
141  LogTrace(myName) << myName << ": E" << jend << " S" << jstat << " R" << jring << " C" << jch << " L" << jlay;
142  LogTrace(myName) << myName << ": npar=" << fpar.size() << " hB=" << fpar[0] << " hT=" << fpar[1] << " hD=" << fpar[2]
143  << " hH=" << fpar[3];
144  LogTrace(myName) << myName << ": gtran[0,1,2]=" << gtran[0] << " " << gtran[1] << " " << gtran[2];
145  LogTrace(myName) << myName << ": grmat[0-8]=" << grmat[0] << " " << grmat[1] << " " << grmat[2] << " " << grmat[3]
146  << " " << grmat[4] << " " << grmat[5] << " " << grmat[6] << " " << grmat[7] << " " << grmat[8];
147  LogTrace(myName) << myName << ": nupar=" << fupar.size() << " upar[0]=" << fupar[0] << " upar[" << fupar.size() - 1
148  << "]=" << fupar[fupar.size() - 1];
149 
150  const CSCChamber* chamber = theGeometry.chamber(chamberId);
151  if (chamber) {
152  } else { // this chamber not yet built/stored
153 
154  LogTrace(myName) << myName << ": CSCChamberSpecs::build requested for ME" << jstat << jring;
155  int chamberType = CSCChamberSpecs::whatChamberType(jstat, jring);
156  const CSCChamberSpecs* aSpecs = theGeometry.findSpecs(chamberType);
157  if (!fupar.empty() && aSpecs == nullptr) {
158  // make new one:
159  aSpecs = theGeometry.buildSpecs(chamberType, fpar, fupar, wg);
160  } else if (fupar.empty() && aSpecs == nullptr) {
162  << "SHOULD BE THROW? Error, wg and/or fupar size are 0 BUT this Chamber Spec has not been built!";
163  }
164 
165  // Build a Transformation out of GEANT gtran and grmat...
166  // These are used to transform a point in the local reference frame
167  // of a subdetector to the global frame of CMS by
168  // (grmat)^(-1)*local + (gtran)
169  // The corresponding transformation from global to local is
170  // (grmat)*(global - gtran)
171 
173  grmat[0], grmat[1], grmat[2], grmat[3], grmat[4], grmat[5], grmat[6], grmat[7], grmat[8]);
174 
175  // This rotation from GEANT considers the detector face as the x-z plane.
176  // We want this to be the local x-y plane.
177  // Furthermore, the -z_global endcap has LH local coordinates, since it is built
178  // in GEANT as a *reflection* of the +z_global endcap.
179  // So we need to rotate, and in -z flip local x.
180 
181  // aRot.rotateAxes will transform aRot in place so that it becomes
182  // applicable to the new local coordinates: detector face in x-y plane
183  // looking out along z, in either endcap.
184 
185  // The interface for rotateAxes specifies 'new' X,Y,Z but the
186  // implementation deals with them as the 'old'.
187 
188  Basic3DVector<float> oldX(1., 0., 0.);
189  Basic3DVector<float> oldY(0., 0., -1.);
190  Basic3DVector<float> oldZ(0., 1., 0.);
191 
192  if (gtran[2] < 0.)
193  oldX *= -1;
194 
195  aRot.rotateAxes(oldX, oldY, oldZ);
196 
197  // Need to know z of layers w.r.t to z of centre of chamber.
198 
199  float frameThickness = fupar[31] / 10.; // mm -> cm
200  float gapThickness = fupar[32] / 10.; // mm -> cm
201  float panelThickness = fupar[33] / 10.; // mm -> cm
202  float zAverageAGVtoAF = fupar[34] / 10.; // mm -> cm
203 
204  float layerThickness = gapThickness; // consider the layer to be the gas gap
205  float layerSeparation = gapThickness + panelThickness; // centre-to-centre of neighbouring layers
206 
207  float chamberThickness = 7. * panelThickness + 6. * gapThickness + 2. * frameThickness; // chamber frame thickness
208  float hChamberThickness = chamberThickness / 2.; // @@ should match value returned from DDD directly
209 
210  // distAverageAGVtoAF is offset between centre of chamber (AF) and (L1+L6)/2 (average AGVs)
211  // where AF = AluminumFrame and AGV=ActiveGasVolume (volume names in DDD).
212  // It is signed based on global z values: zc - (zl1+zl6)/2
213 
214  // Local z values w.r.t. AF...
215  // z of wires in layer 1 = z_w1 = +/- zAverageAGVtoAF + 2.5*layerSeparation; // layer 1 is at most +ve local z
216  // The sign in '+/-' depends on relative directions of local and global z.
217  // It is '-' if they are the same direction, and '+' if opposite directions.
218  // z of wires in layer N = z_wN = z_w1 - (N-1)*layerSeparation;
219  // z of strips in layer N = z_sN = z_wN + gapThickness/2.; @@ BEWARE: need to check if it should be '-gapThickness/2' !
220 
221  // Set dimensions of trapezoidal chamber volume
222  // N.B. apothem is 4th in fpar but 3rd in ctor
223 
224  // hChamberThickness and fpar[2] should be the same - but using the above value at least shows
225  // how chamber structure works
226 
227  TrapezoidalPlaneBounds* bounds = new TrapezoidalPlaneBounds(fpar[0], fpar[1], fpar[3], hChamberThickness);
228 
229  // Centre of chamber in z is specified in DDD
230  Surface::PositionType aVec(gtran[0], gtran[1], gtran[2]);
231 
232  Plane::PlanePointer plane = Plane::build(aVec, aRot, bounds);
233 
234  CSCChamber* chamber = new CSCChamber(plane, chamberId, aSpecs);
235  theGeometry.addChamber(chamber);
236 
237  LogTrace(myName) << myName << ": Create chamber E" << jend << " S" << jstat << " R" << jring << " C" << jch
238  << " z=" << gtran[2] << " t/2=" << fpar[2] << " (DDD) or " << hChamberThickness
239  << " (specs) adr=" << chamber;
240 
241  // Create the component layers of this chamber
242  // We're taking the z as the z of the wire plane within the layer (middle of gas gap)
243 
244  // Specify global z of layer by offsetting from centre of chamber: since layer 1
245  // is nearest to IP in stations 1/2 but layer 6 is nearest in stations 3/4,
246  // we need to adjust sign of offset appropriately...
247  int localZwrtGlobalZ = +1;
248  if ((jend == 1 && jstat < 3) || (jend == 2 && jstat > 2))
249  localZwrtGlobalZ = -1;
250  int globalZ = +1;
251  if (jend == 2)
252  globalZ = -1;
253 
254  LogTrace(myName) << myName << ": layerSeparation=" << layerSeparation << ", zAF-zAverageAGV=" << zAverageAGVtoAF
255  << ", localZwrtGlobalZ=" << localZwrtGlobalZ << ", gtran[2]=" << gtran[2];
256 
257  for (short j = 1; j <= 6; ++j) {
258  CSCDetId layerId = CSCDetId(jend, jstat, jring, jch, j);
259 
260  // extra-careful check that we haven't already built this layer
261  const CSCLayer* cLayer = dynamic_cast<const CSCLayer*>(theGeometry.idToDet(layerId));
262 
263  if (cLayer == nullptr) {
264  // build the layer - need the chamber's specs and an appropriate layer-geometry
265  const CSCChamberSpecs* aSpecs = chamber->specs();
266  const CSCLayerGeometry* geom = (j % 2 != 0) ? aSpecs->oddLayerGeometry(jend) : aSpecs->evenLayerGeometry(jend);
267 
268  // Build appropriate BoundPlane, based on parent chamber, with gas gap as thickness
269 
270  // centre of chamber is at global z = gtran[2]
271  float zlayer = gtran[2] - globalZ * zAverageAGVtoAF + localZwrtGlobalZ * (3.5 - j) * layerSeparation;
272 
273  Surface::RotationType chamberRotation = chamber->surface().rotation();
274  Surface::PositionType layerPosition(gtran[0], gtran[1], zlayer);
275  std::array<const float, 4> const& dims = geom->parameters(); // returns hb, ht, d, a
276  // dims[2] = layerThickness/2.; // half-thickness required and note it is 3rd value in vector
277  TrapezoidalPlaneBounds* bounds = new TrapezoidalPlaneBounds(dims[0], dims[1], dims[3], layerThickness / 2.);
278  Plane::PlanePointer plane = Plane::build(layerPosition, chamberRotation, bounds);
279 
280  CSCLayer* layer = new CSCLayer(plane, layerId, chamber, geom);
281 
282  LogTrace(myName) << myName << ": Create layer E" << jend << " S" << jstat << " R" << jring << " C" << jch
283  << " L" << j << " z=" << zlayer << " t=" << layerThickness << " or "
284  << layer->surface().bounds().thickness() << " adr=" << layer << " layerGeom adr=" << geom;
285 
286  chamber->addComponent(j, layer);
287  theGeometry.addLayer(layer);
288  } else {
289  edm::LogError(myName) << ": ERROR, layer " << j << " for chamber = " << (chamber->id())
290  << " already exists: layer address=" << cLayer << " chamber address=" << chamber << "\n";
291  }
292 
293  } // layer construction within chamber
294  } // chamber construction
295 }
const CSCLayerGeometry * evenLayerGeometry(int iendcap) const
std::vector< double >::const_iterator shapeEnd(size_t ind) const
const CSCChamberSpecs * buildSpecs(int iChamberType, const std::vector< float > &fpar, const std::vector< float > &fupar, const CSCWireGroupPackage &wg)
Definition: CSCGeometry.cc:159
const CSCChamber * chamber(CSCDetId id) const
Return the chamber corresponding to given DetId.
Definition: CSCGeometry.cc:100
static int whatChamberType(int istation, int iring)
std::vector< double >::const_iterator rotStart(size_t ind) const
void addChamber(CSCChamber *ch)
Add a chamber with given DetId.
Definition: CSCGeometry.cc:58
bool centreTIOffsets() const
Definition: CSCGeometry.h:130
int layer() const
Definition: CSCDetId.h:56
Log< level::Error, false > LogError
assert(be >=bs)
void build(CSCGeometry &theGeometry, const RecoIdealGeometry &rig, const CSCRecoDigiParameters &cscpars)
Build the geometry.
std::vector< double >::const_iterator tranEnd(size_t ind) const
TkRotation & rotateAxes(const Basic3DVector< T > &newX, const Basic3DVector< T > &newY, const Basic3DVector< T > &newZ)
#define LogTrace(id)
constexpr std::array< uint8_t, layerIndexSize > layer
static PlanePointer build(Args &&... args)
Definition: Plane.h:33
std::vector< float > pfupars
void addLayer(CSCLayer *l)
Add a DetUnit.
Definition: CSCGeometry.cc:63
const CSCChamberSpecs * findSpecs(int iChamberType)
Definition: CSCGeometry.cc:151
void buildChamber(CSCGeometry &theGeometry, CSCDetId chamberId, const std::vector< float > &fpar, const std::vector< float > &fupar, const std::vector< float > &gtran, const std::vector< float > &grmat, const CSCWireGroupPackage &wg)
Build one CSC chamber, and its component layers, and add them to the geometry.
std::vector< int > pChamberType
const std::vector< DetId > & detIds() const
std::vector< int > pUserParOffset
int chamber() const
Definition: CSCDetId.h:62
const std::string myName
std::vector< double >::const_iterator shapeStart(size_t ind) const
int station() const
Definition: CSCDetId.h:79
const CSCLayerGeometry * oddLayerGeometry(int iendcap) const
Accessors for LayerGeometry&#39;s.
std::vector< int > pUserParSize
CSCGeometryBuilder()
Constructor.
int endcap() const
Definition: CSCDetId.h:85
virtual ~CSCGeometryBuilder()
Destructor.
int ring() const
Definition: CSCDetId.h:68
Log< level::Warning, false > LogWarning
std::vector< double >::const_iterator rotEnd(size_t ind) const
std::vector< double >::const_iterator tranStart(size_t ind) const
const GeomDet * idToDet(DetId) const override
Definition: CSCGeometry.cc:91