File indexing completed on 2024-04-06 11:58:33
0001
0002
0003
0004
0005
0006 #include "CalibPPS/AlignmentRelative/interface/AlignmentTask.h"
0007 #include "CalibPPS/AlignmentRelative/interface/AlignmentConstraint.h"
0008
0009 #include "DataFormats/CTPPSDetId/interface/CTPPSDetId.h"
0010 #include "DataFormats/CTPPSDetId/interface/TotemRPDetId.h"
0011
0012 #include "Geometry/VeryForwardGeometryBuilder/interface/CTPPSGeometry.h"
0013
0014 #include <algorithm>
0015
0016
0017
0018 using namespace std;
0019 using namespace edm;
0020
0021
0022
0023 AlignmentTask::AlignmentTask(const ParameterSet &ps)
0024 : resolveShR(ps.getParameter<bool>("resolveShR")),
0025 resolveShZ(ps.getParameter<bool>("resolveShZ")),
0026 resolveRotZ(ps.getParameter<bool>("resolveRotZ")),
0027
0028 oneRotZPerPot(ps.getParameter<bool>("oneRotZPerPot")),
0029 useEqualMeanUMeanVRotZConstraints(ps.getParameter<bool>("useEqualMeanUMeanVRotZConstraints")),
0030
0031 fixedDetectorsConstraints(ps.getParameterSet("fixedDetectorsConstraints")),
0032 standardConstraints(ps.getParameterSet("standardConstraints")) {
0033 if (resolveShR) {
0034 quantityClasses.push_back(qcShR1);
0035 quantityClasses.push_back(qcShR2);
0036 }
0037
0038 if (resolveShZ) {
0039 quantityClasses.push_back(qcShZ);
0040 }
0041
0042 if (resolveRotZ) {
0043 quantityClasses.push_back(qcRotZ);
0044 }
0045 }
0046
0047
0048
0049 void AlignmentTask::buildGeometry(const vector<unsigned int> &rpDecIds,
0050 const vector<unsigned int> &excludedSensors,
0051 const CTPPSGeometry *input,
0052 double z0,
0053 AlignmentGeometry &geometry) {
0054 geometry.z0 = z0;
0055
0056
0057 for (auto it = input->beginSensor(); it != input->endSensor(); ++it) {
0058
0059 if (find(excludedSensors.begin(), excludedSensors.end(), it->first) != excludedSensors.end())
0060 continue;
0061
0062
0063 const CTPPSDetId detId(it->first);
0064 const unsigned int rpDecId = 100 * detId.arm() + 10 * detId.station() + detId.rp();
0065 if (find(rpDecIds.begin(), rpDecIds.end(), rpDecId) == rpDecIds.end())
0066 continue;
0067
0068
0069 CTPPSGeometry::Vector c = input->localToGlobal(detId, CTPPSGeometry::Vector(0., 0., 0.));
0070 CTPPSGeometry::Vector d1 = input->localToGlobal(detId, CTPPSGeometry::Vector(1., 0., 0.)) - c;
0071 CTPPSGeometry::Vector d2 = input->localToGlobal(detId, CTPPSGeometry::Vector(0., 1., 0.)) - c;
0072
0073
0074 bool isU = false;
0075 if (detId.subdetId() == CTPPSDetId::sdTrackingStrip) {
0076 TotemRPDetId stripDetId(it->first);
0077 unsigned int rpNum = stripDetId.rp();
0078 unsigned int plNum = stripDetId.plane();
0079 isU = (plNum % 2 != 0);
0080 if (rpNum == 2 || rpNum == 3)
0081 isU = !isU;
0082 }
0083
0084 DetGeometry dg(c.z() - z0, c.x(), c.y(), isU);
0085 dg.setDirection(1, d1.x(), d1.y(), d1.z());
0086 dg.setDirection(2, d2.x(), d2.y(), d2.z());
0087 geometry.insert(it->first, dg);
0088 }
0089 }
0090
0091
0092
0093 void AlignmentTask::buildIndexMaps() {
0094
0095 mapMeasurementIndeces.clear();
0096 mapQuantityIndeces.clear();
0097
0098
0099 for (const auto &qcl : quantityClasses) {
0100
0101 mapMeasurementIndeces[qcl];
0102
0103
0104 unsigned int idxMeas = 0;
0105 unsigned int idxQuan = 0;
0106 for (const auto &git : geometry.getSensorMap()) {
0107 const unsigned int detId = git.first;
0108 const unsigned int subdetId = CTPPSDetId(git.first).subdetId();
0109
0110
0111 if (qcl == qcShR1) {
0112 if (subdetId == CTPPSDetId::sdTimingDiamond)
0113 mapMeasurementIndeces[qcl][{detId, 1}] = idxMeas++;
0114 if (subdetId == CTPPSDetId::sdTrackingPixel)
0115 mapMeasurementIndeces[qcl][{detId, 1}] = idxMeas++;
0116 }
0117
0118 if (qcl == qcShR2) {
0119 if (subdetId == CTPPSDetId::sdTrackingStrip)
0120 mapMeasurementIndeces[qcl][{detId, 2}] = idxMeas++;
0121 if (subdetId == CTPPSDetId::sdTrackingPixel)
0122 mapMeasurementIndeces[qcl][{detId, 2}] = idxMeas++;
0123 }
0124
0125 if (qcl == qcShZ) {
0126 if (subdetId == CTPPSDetId::sdTrackingStrip)
0127 mapMeasurementIndeces[qcl][{detId, 2}] = idxMeas++;
0128 if (subdetId == CTPPSDetId::sdTrackingPixel)
0129 mapMeasurementIndeces[qcl][{detId, 1}] = idxMeas++;
0130 if (subdetId == CTPPSDetId::sdTrackingPixel)
0131 mapMeasurementIndeces[qcl][{detId, 2}] = idxMeas++;
0132 if (subdetId == CTPPSDetId::sdTimingDiamond)
0133 mapMeasurementIndeces[qcl][{detId, 1}] = idxMeas++;
0134 }
0135
0136 if (qcl == qcRotZ) {
0137 if (subdetId == CTPPSDetId::sdTrackingStrip)
0138 mapMeasurementIndeces[qcl][{detId, 2}] = idxMeas++;
0139 if (subdetId == CTPPSDetId::sdTrackingPixel)
0140 mapMeasurementIndeces[qcl][{detId, 1}] = idxMeas++;
0141 if (subdetId == CTPPSDetId::sdTrackingPixel)
0142 mapMeasurementIndeces[qcl][{detId, 2}] = idxMeas++;
0143 if (subdetId == CTPPSDetId::sdTimingDiamond)
0144 mapMeasurementIndeces[qcl][{detId, 1}] = idxMeas++;
0145 }
0146
0147
0148 if (qcl == qcShR1) {
0149 if (subdetId == CTPPSDetId::sdTimingDiamond)
0150 mapQuantityIndeces[qcl][detId] = idxQuan++;
0151 if (subdetId == CTPPSDetId::sdTrackingPixel)
0152 mapQuantityIndeces[qcl][detId] = idxQuan++;
0153 }
0154
0155 if (qcl == qcShR2) {
0156 if (subdetId == CTPPSDetId::sdTrackingStrip)
0157 mapQuantityIndeces[qcl][detId] = idxQuan++;
0158 if (subdetId == CTPPSDetId::sdTrackingPixel)
0159 mapQuantityIndeces[qcl][detId] = idxQuan++;
0160 }
0161
0162 if (qcl == qcShZ) {
0163 if (subdetId == CTPPSDetId::sdTrackingStrip)
0164 mapQuantityIndeces[qcl][detId] = idxQuan++;
0165 if (subdetId == CTPPSDetId::sdTimingDiamond)
0166 mapQuantityIndeces[qcl][detId] = idxQuan++;
0167 if (subdetId == CTPPSDetId::sdTrackingPixel)
0168 mapQuantityIndeces[qcl][detId] = idxQuan++;
0169 }
0170
0171 if (qcl == qcRotZ) {
0172 if (subdetId == CTPPSDetId::sdTrackingStrip)
0173 mapQuantityIndeces[qcl][detId] = idxQuan++;
0174 if (subdetId == CTPPSDetId::sdTimingDiamond)
0175 mapQuantityIndeces[qcl][detId] = idxQuan++;
0176 if (subdetId == CTPPSDetId::sdTrackingPixel)
0177 mapQuantityIndeces[qcl][detId] = idxQuan++;
0178 }
0179 }
0180 }
0181 }
0182
0183
0184
0185 signed int AlignmentTask::getMeasurementIndex(QuantityClass cl, unsigned int detId, unsigned int dirIdx) const {
0186 auto clit = mapMeasurementIndeces.find(cl);
0187 if (clit == mapMeasurementIndeces.end())
0188 return -1;
0189
0190 auto it = clit->second.find({detId, dirIdx});
0191 if (it == clit->second.end())
0192 return -1;
0193
0194 return it->second;
0195 }
0196
0197
0198
0199 signed int AlignmentTask::getQuantityIndex(QuantityClass cl, unsigned int detId) const {
0200 auto clit = mapQuantityIndeces.find(cl);
0201 if (clit == mapQuantityIndeces.end())
0202 return -1;
0203
0204 auto it = clit->second.find(detId);
0205 if (it == clit->second.end())
0206 return -1;
0207
0208 return it->second;
0209 }
0210
0211
0212
0213 string AlignmentTask::quantityClassTag(QuantityClass qc) const {
0214 switch (qc) {
0215 case qcShR1:
0216 return "ShR1";
0217 case qcShR2:
0218 return "ShR2";
0219 case qcShZ:
0220 return "ShZ";
0221 case qcRotZ:
0222 return "RotZ";
0223 }
0224
0225 throw cms::Exception("PPS") << "Unknown quantity class " << qc << ".";
0226 }
0227
0228
0229
0230 unsigned int AlignmentTask::measurementsOfClass(QuantityClass qc) const {
0231 auto it = mapMeasurementIndeces.find(qc);
0232 if (it == mapMeasurementIndeces.end())
0233 return 0;
0234 else
0235 return it->second.size();
0236 }
0237
0238
0239
0240 unsigned int AlignmentTask::quantitiesOfClass(QuantityClass qc) const {
0241 auto it = mapQuantityIndeces.find(qc);
0242 if (it == mapQuantityIndeces.end())
0243 return 0;
0244 else
0245 return it->second.size();
0246 }
0247
0248
0249
0250 void AlignmentTask::buildFixedDetectorsConstraints(vector<AlignmentConstraint> &constraints) const {
0251 for (auto &quantityClass : quantityClasses) {
0252
0253 const string &tag = quantityClassTag(quantityClass);
0254
0255 const ParameterSet &classSettings = fixedDetectorsConstraints.getParameterSet(tag.c_str());
0256 vector<unsigned int> ids(classSettings.getParameter<vector<unsigned int>>("ids"));
0257 vector<double> values(classSettings.getParameter<vector<double>>("values"));
0258
0259 if (ids.size() != values.size())
0260 throw cms::Exception("PPS") << "Different number of constraint ids and values for " << tag << ".";
0261
0262
0263 unsigned int size = ids.size();
0264
0265
0266 if (oneRotZPerPot && quantityClass == qcRotZ) {
0267 if (size > 1)
0268 size = 1;
0269 }
0270
0271
0272 for (unsigned int j = 0; j < size; j++) {
0273
0274 AlignmentConstraint ac;
0275
0276 for (auto &qcit : quantityClasses) {
0277 ac.coef[qcit].ResizeTo(quantitiesOfClass(qcit));
0278 ac.coef[qcit].Zero();
0279 }
0280
0281
0282 char buf[40];
0283 sprintf(buf, "%s: fixed plane %4u", tag.c_str(), ids[j]);
0284 ac.name = buf;
0285
0286
0287 signed int qIndex = getQuantityIndex(quantityClass, ids[j]);
0288 if (qIndex < 0)
0289 throw cms::Exception("AlignmentTask::BuildFixedDetectorsConstraints")
0290 << "Quantity index for class " << quantityClass << " and id " << ids[j] << " is " << qIndex;
0291
0292
0293 ac.coef[quantityClass][qIndex] = 1.;
0294 ac.val = values[j] * 1E-3;
0295
0296
0297 constraints.push_back(ac);
0298 }
0299
0300 if (oneRotZPerPot && quantityClass == qcRotZ)
0301 buildOneRotZPerPotConstraints(constraints);
0302 }
0303 }
0304
0305
0306
0307 void AlignmentTask::buildStandardConstraints(vector<AlignmentConstraint> &constraints) const {
0308 const vector<unsigned int> &decUnitIds = standardConstraints.getParameter<vector<unsigned int>>("units");
0309
0310
0311 map<unsigned int, unsigned int> planesPerPot;
0312 for (const auto &it : geometry.getSensorMap()) {
0313 CTPPSDetId detId(it.first);
0314 planesPerPot[detId.rpId()]++;
0315 }
0316
0317
0318 if (resolveShR) {
0319 for (const auto &decUnitId : decUnitIds) {
0320
0321 AlignmentConstraint ac_X;
0322 for (auto &qcit : quantityClasses) {
0323 ac_X.coef[qcit].ResizeTo(quantitiesOfClass(qcit));
0324 ac_X.coef[qcit].Zero();
0325 }
0326 ac_X.val = 0;
0327
0328 AlignmentConstraint ac_Y(ac_X);
0329
0330
0331 char buf[50];
0332 sprintf(buf, "ShR: unit %u, MeanX=0", decUnitId);
0333 ac_X.name = buf;
0334 sprintf(buf, "ShR: unit %u, MeanY=0", decUnitId);
0335 ac_Y.name = buf;
0336
0337
0338 for (const auto &git : geometry.getSensorMap()) {
0339
0340 CTPPSDetId senId(git.first);
0341 unsigned int senDecUnit = senId.arm() * 100 + senId.station() * 10;
0342 if (senId.rp() > 2)
0343 senDecUnit += 1;
0344
0345 if (senDecUnit != decUnitId)
0346 continue;
0347
0348
0349 if (senId.subdetId() == CTPPSDetId::sdTrackingStrip) {
0350 signed int qIndex = getQuantityIndex(qcShR2, git.first);
0351 if (qIndex < 0)
0352 throw cms::Exception("AlignmentTask::BuildStandardConstraints")
0353 << "Cannot get quantity index for class " << qcShR2 << " and sensor id " << git.first << ".";
0354
0355
0356 const double weight = 1. / planesPerPot[senId.rpId()];
0357
0358
0359 ac_X.coef[qcShR2][qIndex] = git.second.getDirectionData(2).dx * weight;
0360 ac_Y.coef[qcShR2][qIndex] = git.second.getDirectionData(2).dy * weight;
0361 }
0362
0363
0364 if (senId.subdetId() == CTPPSDetId::sdTrackingPixel) {
0365
0366 const signed int qIndex1 = getQuantityIndex(qcShR1, git.first);
0367 if (qIndex1 < 0)
0368 throw cms::Exception("AlignmentTask::BuildStandardConstraints")
0369 << "Cannot get quantity index for class " << qcShR1 << " and sensor id " << git.first << ".";
0370
0371 const signed int qIndex2 = getQuantityIndex(qcShR2, git.first);
0372 if (qIndex2 < 0)
0373 throw cms::Exception("AlignmentTask::BuildStandardConstraints")
0374 << "Cannot get quantity index for class " << qcShR2 << " and sensor id " << git.first << ".";
0375
0376
0377 const double weight = 0.5 / planesPerPot[senId.rpId()];
0378
0379
0380 const double d1x = git.second.getDirectionData(1).dx;
0381 const double d1y = git.second.getDirectionData(1).dy;
0382 const double d2x = git.second.getDirectionData(2).dx;
0383 const double d2y = git.second.getDirectionData(2).dy;
0384
0385
0386
0387
0388 const double D = d1x * d2y - d1y * d2x;
0389 const double coef_x_s1 = +d2y / D;
0390 const double coef_y_s1 = -d2x / D;
0391 const double coef_x_s2 = -d1y / D;
0392 const double coef_y_s2 = +d1x / D;
0393
0394
0395 ac_X.coef[qcShR1][qIndex1] = coef_x_s1 * weight;
0396 ac_Y.coef[qcShR1][qIndex1] = coef_y_s1 * weight;
0397 ac_X.coef[qcShR2][qIndex2] = coef_x_s2 * weight;
0398 ac_Y.coef[qcShR2][qIndex2] = coef_y_s2 * weight;
0399 }
0400 }
0401
0402
0403 constraints.push_back(ac_X);
0404 constraints.push_back(ac_Y);
0405 }
0406 }
0407
0408
0409 if (resolveRotZ) {
0410 for (const auto &decUnitId : decUnitIds) {
0411
0412 AlignmentConstraint ac;
0413 for (unsigned int i = 0; i < quantityClasses.size(); i++) {
0414 ac.coef[quantityClasses[i]].ResizeTo(quantitiesOfClass(quantityClasses[i]));
0415 ac.coef[quantityClasses[i]].Zero();
0416 }
0417 ac.val = 0;
0418
0419 char buf[50];
0420 sprintf(buf, "RotZ: unit %u, Mean=0", decUnitId);
0421 ac.name = buf;
0422
0423
0424 for (const auto &git : geometry.getSensorMap()) {
0425
0426 CTPPSDetId senId(git.first);
0427 unsigned int senDecUnit = senId.arm() * 100 + senId.station() * 10;
0428 if (senId.rp() > 2)
0429 senDecUnit += 1;
0430
0431 if (senDecUnit != decUnitId)
0432 continue;
0433
0434
0435 const double weight = 1. / planesPerPot[senId.rpId()];
0436
0437
0438 signed int qIndex = getQuantityIndex(qcRotZ, git.first);
0439 ac.coef[qcRotZ][qIndex] = weight;
0440 }
0441
0442 constraints.push_back(ac);
0443 }
0444 }
0445
0446 if (resolveRotZ && oneRotZPerPot)
0447 buildOneRotZPerPotConstraints(constraints);
0448
0449 if (resolveRotZ && useEqualMeanUMeanVRotZConstraints)
0450 buildEqualMeanUMeanVRotZConstraints(constraints);
0451 }
0452
0453
0454
0455 void AlignmentTask::buildOneRotZPerPotConstraints(std::vector<AlignmentConstraint> &constraints) const {
0456
0457 map<unsigned int, vector<unsigned int>> m;
0458 for (const auto &p : geometry.getSensorMap()) {
0459 CTPPSDetId detId(p.first);
0460 CTPPSDetId rpId = detId.rpId();
0461 unsigned int decRPId = rpId.arm() * 100 + rpId.station() * 10 + rpId.rp();
0462 m[decRPId].push_back(p.first);
0463 }
0464
0465
0466 for (const auto &p : m) {
0467
0468 unsigned int prev_detId = 0;
0469 for (const auto &detId : p.second) {
0470 if (prev_detId != 0) {
0471 AlignmentConstraint ac;
0472
0473 char buf[100];
0474 sprintf(buf, "RotZ: RP %u, plane %u = plane %u", p.first, prev_detId, detId);
0475 ac.name = buf;
0476
0477 ac.val = 0;
0478
0479 for (auto &qcit : quantityClasses) {
0480 ac.coef[qcit].ResizeTo(quantitiesOfClass(qcit));
0481 ac.coef[qcit].Zero();
0482 }
0483
0484 signed int qIdx1 = getQuantityIndex(qcRotZ, prev_detId);
0485 signed int qIdx2 = getQuantityIndex(qcRotZ, detId);
0486
0487 ac.coef[qcRotZ][qIdx1] = +1.;
0488 ac.coef[qcRotZ][qIdx2] = -1.;
0489
0490 constraints.push_back(ac);
0491 }
0492
0493 prev_detId = detId;
0494 }
0495 }
0496 }
0497
0498
0499
0500 void AlignmentTask::buildEqualMeanUMeanVRotZConstraints(vector<AlignmentConstraint> &constraints) const {
0501
0502 map<unsigned int, pair<vector<unsigned int>, vector<unsigned int>>> m;
0503 for (const auto &p : geometry.getSensorMap()) {
0504 CTPPSDetId detId(p.first);
0505
0506 if (detId.subdetId() != CTPPSDetId::sdTrackingStrip)
0507 continue;
0508
0509 CTPPSDetId rpId = detId.rpId();
0510 unsigned int decRPId = rpId.arm() * 100 + rpId.station() * 10 + rpId.rp();
0511
0512 if (p.second.isU)
0513 m[decRPId].first.push_back(p.first);
0514 else
0515 m[decRPId].second.push_back(p.first);
0516 }
0517
0518
0519 for (const auto &p : m) {
0520 AlignmentConstraint ac;
0521
0522 char buf[100];
0523 sprintf(buf, "RotZ: RP %u, MeanU = MeanV", p.first);
0524 ac.name = buf;
0525
0526 ac.val = 0;
0527
0528 for (auto &qcit : quantityClasses) {
0529 ac.coef[qcit].ResizeTo(quantitiesOfClass(qcit));
0530 ac.coef[qcit].Zero();
0531 }
0532
0533 for (auto &&proj : {"U", "V"}) {
0534 const auto &planes = (proj == string("U")) ? p.second.first : p.second.second;
0535 const double c = ((proj == string("U")) ? -1. : +1.) / planes.size();
0536
0537 for (const auto &plane : planes) {
0538 signed int qIdx = getQuantityIndex(qcRotZ, plane);
0539 ac.coef[qcRotZ][qIdx] = c;
0540
0541 TotemRPDetId plId(plane);
0542 }
0543 }
0544
0545 constraints.push_back(ac);
0546 }
0547 }