File indexing completed on 2024-09-18 05:06:26
0001
0002
0003 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0004 #include "FWCore/Utilities/interface/Parse.h"
0005
0006 #include "Alignment/CommonAlignment/interface/Utilities.h"
0007
0008 align::EulerAngles align::toAngles(const RotationType& rot) {
0009 const Scalar one = 1;
0010
0011 EulerAngles angles(3);
0012
0013 if (std::abs(rot.zx()) > one) {
0014 edm::LogWarning("Alignment") << "Rounding errors in\n" << rot;
0015 }
0016
0017 if (std::abs(rot.zx()) < one) {
0018 angles(1) = -std::atan2(rot.zy(), rot.zz());
0019 angles(2) = std::asin(rot.zx());
0020 angles(3) = -std::atan2(rot.yx(), rot.xx());
0021 } else if (rot.zx() >= one) {
0022 angles(1) = std::atan2(rot.xy() + rot.yz(), rot.yy() - rot.xz());
0023 angles(2) = std::asin(one);
0024 angles(3) = 0;
0025 } else if (rot.zx() <= -one) {
0026 angles(1) = std::atan2(rot.xy() - rot.yz(), rot.yy() + rot.xz());
0027 angles(2) = std::asin(-one);
0028 angles(3) = 0;
0029 }
0030
0031 return angles;
0032 }
0033
0034 align::RotationType align::toMatrix(const EulerAngles& angles) {
0035 Scalar s1 = std::sin(angles[0]), c1 = std::cos(angles[0]);
0036 Scalar s2 = std::sin(angles[1]), c2 = std::cos(angles[1]);
0037 Scalar s3 = std::sin(angles[2]), c3 = std::cos(angles[2]);
0038
0039 return RotationType(c2 * c3,
0040 c1 * s3 + s1 * s2 * c3,
0041 s1 * s3 - c1 * s2 * c3,
0042 -c2 * s3,
0043 c1 * c3 - s1 * s2 * s3,
0044 s1 * c3 + c1 * s2 * s3,
0045 s2,
0046 -s1 * c2,
0047 c1 * c2);
0048 }
0049
0050 align::PositionType align::motherPosition(const std::vector<const PositionType*>& dauPos) {
0051 unsigned int nDau = dauPos.size();
0052
0053 Scalar posX(0.), posY(0.), posZ(0.);
0054
0055 for (unsigned int i = 0; i < nDau; ++i) {
0056 const PositionType* point = dauPos[i];
0057
0058 posX += point->x();
0059 posY += point->y();
0060 posZ += point->z();
0061 }
0062
0063 Scalar inv = 1. / static_cast<Scalar>(nDau);
0064
0065 return PositionType(posX * inv, posY * inv, posZ * inv);
0066 }
0067
0068 align::RotationType align::diffRot(const GlobalVectors& current, const GlobalVectors& nominal) {
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098 static const double tolerance = 1e-12;
0099
0100 RotationType rot;
0101
0102
0103
0104 AlgebraicSymMatrix I(3);
0105
0106 GlobalVectors rotated = current;
0107
0108 unsigned int nPoints = nominal.size();
0109
0110 for (unsigned int j = 0; j < nPoints; ++j) {
0111 const GlobalVector& r = nominal[j];
0112
0113
0114 I.fast(1, 1) += r.y() * r.y() + r.z() * r.z();
0115 I.fast(2, 2) += r.x() * r.x() + r.z() * r.z();
0116 I.fast(3, 3) += r.y() * r.y() + r.x() * r.x();
0117 I.fast(2, 1) -= r.x() * r.y();
0118 I.fast(3, 1) -= r.x() * r.z();
0119 I.fast(3, 2) -= r.y() * r.z();
0120 }
0121 int count = 0;
0122 while (true) {
0123 AlgebraicVector rhs(3);
0124
0125 for (unsigned int j = 0; j < nPoints; ++j) {
0126 const GlobalVector& r = nominal[j];
0127 const GlobalVector& c = rotated[j];
0128
0129
0130
0131 rhs(1) += c.y() * r.z() - c.z() * r.y();
0132 rhs(2) += c.z() * r.x() - c.x() * r.z();
0133 rhs(3) += c.x() * r.y() - c.y() * r.x();
0134 }
0135
0136 EulerAngles dOmega = CLHEP::solve(I, rhs);
0137
0138 rot *= toMatrix(dOmega);
0139
0140 if (dOmega.normsq() < tolerance)
0141 break;
0142 count++;
0143 if (count > 100000) {
0144 std::cout << "diffRot infinite loop: dOmega is " << dOmega.normsq() << "\n";
0145 break;
0146 }
0147
0148
0149
0150 for (unsigned int j = 0; j < nPoints; ++j) {
0151 rotated[j] = GlobalVector(rot.multiplyInverse(current[j].basicVector()));
0152 }
0153 }
0154
0155 return rot;
0156 }
0157
0158 align::GlobalVector align::diffR(const GlobalVectors& current, const GlobalVectors& nominal) {
0159 GlobalVector nCM(0, 0, 0);
0160 GlobalVector cCM(0, 0, 0);
0161
0162 unsigned int nPoints = nominal.size();
0163
0164 for (unsigned int j = 0; j < nPoints; ++j) {
0165 nCM += nominal[j];
0166 cCM += current[j];
0167 }
0168
0169 nCM -= cCM;
0170
0171 return nCM /= static_cast<Scalar>(nPoints);
0172 }
0173
0174 align::GlobalVector align::centerOfMass(const GlobalVectors& theVs) {
0175 unsigned int nPoints = theVs.size();
0176
0177 GlobalVector CM(0, 0, 0);
0178
0179 for (unsigned int j = 0; j < nPoints; ++j)
0180 CM += theVs[j];
0181
0182 return CM /= static_cast<Scalar>(nPoints);
0183 }
0184
0185 void align::rectify(RotationType& rot) {
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199 rot = toMatrix(toAngles(rot));
0200 }
0201
0202 align::RunRanges align::makeNonOverlappingRunRanges(const edm::VParameterSet& runRanges, const RunNumber& defaultRun) {
0203 const auto beginValue = cond::timeTypeSpecs[cond::runnumber].beginValue;
0204 const auto endValue = cond::timeTypeSpecs[cond::runnumber].endValue;
0205 RunRanges uniqueRunRanges;
0206 if (!runRanges.empty()) {
0207 std::map<RunNumber, RunNumber> uniqueFirstRunNumbers;
0208 for (const auto& ipset : runRanges) {
0209 const auto RunRangeStrings = ipset.getParameter<std::vector<std::string> >("RunRanges");
0210 for (const auto& irange : RunRangeStrings) {
0211 if (irange.find(':') == std::string::npos) {
0212 long int temp{strtol(irange.c_str(), nullptr, 0)};
0213 auto first = (temp != -1) ? temp : beginValue;
0214 uniqueFirstRunNumbers[first] = first;
0215 } else {
0216 edm::LogWarning("BadConfig") << "@SUB=align::makeNonOverlappingRunRanges"
0217 << "Config file contains old format for 'RunRangeSelection'. Only "
0218 << "the start run number is used internally. The number of the last"
0219 << " run is ignored and can besafely removed from the config file.";
0220 auto tokens = edm::tokenize(irange, ":");
0221 long int temp{strtol(tokens[0].c_str(), nullptr, 0)};
0222 auto first = (temp != -1) ? temp : beginValue;
0223 uniqueFirstRunNumbers[first] = first;
0224 }
0225 }
0226 }
0227
0228 for (const auto& iFirst : uniqueFirstRunNumbers) {
0229 uniqueRunRanges.push_back(std::make_pair(iFirst.first, endValue));
0230 }
0231 for (unsigned int i = 0; i < uniqueRunRanges.size() - 1; ++i) {
0232 uniqueRunRanges[i].second = uniqueRunRanges[i + 1].first - 1;
0233 }
0234 } else {
0235 uniqueRunRanges.push_back(std::make_pair(defaultRun, endValue));
0236 }
0237
0238 return uniqueRunRanges;
0239 }
0240
0241 align::RunRanges align::makeUniqueRunRanges(const edm::VParameterSet& runRanges, const RunNumber& defaultRun) {
0242 auto uniqueRunRanges = align::makeNonOverlappingRunRanges(runRanges, defaultRun);
0243 if (uniqueRunRanges.empty()) {
0244 const RunRange runRange(defaultRun, cond::timeTypeSpecs[cond::runnumber].endValue);
0245 uniqueRunRanges.push_back(runRange);
0246 }
0247 return uniqueRunRanges;
0248 }