00001 #include <iostream>
00002
00003 #include "CLHEP/Matrix/Matrix.h"
00004 #include "TMatrixDEigen.h"
00005
00006 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00007
00008 #include "Alignment/MuonAlignmentAlgorithms/plugins/CSCChamberFitter.h"
00009
00010 const double infinity = 0.1;
00011
00012
00013 CSCChamberFitter::CSCChamberFitter(const edm::ParameterSet &iConfig, std::vector<CSCPairResidualsConstraint*> &residualsConstraints) {
00014 m_name = iConfig.getParameter<std::string>("name");
00015 m_alignables = iConfig.getParameter<std::vector<std::string> >("alignables");
00016 if (m_alignables.size() == 0) {
00017 throw cms::Exception("BadConfig") << "Fitter " << m_name << " has no alignables!" << std::endl;
00018 }
00019
00020 int i = 0;
00021 for (std::vector<std::string>::const_iterator alignable = m_alignables.begin(); alignable != m_alignables.end(); ++alignable) {
00022 if (alignableId(*alignable) == -1) m_frames.push_back(i);
00023 i++;
00024 }
00025
00026 m_fixed = -1;
00027 std::string fixed = iConfig.getParameter<std::string>("fixed");
00028 if (fixed != "") {
00029 int i = 0;
00030 for (std::vector<std::string>::const_iterator alignable = m_alignables.begin(); alignable != m_alignables.end(); ++alignable) {
00031 if (fixed == *alignable) {
00032 m_fixed = i;
00033 }
00034 i++;
00035 }
00036 if (m_fixed == -1) throw cms::Exception("BadConfig") << "Cannot fix unrecognized alignable " << fixed << std::endl;
00037 }
00038
00039 int numConstraints = 0;
00040 std::vector<edm::ParameterSet> constraints = iConfig.getParameter<std::vector<edm::ParameterSet> >("constraints");
00041 for (std::vector<edm::ParameterSet>::const_iterator constraint = constraints.begin(); constraint != constraints.end(); ++constraint) {
00042 int i = index(constraint->getParameter<std::string>("i"));
00043 int j = index(constraint->getParameter<std::string>("j"));
00044 double value = constraint->getParameter<double>("value");
00045 double error = constraint->getParameter<double>("error");
00046
00047 if (i < 0) throw cms::Exception("BadConfig") << "Unrecognized alignable " << constraint->getParameter<std::string>("i") << " in constraint " << numConstraints << " of fitter " << m_name << std::endl;
00048 if (j < 0) throw cms::Exception("BadConfig") << "Unrecognized alignable " << constraint->getParameter<std::string>("j") << " in constraint " << numConstraints << " of fitter " << m_name << std::endl;
00049 if (error <= 0.) throw cms::Exception("BadConfig") << "Non-positive uncertainty in constraint " << numConstraints << " of fitter " << m_name << std::endl;
00050 if (i == j) throw cms::Exception("BadConfig") << "Self-connection from " << constraint->getParameter<std::string>("i") << " to " << constraint->getParameter<std::string>("j") << " is not allowed in constraint " << numConstraints << " of fitter " << m_name << std::endl;
00051
00052 m_constraints.push_back(new CSCPairConstraint(i, j, value, error));
00053 numConstraints++;
00054 }
00055
00056
00057 for (unsigned int i = 0; i < m_alignables.size(); i++) {
00058 std::string alignable_i = m_alignables[i];
00059 long id_i = alignableId(alignable_i);
00060 if (id_i != -1) {
00061 CSCDetId cscid_i(id_i);
00062
00063 for (unsigned int j = 0; j < m_alignables.size(); j++) {
00064 std::string alignable_j = m_alignables[j];
00065 long id_j = alignableId(alignable_j);
00066 if (i != j && id_j != -1) {
00067 CSCDetId cscid_j(id_j);
00068
00069 if (!(cscid_i.station() == 1 && cscid_i.ring() == 3 && cscid_j.station() == 1 && cscid_j.ring() == 3)) {
00070
00071 int next_chamber = cscid_i.chamber() + 1;
00072 if (cscid_i.station() > 1 && cscid_i.ring() == 1 && next_chamber == 19) next_chamber = 1;
00073 else if (!(cscid_i.station() > 1 && cscid_i.ring() == 1) && next_chamber == 37) next_chamber = 1;
00074 if (cscid_i.endcap() == cscid_j.endcap() && cscid_i.station() == cscid_j.station() && cscid_i.ring() == cscid_j.ring() && next_chamber == cscid_j.chamber()) {
00075
00076 CSCPairResidualsConstraint *residualsConstraint = new CSCPairResidualsConstraint(residualsConstraints.size(), i, j, cscid_i, cscid_j);
00077 m_constraints.push_back(residualsConstraint);
00078 residualsConstraints.push_back(residualsConstraint);
00079 numConstraints++;
00080 }
00081 }
00082 }
00083 }
00084 }
00085 }
00086
00087 std::map<int,bool> touched;
00088 for (unsigned int i = 0; i < m_alignables.size(); i++) touched[i] = false;
00089 walk(touched, 0);
00090 for (unsigned int i = 0; i < m_alignables.size(); i++) {
00091 if (!touched[i]) throw cms::Exception("BadConfig") << "Fitter " << m_name << " is not a connected graph (no way to get to " << m_alignables[i] << " from " << m_alignables[0] << ", for instance)" << std::endl;
00092 }
00093 }
00094
00095 int CSCChamberFitter::index(std::string alignable) const {
00096 int i = 0;
00097 for (std::vector<std::string>::const_iterator a = m_alignables.begin(); a != m_alignables.end(); ++a) {
00098 if (*a == alignable) return i;
00099 i++;
00100 }
00101 return -1;
00102 }
00103
00104 void CSCChamberFitter::walk(std::map<int,bool> &touched, int alignable) const {
00105 touched[alignable] = true;
00106
00107 for (std::vector<CSCPairConstraint*>::const_iterator constraint = m_constraints.begin(); constraint != m_constraints.end(); ++constraint) {
00108 if (alignable == (*constraint)->i() || alignable == (*constraint)->j()) {
00109 if (!touched[(*constraint)->i()]) walk(touched, (*constraint)->i());
00110 if (!touched[(*constraint)->j()]) walk(touched, (*constraint)->j());
00111 }
00112 }
00113 }
00114
00115 long CSCChamberFitter::alignableId(std::string alignable) const {
00116 if (alignable.size() != 9) return -1;
00117
00118 if (alignable[0] == 'M' && alignable[1] == 'E') {
00119 int endcap = -1;
00120 if (alignable[2] == '+') endcap = 1;
00121 else if (alignable[2] == '-') endcap = 2;
00122
00123 if (endcap != -1) {
00124 int station = -1;
00125 if (alignable[3] == '1') station = 1;
00126 else if (alignable[3] == '2') station = 2;
00127 else if (alignable[3] == '3') station = 3;
00128 else if (alignable[3] == '4') station = 4;
00129
00130 if (alignable[4] == '/' && station != -1) {
00131 int ring = -1;
00132 if (alignable[5] == '1') ring = 1;
00133 else if (alignable[5] == '2') ring = 2;
00134 else if (alignable[5] == '3') ring = 3;
00135 else if (alignable[5] == '4') ring = 4;
00136 if (station > 1 && ring > 2) return -1;
00137
00138 if (alignable[6] == '/' && ring != -1) {
00139 int chamber = -1;
00140 if (alignable[7] == '0' && alignable[8] == '1') chamber = 1;
00141 else if (alignable[7] == '0' && alignable[8] == '2') chamber = 2;
00142 else if (alignable[7] == '0' && alignable[8] == '3') chamber = 3;
00143 else if (alignable[7] == '0' && alignable[8] == '4') chamber = 4;
00144 else if (alignable[7] == '0' && alignable[8] == '5') chamber = 5;
00145 else if (alignable[7] == '0' && alignable[8] == '6') chamber = 6;
00146 else if (alignable[7] == '0' && alignable[8] == '7') chamber = 7;
00147 else if (alignable[7] == '0' && alignable[8] == '8') chamber = 8;
00148 else if (alignable[7] == '0' && alignable[8] == '9') chamber = 9;
00149 else if (alignable[7] == '1' && alignable[8] == '0') chamber = 10;
00150 else if (alignable[7] == '1' && alignable[8] == '1') chamber = 11;
00151 else if (alignable[7] == '1' && alignable[8] == '2') chamber = 12;
00152 else if (alignable[7] == '1' && alignable[8] == '3') chamber = 13;
00153 else if (alignable[7] == '1' && alignable[8] == '4') chamber = 14;
00154 else if (alignable[7] == '1' && alignable[8] == '5') chamber = 15;
00155 else if (alignable[7] == '1' && alignable[8] == '6') chamber = 16;
00156 else if (alignable[7] == '1' && alignable[8] == '7') chamber = 17;
00157 else if (alignable[7] == '1' && alignable[8] == '8') chamber = 18;
00158 else if (alignable[7] == '1' && alignable[8] == '9') chamber = 19;
00159 else if (alignable[7] == '2' && alignable[8] == '0') chamber = 20;
00160 else if (alignable[7] == '2' && alignable[8] == '1') chamber = 21;
00161 else if (alignable[7] == '2' && alignable[8] == '2') chamber = 22;
00162 else if (alignable[7] == '2' && alignable[8] == '3') chamber = 23;
00163 else if (alignable[7] == '2' && alignable[8] == '4') chamber = 24;
00164 else if (alignable[7] == '2' && alignable[8] == '5') chamber = 25;
00165 else if (alignable[7] == '2' && alignable[8] == '6') chamber = 26;
00166 else if (alignable[7] == '2' && alignable[8] == '7') chamber = 27;
00167 else if (alignable[7] == '2' && alignable[8] == '8') chamber = 28;
00168 else if (alignable[7] == '2' && alignable[8] == '9') chamber = 29;
00169 else if (alignable[7] == '3' && alignable[8] == '0') chamber = 30;
00170 else if (alignable[7] == '3' && alignable[8] == '1') chamber = 31;
00171 else if (alignable[7] == '3' && alignable[8] == '2') chamber = 32;
00172 else if (alignable[7] == '3' && alignable[8] == '3') chamber = 33;
00173 else if (alignable[7] == '3' && alignable[8] == '4') chamber = 34;
00174 else if (alignable[7] == '3' && alignable[8] == '5') chamber = 35;
00175 else if (alignable[7] == '3' && alignable[8] == '6') chamber = 36;
00176
00177 if (station > 1 && ring == 1 && chamber > 18) return -1;
00178
00179 if (chamber != -1) {
00180 return CSCDetId(endcap, station, ring, chamber, 0).rawId();
00181 }
00182 }
00183 }
00184 }
00185 }
00186
00187 return -1;
00188 }
00189
00190 bool CSCChamberFitter::isFrame(int i) const {
00191 for (std::vector<int>::const_iterator frame = m_frames.begin(); frame != m_frames.end(); ++frame) {
00192 if (i == *frame) return true;
00193 }
00194 return false;
00195 }
00196
00197 double CSCChamberFitter::chi2(AlgebraicVector A, double lambda) const {
00198 double sumFixed = 0.;
00199
00200 if (m_fixed == -1) {
00201 for (unsigned int i = 0; i < m_alignables.size(); i++) {
00202 if (!isFrame(i)) {
00203 sumFixed += A[i];
00204 }
00205 }
00206 }
00207 else {
00208 sumFixed = A[m_fixed];
00209 }
00210
00211 double s = lambda * sumFixed*sumFixed;
00212 for (std::vector<CSCPairConstraint*>::const_iterator constraint = m_constraints.begin(); constraint != m_constraints.end(); ++constraint) {
00213 if ((*constraint)->valid()) {
00214 s += pow((*constraint)->value() - A[(*constraint)->i()] + A[(*constraint)->j()], 2)/(*constraint)->error()/(*constraint)->error();
00215 }
00216 }
00217 return s;
00218 }
00219
00220 double CSCChamberFitter::lhsVector(int k) const {
00221 double s = 0.;
00222 for (std::vector<CSCPairConstraint*>::const_iterator constraint = m_constraints.begin(); constraint != m_constraints.end(); ++constraint) {
00223 if ((*constraint)->valid()) {
00224 double d = 2.*(*constraint)->value()/(*constraint)->error()/(*constraint)->error();
00225 if ((*constraint)->i() == k) s += d;
00226 if ((*constraint)->j() == k) s -= d;
00227 }
00228 }
00229 return s;
00230 }
00231
00232 double CSCChamberFitter::hessian(int k, int l, double lambda) const {
00233 double s = 0.;
00234
00235 if (m_fixed == -1) {
00236 if (!isFrame(k) && !isFrame(l)) s += 2.*lambda;
00237 }
00238 else {
00239 if (k == l && l == m_fixed) s += 2.*lambda;
00240 }
00241
00242 for (std::vector<CSCPairConstraint*>::const_iterator constraint = m_constraints.begin(); constraint != m_constraints.end(); ++constraint) {
00243 double d = 2./infinity/infinity;
00244 if ((*constraint)->valid()) {
00245 d = 2./(*constraint)->error()/(*constraint)->error();
00246 }
00247
00248 if (k == l && ((*constraint)->i() == k || (*constraint)->j() == k)) s += d;
00249 if (((*constraint)->i() == k && (*constraint)->j() == l) || ((*constraint)->j() == k && (*constraint)->i() == l)) s -= d;
00250 }
00251 return s;
00252 }
00253
00254 bool CSCChamberFitter::fit(std::vector<CSCAlignmentCorrections*> &corrections) const {
00255 double lambda = 1./infinity/infinity;
00256
00257 AlgebraicVector A(m_alignables.size());
00258 AlgebraicVector V(m_alignables.size());
00259 AlgebraicMatrix M(m_alignables.size(), m_alignables.size());
00260
00261 for (unsigned int k = 0; k < m_alignables.size(); k++) {
00262 A[k] = 0.;
00263 V[k] = lhsVector(k);
00264 for (unsigned int l = 0; l < m_alignables.size(); l++) {
00265 M[k][l] = hessian(k, l, lambda);
00266 }
00267 }
00268
00269 double oldchi2 = chi2(A, lambda);
00270
00271 int ierr;
00272 M.invert(ierr);
00273 if (ierr != 0) {
00274 edm::LogError("CSCOverlapsAlignmentAlgorithm") << "Matrix inversion failed for fitter " << m_name << " matrix is " << M << std::endl;
00275 return false;
00276 }
00277
00278 A = M * V;
00279
00281 CSCAlignmentCorrections *correction = new CSCAlignmentCorrections(m_name, oldchi2, chi2(A, lambda));
00282
00283 for (unsigned int i = 0; i < m_alignables.size(); i++) {
00284 if (!isFrame(i)) {
00285 correction->insertCorrection(m_alignables[i], CSCDetId(alignableId(m_alignables[i])), A[i]);
00286 }
00287 }
00288
00289
00290
00291
00292 TMatrixD tmatrix(m_alignables.size(), m_alignables.size());
00293 for (unsigned int i = 0; i < m_alignables.size(); i++) {
00294 for (unsigned int j = 0; j < m_alignables.size(); j++) {
00295 tmatrix[i][j] = M[i][j];
00296 }
00297 }
00298 TMatrixDEigen tmatrixdeigen(tmatrix);
00299 TMatrixD basis = tmatrixdeigen.GetEigenVectors();
00300 TMatrixD invbasis = tmatrixdeigen.GetEigenVectors();
00301 invbasis.Invert();
00302 TMatrixD diagonalized = invbasis * (tmatrix * basis);
00303
00304 for (unsigned int i = 0; i < m_alignables.size(); i++) {
00305 std::vector<double> coefficient;
00306 std::vector<std::string> modename;
00307 std::vector<long> modeid;
00308 for (unsigned int j = 0; j < m_alignables.size(); j++) {
00309 coefficient.push_back(invbasis[i][j]);
00310 modename.push_back(m_alignables[j]);
00311 modeid.push_back(alignableId(m_alignables[j]));
00312 }
00313
00314 correction->insertMode(coefficient, modename, modeid, sqrt(2. * fabs(diagonalized[i][i])) * (diagonalized[i][i] >= 0. ? 1. : -1.));
00315 }
00316
00317 for (std::vector<CSCPairConstraint*>::const_iterator constraint = m_constraints.begin(); constraint != m_constraints.end(); ++constraint) {
00318 if ((*constraint)->valid()) {
00319 double residual = (*constraint)->value() - A[(*constraint)->i()] + A[(*constraint)->j()];
00320 correction->insertResidual(m_alignables[(*constraint)->i()], m_alignables[(*constraint)->j()], (*constraint)->value(), (*constraint)->error(), residual, residual/(*constraint)->error());
00321 }
00322 }
00323
00324 corrections.push_back(correction);
00325 return true;
00326 }
00327
00328 void CSCChamberFitter::radiusCorrection(AlignableNavigator *alignableNavigator, AlignmentParameterStore *alignmentParameterStore, bool combineME11) const {
00329 double sum_phipos_residuals = 0.;
00330 double num_valid = 0.;
00331 double sum_radius = 0.;
00332 double num_total = 0.;
00333 for (std::vector<CSCPairConstraint*>::const_iterator constraint = m_constraints.begin(); constraint != m_constraints.end(); ++constraint) {
00334 CSCPairResidualsConstraint *residualsConstraint = dynamic_cast<CSCPairResidualsConstraint*>(*constraint);
00335 if (residualsConstraint != NULL) {
00336
00337 if (residualsConstraint->valid()) {
00338 sum_phipos_residuals += residualsConstraint->value();
00339 num_valid += 1.;
00340 }
00341
00342 sum_radius += residualsConstraint->radius(true);
00343 num_total += 1.;
00344 }
00345 }
00346 if (num_valid == 0. || num_total == 0.) return;
00347 double average_phi_residual = sum_phipos_residuals / num_valid;
00348 double average_radius = sum_radius / num_total;
00349
00350 double radial_correction = average_phi_residual * average_radius * num_total / (2.*M_PI);
00351
00352 for (std::vector<CSCPairConstraint*>::const_iterator constraint = m_constraints.begin(); constraint != m_constraints.end(); ++constraint) {
00353 CSCPairResidualsConstraint *residualsConstraint = dynamic_cast<CSCPairResidualsConstraint*>(*constraint);
00354 if (residualsConstraint != NULL) {
00355
00356 const DetId id(residualsConstraint->id_i());
00357 Alignable *alignable = alignableNavigator->alignableFromDetId(id).alignable();
00358 Alignable *also = NULL;
00359 if (combineME11 && residualsConstraint->id_i().station() == 1 && residualsConstraint->id_i().ring() == 1) {
00360 CSCDetId alsoid(residualsConstraint->id_i().endcap(), 1, 4, residualsConstraint->id_i().chamber(), 0);
00361 const DetId alsoid2(alsoid);
00362 also = alignableNavigator->alignableFromDetId(alsoid2).alignable();
00363 }
00364
00365 AlgebraicVector params(6);
00366 AlgebraicSymMatrix cov(6);
00367
00368 params[1] = radial_correction;
00369 cov[1][1] = 1e-6;
00370
00371 AlignmentParameters *parnew = alignable->alignmentParameters()->cloneFromSelected(params, cov);
00372 alignable->setAlignmentParameters(parnew);
00373 alignmentParameterStore->applyParameters(alignable);
00374 alignable->alignmentParameters()->setValid(true);
00375 if (also != NULL) {
00376 AlignmentParameters *parnew2 = also->alignmentParameters()->cloneFromSelected(params, cov);
00377 also->setAlignmentParameters(parnew2);
00378 alignmentParameterStore->applyParameters(also);
00379 also->alignmentParameters()->setValid(true);
00380 }
00381 }
00382 }
00383 }