CMS 3D CMS Logo

IdealResult.cc
Go to the documentation of this file.
1 /****************************************************************************
2 * Authors:
3 * Jan Kašpar (jan.kaspar@gmail.com)
4 ****************************************************************************/
5 
7 
9 
12 
13 #include "TMatrixD.h"
14 #include "TVectorD.h"
15 
16 using namespace std;
17 
18 //----------------------------------------------------------------------------------------------------
19 
21 
22 //----------------------------------------------------------------------------------------------------
23 
24 void IdealResult::begin(const CTPPSGeometry *geometryReal, const CTPPSGeometry *geometryMisaligned) {
25  gReal = geometryReal;
26  gMisaligned = geometryMisaligned;
27 }
28 //----------------------------------------------------------------------------------------------------
29 
30 unsigned int IdealResult::solve(const std::vector<AlignmentConstraint> &constraints,
31  std::map<unsigned int, AlignmentResult> &results,
32  TDirectory *dir) {
33  /*
34  STRATEGY:
35 
36  1) Determine true misalignment as misalign_geometry - real_geometry.
37 
38  2) Represent the true misalignment as the "chi" vector (cf. Jan algorithm), denoted chi_tr.
39 
40  3) Find the expected result of track-based alignment, subject to the given constraints. Formally this corresponds to finding
41  chi_exp = chi_tr + I * Lambda
42  where the I matrix contains the "inaccessible alignment modes" as columns and Lambda is a vector of parameters. The constraints are given by
43  C^T * chi_exp = V
44  Since the problem may be generally overconstrained, it is better to formulate it as search for Lambda which minimises
45  |C^ * chi_exp - V|^2
46  This gives
47  Lambda = (A^T * A)^-1 * A^T * b, A = C^T * I, b = V - C^T * chi_tr
48  */
49 
50  results.clear();
51 
52  // determine dimension and offsets
53  unsigned int dim = 0;
54  vector<unsigned int> offsets;
55  map<unsigned int, unsigned int> offset_map;
56  for (unsigned int qci = 0; qci < task->quantityClasses.size(); qci++) {
57  offsets.push_back(dim);
58  offset_map[task->quantityClasses[qci]] = dim;
60  }
61 
62  // collect true misalignments
63  TVectorD chi_tr(dim);
64 
65  for (const auto &dit : task->geometry.getSensorMap()) {
66  unsigned int detId = dit.first;
67 
68  const DetGeomDesc *real = gReal->sensor(detId);
69  const DetGeomDesc *misal = gMisaligned->sensor(detId);
70 
71  // extract shift
72  const auto shift = misal->translation() - real->translation();
73 
74  // extract rotation around z
75  const auto rotation = misal->rotation() * real->rotation().Inverse();
76 
77  double r_xx, r_xy, r_xz;
78  double r_yx, r_yy, r_yz;
79  double r_zx, r_zy, r_zz;
80  rotation.GetComponents(r_xx, r_xy, r_xz, r_yx, r_yy, r_yz, r_zx, r_zy, r_zz);
81 
82  if (std::abs(r_zz - 1.) > 1E-5)
83  throw cms::Exception("PPS") << "IdealResult::Solve: only rotations about z are supported.";
84 
85  double rot_z = atan2(r_yx, r_xx);
86 
87  const auto &geom = task->geometry.get(detId);
88 
89  for (unsigned int qci = 0; qci < task->quantityClasses.size(); ++qci) {
90  const auto &qc = task->quantityClasses[qci];
91  signed int idx = task->getQuantityIndex(qc, detId);
92  if (idx < 0)
93  continue;
94 
95  double v = 0.;
96 
97  if (qc == AlignmentTask::qcShR1) {
98  const auto &d = geom.getDirectionData(1);
99  v = shift.x() * d.dx + shift.y() * d.dy + shift.z() * d.dz;
100  }
101 
102  if (qc == AlignmentTask::qcShR2) {
103  const auto &d = geom.getDirectionData(2);
104  v = shift.x() * d.dx + shift.y() * d.dy + shift.z() * d.dz;
105  }
106 
107  if (qc == AlignmentTask::qcRotZ)
108  v = rot_z;
109 
110  chi_tr(offsets[qci] + idx) = v;
111  }
112  }
113 
114  // build list of "inaccessible" modes
115  vector<TVectorD> inaccessibleModes;
116 
117  if (task->resolveShR) {
118  TVectorD fm_ShX_gl(dim);
119  fm_ShX_gl.Zero();
120  TVectorD fm_ShX_lp(dim);
121  fm_ShX_lp.Zero();
122  TVectorD fm_ShY_gl(dim);
123  fm_ShY_gl.Zero();
124  TVectorD fm_ShY_lp(dim);
125  fm_ShY_lp.Zero();
126 
127  for (const auto &sp : task->geometry.getSensorMap()) {
128  CTPPSDetId senId(sp.first);
129  const auto &geom = sp.second;
130 
131  if (senId.subdetId() == CTPPSDetId::sdTrackingStrip) {
132  signed int qIndex = task->getQuantityIndex(AlignmentTask::qcShR2, senId);
133 
134  const double d2x = geom.getDirectionData(2).dx;
135  const double d2y = geom.getDirectionData(2).dy;
136 
137  const auto &offset2 = offset_map[AlignmentTask::qcShR2];
138  fm_ShX_gl(offset2 + qIndex) = d2x;
139  fm_ShX_lp(offset2 + qIndex) = d2x * geom.z;
140  fm_ShY_gl(offset2 + qIndex) = d2y;
141  fm_ShY_lp(offset2 + qIndex) = d2y * geom.z;
142  }
143 
144  if (senId.subdetId() == CTPPSDetId::sdTrackingPixel) {
145  const signed int qIndex1 = task->getQuantityIndex(AlignmentTask::qcShR1, senId);
146  const signed int qIndex2 = task->getQuantityIndex(AlignmentTask::qcShR2, senId);
147 
148  const double d1x = geom.getDirectionData(1).dx;
149  const double d1y = geom.getDirectionData(1).dy;
150  const double d2x = geom.getDirectionData(2).dx;
151  const double d2y = geom.getDirectionData(2).dy;
152 
153  const auto &offset1 = offset_map[AlignmentTask::qcShR1];
154  fm_ShX_gl(offset1 + qIndex1) = d1x;
155  fm_ShX_lp(offset1 + qIndex1) = d1x * geom.z;
156  fm_ShY_gl(offset1 + qIndex1) = d1y;
157  fm_ShY_lp(offset1 + qIndex1) = d1y * geom.z;
158 
159  const auto &offset2 = offset_map[AlignmentTask::qcShR2];
160  fm_ShX_gl(offset2 + qIndex2) = d2x;
161  fm_ShX_lp(offset2 + qIndex2) = d2x * geom.z;
162  fm_ShY_gl(offset2 + qIndex2) = d2y;
163  fm_ShY_lp(offset2 + qIndex2) = d2y * geom.z;
164  }
165  }
166 
167  inaccessibleModes.push_back(fm_ShX_gl);
168  inaccessibleModes.push_back(fm_ShX_lp);
169  inaccessibleModes.push_back(fm_ShY_gl);
170  inaccessibleModes.push_back(fm_ShY_lp);
171  }
172 
173  if (task->resolveRotZ) {
174  TVectorD fm_RotZ_gl(dim);
175  fm_RotZ_gl.Zero();
176  TVectorD fm_RotZ_lp(dim);
177  fm_RotZ_lp.Zero();
178 
179  for (const auto &sp : task->geometry.getSensorMap()) {
180  CTPPSDetId senId(sp.first);
181  const auto &geom = sp.second;
182 
183  for (int m = 0; m < 2; ++m) {
184  double rho = 0.;
185  TVectorD *fmp = nullptr;
186  if (m == 0) {
187  rho = 1.;
188  fmp = &fm_RotZ_gl;
189  }
190  if (m == 1) {
191  rho = geom.z;
192  fmp = &fm_RotZ_lp;
193  }
194  TVectorD &fm = *fmp;
195 
196  const signed int qIndex = task->getQuantityIndex(AlignmentTask::qcRotZ, senId);
197  const auto &offset = offset_map[AlignmentTask::qcRotZ];
198  fm(offset + qIndex) = rho;
199 
200  const double as_x = -rho * geom.sy;
201  const double as_y = +rho * geom.sx;
202 
203  if (senId.subdetId() == CTPPSDetId::sdTrackingStrip) {
204  const double d2x = geom.getDirectionData(2).dx;
205  const double d2y = geom.getDirectionData(2).dy;
206 
207  const signed int qIndex2 = task->getQuantityIndex(AlignmentTask::qcShR2, senId);
208  const auto &offset2 = offset_map[AlignmentTask::qcShR2];
209  fm(offset2 + qIndex2) = d2x * as_x + d2y * as_y;
210  }
211 
212  if (senId.subdetId() == CTPPSDetId::sdTrackingPixel) {
213  const double d1x = geom.getDirectionData(1).dx;
214  const double d1y = geom.getDirectionData(1).dy;
215  const double d2x = geom.getDirectionData(2).dx;
216  const double d2y = geom.getDirectionData(2).dy;
217 
218  const signed int qIndex1 = task->getQuantityIndex(AlignmentTask::qcShR1, senId);
219  const auto &offset1 = offset_map[AlignmentTask::qcShR1];
220  fm(offset1 + qIndex1) = d1x * as_x + d1y * as_y;
221 
222  const signed int qIndex2 = task->getQuantityIndex(AlignmentTask::qcShR2, senId);
223  const auto &offset2 = offset_map[AlignmentTask::qcShR2];
224  fm(offset2 + qIndex2) = d2x * as_x + d2y * as_y;
225  }
226  }
227  }
228 
229  inaccessibleModes.push_back(fm_RotZ_gl);
230  inaccessibleModes.push_back(fm_RotZ_lp);
231  }
232 
233  // build matrices and vectors
234  TMatrixD C(dim, constraints.size());
235  TVectorD V(constraints.size());
236  for (unsigned int i = 0; i < constraints.size(); i++) {
237  V(i) = constraints[i].val;
238 
239  unsigned int offset = 0;
240  for (auto &quantityClass : task->quantityClasses) {
241  const TVectorD &cv = constraints[i].coef.find(quantityClass)->second;
242  for (int k = 0; k < cv.GetNrows(); k++) {
243  C[offset][i] = cv[k];
244  offset++;
245  }
246  }
247  }
248 
249  TMatrixD I(dim, inaccessibleModes.size());
250  for (unsigned int i = 0; i < inaccessibleModes.size(); ++i) {
251  for (int j = 0; j < inaccessibleModes[i].GetNrows(); ++j)
252  I(j, i) = inaccessibleModes[i](j);
253  }
254 
255  // determine expected track-based alignment result
256  TMatrixD CT(TMatrixD::kTransposed, C);
257  TMatrixD CTI(CT * I);
258 
259  const TMatrixD &A = CTI;
260  TMatrixD AT(TMatrixD::kTransposed, A);
261  TMatrixD ATA(AT * A);
262  TMatrixD ATA_inv(TMatrixD::kInverted, ATA);
263 
264  TVectorD b = V - CT * chi_tr;
265 
266  TVectorD La(ATA_inv * AT * b);
267 
268  TVectorD chi_exp(chi_tr + I * La);
269 
270  // save result
271  for (const auto &dit : task->geometry.getSensorMap()) {
273 
274  for (unsigned int qci = 0; qci < task->quantityClasses.size(); ++qci) {
275  const auto &qc = task->quantityClasses[qci];
276  const auto idx = task->getQuantityIndex(qc, dit.first);
277  if (idx < 0)
278  continue;
279 
280  const auto &v = chi_exp(offsets[qci] + idx);
281 
282  switch (qc) {
284  r.setShR1(v);
285  break;
287  r.setShR2(v);
288  break;
290  r.setShZ(v);
291  break;
293  r.setRotZ(v);
294  break;
295  }
296  }
297 
298  results[dit.first] = r;
299  }
300 
301  return 0;
302 }
AlignmentTask * task
the tasked to be completed
const Translation & translation() const
Definition: DetGeomDesc.h:80
const std::map< unsigned int, DetGeometry > & getSensorMap() const
IdealResult()
dummy constructor (not to be used)
Definition: IdealResult.h:30
cv
Definition: cuy.py:363
std::vector< QuantityClass > quantityClasses
list of quantity classes to be optimized
Definition: AlignmentTask.h:68
Abstract parent for all (track-based) alignment algorithms.
unsigned int solve(const std::vector< AlignmentConstraint > &, std::map< unsigned int, AlignmentResult > &result, TDirectory *dir) override
Definition: IdealResult.cc:30
bool resolveRotZ
whether to resolve detector rotations around z
Definition: AlignmentTask.h:31
Represents an alignment task.
Definition: AlignmentTask.h:20
uint32_t T const *__restrict__ uint32_t const *__restrict__ int32_t int Histo::index_type cudaStream_t V
detector shifts in first readout direction
Definition: AlignmentTask.h:61
edm::ESHandle< CTPPSGeometry > gMisaligned
Definition: IdealResult.h:26
AlignmentGeometry geometry
the geometry for this task
Definition: AlignmentTask.h:48
void begin(const CTPPSGeometry *geometryReal, const CTPPSGeometry *geometryMisaligned) override
prepare for processing
Definition: IdealResult.cc:24
const DetGeomDesc * sensor(unsigned int id) const
returns geometry of a detector performs necessary checks, returns NULL if fails
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
const std::complex< double > I
Definition: I.h:8
constexpr int subdetId() const
get the contents of the subdetector field (not cast into any detector&#39;s numbering enum) ...
Definition: DetId.h:48
d
Definition: ztail.py:151
The manager class for TOTEM RP geometry.
Definition: CTPPSGeometry.h:30
detector shifts in second readout direction
Definition: AlignmentTask.h:62
signed int getQuantityIndex(QuantityClass cl, unsigned int detId) const
returns measurement index (if non-existent, returns -1)
edm::ESHandle< CTPPSGeometry > gReal
Definition: IdealResult.h:26
bool resolveShR
whether to resolve detector shifts in readout direction(s)
Definition: AlignmentTask.h:25
detector rotations around z
Definition: AlignmentTask.h:64
double b
Definition: hdecay.h:118
Result of CTPPS track-based alignment.
const RotationMatrix & rotation() const
Definition: DetGeomDesc.h:81
Base class for CTPPS detector IDs.
Definition: CTPPSDetId.h:32
const DetGeometry & get(unsigned int id) const
retrieves sensor geometry
static unsigned int const shift
unsigned int quantitiesOfClass(QuantityClass) const
returns the number of quantities of the given class
Definition: APVGainStruct.h:7
detector shifts in z
Definition: AlignmentTask.h:63