CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/Alignment/MillePedeAlignmentAlgorithm/src/PedeSteerer.cc

Go to the documentation of this file.
00001 
00011 #include "PedeSteerer.h"
00012 #include "Alignment/MillePedeAlignmentAlgorithm/interface/PedeLabelerBase.h"
00013 
00014 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00015 
00016 #include "Alignment/CommonAlignment/interface/Alignable.h"
00017 #include <boost/cstdint.hpp> 
00018 #include "Alignment/CommonAlignment/interface/AlignableObjectId.h"
00019 #include "Alignment/CommonAlignment/interface/Utilities.h"
00020 #include "Alignment/CommonAlignmentAlgorithm/interface/AlignmentParameterStore.h"
00021 #include "Alignment/CommonAlignmentAlgorithm/interface/AlignmentParameterSelector.h"
00022 #include "Alignment/CommonAlignmentAlgorithm/interface/SelectionUserVariables.h"
00023 #include "Alignment/CommonAlignmentParametrization/interface/AlignmentParametersFactory.h"
00024 #include "Alignment/CommonAlignmentParametrization/interface/RigidBodyAlignmentParameters.h"
00025 
00026 #include "Alignment/TrackerAlignment/interface/TrackerAlignableId.h"
00027 // for 'type identification' as Alignable
00028 #include "Alignment/TrackerAlignment/interface/AlignableTracker.h"
00029 #include "Alignment/MuonAlignment/interface/AlignableMuon.h"
00030 #include "Alignment/CommonAlignment/interface/AlignableExtras.h"
00031 // GF doubts the need of these includes from include checker campaign:
00032 #include <FWCore/Framework/interface/EventSetup.h> 
00033 #include <Geometry/CommonDetUnit/interface/GeomDetUnit.h> 
00034 #include <Geometry/CommonDetUnit/interface/GeomDetType.h> 
00035 #include <DataFormats/GeometrySurface/interface/LocalError.h> 
00036 #include <Geometry/DTGeometry/interface/DTLayer.h> 
00037 // end of doubt
00038 
00039 #include "DataFormats/GeometryVector/interface/GlobalPoint.h"
00040 
00041 #include <fstream>
00042 #include <sstream>
00043 #include <algorithm>
00044 
00045 // from ROOT
00046 #include <TSystem.h>
00047 #include <TMath.h>
00048 
00049 #include <iostream>
00050 
00051 PedeSteerer::PedeSteerer(AlignableTracker *aliTracker, AlignableMuon *aliMuon, AlignableExtras *aliExtras,
00052                          AlignmentParameterStore *store, const PedeLabelerBase *labels,
00053                          const edm::ParameterSet &config, const std::string &defaultDir,
00054                          bool noSteerFiles) :
00055   myParameterStore(store), myLabels(labels), myConfig(config),
00056   myDirectory(myConfig.getUntrackedParameter<std::string>("fileDir")),
00057   myNoSteerFiles(noSteerFiles),
00058   myIsSteerFileDebug(myConfig.getUntrackedParameter<bool>("steerFileDebug")),
00059   myParameterSign(myConfig.getUntrackedParameter<int>("parameterSign")),
00060   theMinHieraConstrCoeff(myConfig.getParameter<double>("minHieraConstrCoeff")),
00061   theMinHieraParPerConstr(myConfig.getParameter<unsigned int>("minHieraParPerConstr")),
00062   theCoordMaster(0)
00063 {
00064   if (myParameterSign != 1 && myParameterSign != -1) {
00065     cms::Exception("BadConfig") << "Expect PedeSteerer.parameterSign = +/-1, "
00066                                 << "found " << myParameterSign << ".";
00067   }
00068 
00069   // Correct directory, needed before asking for fileName(..):
00070   if (myDirectory.empty()) myDirectory = defaultDir;
00071   if (!myDirectory.empty() && myDirectory.find_last_of('/') != myDirectory.size() - 1) {
00072     myDirectory += '/'; // directory may need '/'
00073   }
00074 
00075   const std::vector<Alignable*> &alis = myParameterStore->alignables();
00076   if (!this->checkParameterChoices(alis)) {} // anyway thrown exception
00077 
00078   // Coordinate system selection and correction before everything
00079   theCoordDefiners = this->selectCoordinateAlis(alis);
00080   if (!theCoordDefiners.empty()) { // Create steering with constraints to define coordinate system:
00081     // OK, some hacks:
00082     // - we want a composite with global coordinates where tracker and muon are components
00083     //   (to call RigidBodyAl.Param.->globalParameters() in correctToReferenceSystem(..))
00084     // - so we create a AlignableComposite and add tracker and muon
00085     // - but the addComponent(..) method is so cute that it calculates position from 
00086     //   daughters' deepComponents()
00087     // - so we want to move it back to (0,0,0), but ali->move(..) would move daughters as well
00088     //   => cheat with a const_cast and move only the surface back
00089     // - this hacked master object does not have a label for its parameters
00090     //   => some warnings if debug output selected in pedeSteer files
00091     // - we must not delete our new master (little mem. leak...) since that would delete
00092     //   the daughters as well!
00093     if (aliTracker) {
00094       theCoordMaster = new AlignableComposite(aliTracker->id(), align::invalid);
00095       theCoordMaster->addComponent(aliTracker);
00096     } else if (aliMuon) {
00097       theCoordMaster = new AlignableComposite(aliMuon->id(), align::invalid);
00098     } else {
00099       throw cms::Exception("BadConfig")
00100         << "[PedeSteerer]" << "Cannot define global coordinate system "
00101         << "with neither tracker nor muon!";
00102     }
00103     if (aliMuon) theCoordMaster->addComponent(aliMuon); // tracker is already added if existing
00104     if (aliExtras) { // tracker and/or muon are already added if existing
00105       align::Alignables allExtras = aliExtras->components();
00106       for ( std::vector<Alignable*>::iterator it = allExtras.begin(); it != allExtras.end(); ++it ) {
00107         theCoordMaster->addComponent(*it);
00108       }
00109     }
00110 
00111     const Alignable::PositionType &tmpPos = theCoordMaster->globalPosition();
00112     AlignableSurface & masterSurf = const_cast<AlignableSurface&>(theCoordMaster->surface());
00113     masterSurf.move(align::GlobalVector(-tmpPos.x(),-tmpPos.y(),-tmpPos.z()));
00114 
00115     if (this->isCorrectToRefSystem(theCoordDefiners)) { // defined by 's' (MC): 'correct' misalignment
00116       this->correctToReferenceSystem(); // really before 'defineCoordinates'?
00117     }
00118   } 
00119 
00120 }
00121 
00122 //___________________________________________________________________________
00123 PedeSteerer::~PedeSteerer()
00124 {
00125   // delete theCoordMaster; NO, see above
00126 }
00127 
00128 //_________________________________________________________________________
00129 bool PedeSteerer::isNoHiera(const Alignable* ali) const
00130 {
00131   return (myNoHieraCollection.find(ali) != myNoHieraCollection.end());
00132 }
00133 
00134 //_________________________________________________________________________
00135 double PedeSteerer::cmsToPedeFactor(unsigned int parNum) const
00136 {
00137   return 1.; // mmh, otherwise would need to FIXME hierarchyConstraint...
00138 
00139   switch (parNum) {
00140   case RigidBodyAlignmentParameters::dx:
00141   case RigidBodyAlignmentParameters::dy:
00142     return 1000.; // cm to mum *1/10 to get smaller values
00143   case RigidBodyAlignmentParameters::dz:
00144     return 2500.;   // cm to mum *1/4 
00145   case RigidBodyAlignmentParameters::dalpha:
00146   case RigidBodyAlignmentParameters::dbeta:
00147     return 1000.; // rad to mrad (no first guess for sensitivity yet)
00148   case RigidBodyAlignmentParameters::dgamma:
00149     return 10000.; // rad to mrad *10 to get larger values
00150   default:
00151     return 1.;
00152   }
00153 }
00154 
00155 //_________________________________________________________________________
00156 unsigned int PedeSteerer::buildNoHierarchyCollection(const std::vector<Alignable*> &alis)
00157 {
00158   myNoHieraCollection.clear();  // just in case of re-use...
00159 
00160   for (std::vector<Alignable*>::const_iterator iAli = alis.begin() ; iAli != alis.end(); ++iAli) {
00161     AlignmentParameters *params = (*iAli)->alignmentParameters();
00162     SelectionUserVariables *selVar = dynamic_cast<SelectionUserVariables*>(params->userVariables());
00163     if (!selVar) continue;
00164     // Now check whether taking out of hierarchy is selected - must be consistent!
00165     unsigned int numNoHieraPar = 0;
00166     unsigned int numHieraPar = 0;
00167     for (unsigned int iParam = 0; static_cast<int>(iParam) < params->size(); ++iParam) {
00168       const char selector = selVar->fullSelection()[iParam];
00169       if (selector == 'C' || selector == 'F' || selector == 'H') {
00170         ++numNoHieraPar;
00171       } else if (selector == 'c' || selector == 'f' || selector == '1' || selector == 'r'
00172                  || selector == 's') {
00173         ++numHieraPar;
00174       } // else ... accept '0' as undetermined
00175     }
00176     if (numNoHieraPar) { // Selected to be taken out.
00177       if (numHieraPar) { // Inconsistent: Some parameters still in hierarchy ==> exception!
00178         throw cms::Exception("BadConfig") 
00179           << "[PedeSteerer::buildNoHierarchyCollection] All active parameters of alignables to be "
00180           << " taken out of the hierarchy must be marked with capital letters 'C', 'F' or 'H'!";
00181       }
00182       bool isInHiera = false; // Check whether Alignable is really part of hierarchy:
00183       Alignable *mother = *iAli;
00184       while ((mother = mother->mother())) {
00185         if (mother->alignmentParameters()) isInHiera = true; // could 'break;', but loop is short
00186       }
00187       // Complain, but keep collection short if not in hierarchy:
00188       if (isInHiera) myNoHieraCollection.insert(*iAli);
00189       else edm::LogWarning("Alignment") << "@SUB=PedeSteerer::buildNoHierarchyCollection"
00190                                         << "Alignable not in hierarchy, no need to remove it!";
00191     }
00192   } // end loop on alignables
00193 
00194   return myNoHieraCollection.size();
00195 }
00196 
00197 //_________________________________________________________________________
00198 bool PedeSteerer::checkParameterChoices(const std::vector<Alignable*> &alis) const
00199 {
00200   for (std::vector<Alignable*>::const_iterator iAli = alis.begin() ; iAli != alis.end(); ++iAli) {
00201     AlignmentParameters *paras = (*iAli)->alignmentParameters();
00202     SelectionUserVariables *selVar = dynamic_cast<SelectionUserVariables*>(paras->userVariables());
00203     if (!selVar) continue;
00204     for (unsigned int iParam = 0; static_cast<int>(iParam) < paras->size(); ++iParam) {
00205       const char sel = selVar->fullSelection()[iParam];
00206       if (sel != 'f' && sel != 'F' && sel != 'c' && sel != 'C' &&
00207           sel != '0' && sel != '1' && sel != 'H' && sel != 'r' && sel != 's') {
00208         throw cms::Exception("BadConfig")
00209           << "[PedeSteerer::unknownParameterChoices] " 
00210           << "Unexpected parameter selector '" << sel
00211           << "', use \n'f/F' (fix),\n'c/C' (fix at correct pos.),\n'1/H' (free),\n"
00212           << "'r/s' (free, but defining reference system, trying to correct misalignment if 's')"
00213           << " or \n'0' (ignore).\n"
00214           << "Capital letters mean that the Alignable is taken out of a possible hierarchy,\n"
00215           << "but must be used consistently for all its parameters.";
00216         return false; // unreached
00217       }
00218     }
00219   }
00220 
00221   return true;
00222 }
00223 
00224 //_________________________________________________________________________
00225 std::pair<unsigned int, unsigned int>
00226 PedeSteerer::fixParameters(const std::vector<Alignable*> &alis, const std::string &fileName)
00227 {
00228   // return number of parameters fixed at 0. and fixed at original position 
00229   std::pair<unsigned int, unsigned int> numFixNumFixCor(0, 0);
00230 
00231   std::ofstream *filePtr = 0;
00232 
00233   for (std::vector<Alignable*>::const_iterator iAli = alis.begin() ; iAli != alis.end(); ++iAli) {
00234 
00235     AlignmentParameters *params = (*iAli)->alignmentParameters();
00236     SelectionUserVariables *selVar = dynamic_cast<SelectionUserVariables*>(params->userVariables());
00237     if (!selVar) continue;
00238     
00239     for (unsigned int iParam = 0; static_cast<int>(iParam) < params->size(); ++iParam) {
00240       const unsigned int nInstances = myLabels->numberOfParameterInstances(*iAli, iParam);
00241       for (unsigned int iInstance=0;iInstance<nInstances;++iInstance) {
00242         int whichFix = this->fixParameter(*iAli, iInstance, iParam,
00243                                           selVar->fullSelection()[iParam], filePtr,
00244                                           fileName);
00245         if (whichFix == 1) {
00246           ++(numFixNumFixCor.first);
00247         } else if (whichFix == -1) {
00248           ++(numFixNumFixCor.second);
00249         }
00250       }
00251     }
00252   }
00253 
00254   delete filePtr; // automatically flushes, no problem if NULL ptr.   
00255 
00256   return numFixNumFixCor;
00257 }
00258 
00259 //_________________________________________________________________________
00260 int PedeSteerer::fixParameter(Alignable *ali, unsigned int iInstance,
00261                               unsigned int iParam, char selector,
00262                               std::ofstream* &filePtr, const std::string &fileName)
00263 {
00264   int result = 0;
00265   float fixAt = 0.;
00266   if (selector == 'c' || selector == 'C') {
00267     if (ali->alignmentParameters()->type() != AlignmentParametersFactory::kRigidBody) {
00268       throw cms::Exception("BadConfig") 
00269         << "PedeSteerer::fixParameter: correction (c/C) possible only for RigidBodyParameters";
00270     }
00271     fixAt = -this->parameterSign() * RigidBodyAlignmentParameters(ali, true).parameters()[iParam];
00272     result = -1;
00273   } else if (selector == 'f' || selector == 'F') {
00274     result = 1;
00275   }
00276 
00277   if (result) {
00278     if (!filePtr) {
00279       filePtr = this->createSteerFile(fileName, true);
00280       (*filePtr) << "Parameter\n";
00281     }
00282     std::ofstream &file = *filePtr;
00283 
00284     const unsigned int aliLabel = myLabels->alignableLabelFromParamAndInstance(ali, iParam, iInstance);
00285     file << myLabels->parameterLabel(aliLabel, iParam) << "  " 
00286          << fixAt * this->cmsToPedeFactor(iParam) << " -1.0";
00287     if (myIsSteerFileDebug) { // debug
00288       const GlobalPoint position(ali->globalPosition());
00289       file << "  * id " << ali->id() << ", eta " << position.eta() << ", z " << position.z()
00290            << ", r " << position.perp() << ", phi " << position.phi();
00291     }
00292     file << "\n";
00293   }
00294 
00295   return result;
00296 }
00297 
00298 //_________________________________________________________________________
00299 std::vector<Alignable*> PedeSteerer::selectCoordinateAlis(const std::vector<Alignable*> &alis) const
00300 {
00301   std::vector<Alignable*> coordAlis;
00302 
00303   for (std::vector<Alignable*>::const_iterator iAli = alis.begin() ; iAli != alis.end(); ++iAli) {
00304     AlignmentParameters *params = (*iAli)->alignmentParameters();
00305     SelectionUserVariables *selVar = dynamic_cast<SelectionUserVariables*>(params->userVariables());
00306     if (!selVar) continue;
00307     unsigned int refParam = 0;
00308     unsigned int nonRefParam = 0;
00309     for (unsigned int iParam = 0; static_cast<int>(iParam) < params->size(); ++iParam) {
00310       const char selector = selVar->fullSelection()[iParam];
00311       if (selector == 'r' || selector == 's') {
00312         ++refParam;
00313       } else if (selector != '0' && selector != 'f') { // allow also 'c'?
00314         ++nonRefParam;
00315       }
00316     }
00317     // Check whether some 'r/s' selection string. If yes and selection makes sense, add to result:
00318     if (refParam) {
00319       if (nonRefParam) {
00320         throw cms::Exception("BadConfig") 
00321           << "[PedeSteerer::selectCoordinateAlis] All active parameters of alignables defining "
00322           << "the coordinate system must be marked with 'r/s' (or fixed, 'f')!";
00323       } else {
00324         Alignable *mother = *iAli;
00325         while ((mother = mother->mother())) {
00326           if (mother->alignmentParameters()) {
00327             throw cms::Exception("BadConfig") << "[PedeSteerer::selectCoordinateAlis] "
00328                                               << "Alignables defining the coordinate system must "
00329                                               << "be highest level!";
00330           }
00331         }
00332         coordAlis.push_back(*iAli);
00333       }
00334     }
00335   } // end loop on alignables
00336 
00337   return coordAlis;
00338 }
00339 
00340 
00341 //_________________________________________________________________________
00342 void PedeSteerer::defineCoordinates(const std::vector<Alignable*> &alis, Alignable *aliMaster,
00343                                     const std::string &fileName)
00344 {
00345   std::ofstream *filePtr = this->createSteerFile(fileName, true);
00346   (*filePtr) << "* Constraints to define coordinate system:\n";
00347   if (!aliMaster || aliMaster->alignmentParameters()) {
00348     throw cms::Exception("BadConfig")
00349       << "[PedeSteerer::defineCoordinates] " << "No master alignable or it has parameters!";
00350   }
00351   if (myIsSteerFileDebug) { // See constructor comments about hack:
00352     edm::LogError("Alignment") << "@SUB=PedeSteerer::defineCoordinates"
00353                                << "Ignore following LogicErrors from PedeLabeler.";
00354   }
00355   AlignmentParameters *par = new RigidBodyAlignmentParameters(aliMaster, false);
00356   aliMaster->setAlignmentParameters(par); // hierarchyConstraint needs parameters
00357   this->hierarchyConstraint(aliMaster, alis, *filePtr);
00358   aliMaster->setAlignmentParameters(0); // erase dummy parameters
00359 
00360   delete filePtr; // automatically flushes, no problem if NULL ptr.   
00361 }
00362 
00363 //_________________________________________________________________________
00364 bool PedeSteerer::isCorrectToRefSystem(const std::vector<Alignable*> &coordDefiners) const
00365 {
00366   bool doCorrect = false;
00367   bool doNotCorrect = false;
00368   for (std::vector<Alignable*>::const_iterator it = coordDefiners.begin(), iE=coordDefiners.end();
00369        it != iE; ++it) {
00370     SelectionUserVariables *selVar = 
00371       ((*it)->alignmentParameters() ? 
00372        dynamic_cast<SelectionUserVariables*>((*it)->alignmentParameters()->userVariables()) : 0);
00373     if (!selVar) continue;  // is an error!?
00374 
00375     for (unsigned int i = 0; i < selVar->fullSelection().size(); ++i) {
00376       if (selVar->fullSelection()[i] == 'r') doNotCorrect = true;
00377       else if (selVar->fullSelection()[i] == 's') doCorrect = true;
00378     }
00379   }
00380 
00381   if (doCorrect && doNotCorrect) {
00382     throw cms::Exception("BadConfig")
00383       << "[PedeSteerer::doCorrectToRefSystem]: Parameter selection 's' and 'r' must not coexist!";
00384   }
00385 
00386   return doCorrect;
00387 }
00388 
00389 //_________________________________________________________________________
00390 void PedeSteerer::correctToReferenceSystem()
00391 {
00392   typedef RigidBodyAlignmentParameters RbPars;
00393   if (!theCoordMaster || theCoordDefiners.empty()) return; // nothing was defined
00394 
00395   std::vector<Alignable*> definerDets; // or ...DetUnits
00396   for (std::vector<Alignable*>::iterator it = theCoordDefiners.begin(), iE = theCoordDefiners.end();
00397        it != iE; ++it) {// find lowest level objects of alignables that define the coordinate system
00398     const std::vector<Alignable*> &comp = (*it)->deepComponents();
00399     definerDets.insert(definerDets.end(), comp.begin(), comp.end());
00400   }
00401 
00402   for (unsigned int iLoop = 0; ; ++iLoop) { // iterate: shifts and rotations are not independent
00403     AlgebraicVector meanPars(RbPars::N_PARAM);
00404     for (std::vector<Alignable*>::iterator it = definerDets.begin(), iE = definerDets.end();
00405          it != iE; ++it) { // sum up mean displacements/misrotations:
00406       meanPars += RbPars(*it, true).globalParameters();// requires theCoordMaster has global frame
00407     }
00408     meanPars /= definerDets.size();
00409     const align::Scalar squareSum = meanPars.normsq();
00410 
00411     if (squareSum < 1.e-20) break; // sqrt(1.e-20)=1.e-10: close enough to stop iterating
00412     if (iLoop == 0) {
00413       edm::LogInfo("Alignment") << "@SUB=PedeSteerer::correctToReferenceSystem"
00414                                 << "Loop " << iLoop << " "
00415                                 << "Mean misalignment of dets of defined coordinate system"
00416                                 << (squareSum < 1.e-20 ? ":" :
00417                                     " (will be iteratively corrected to < 1.e-10):") << meanPars;
00418     }
00419     if (iLoop >=5) { // 3 iterations should be safe, use 5 for 'more' safety...
00420         edm::LogError("Alignment") << "@SUB=PedeSteerer::correctToReferenceSystem"
00421                                    << "No convergence in " << iLoop << " iterations, " 
00422                                    << "remaining misalignment: " << meanPars;
00423       break;
00424     }
00425 
00426     const GlobalVector globalShift(meanPars[RbPars::dx],meanPars[RbPars::dy],meanPars[RbPars::dz]);
00427     theCoordMaster->move(-globalShift); // sign to revert
00428     align::EulerAngles globalAngles(3);
00429     globalAngles[0] = meanPars[RbPars::dalpha];
00430     globalAngles[1] = meanPars[RbPars::dbeta];
00431     globalAngles[2] = meanPars[RbPars::dgamma];
00432     theCoordMaster->rotateInGlobalFrame(align::toMatrix(-globalAngles)); // sign to revert
00433   }
00434   
00435 }
00436 
00437 //_________________________________________________________________________
00438 unsigned int PedeSteerer::hierarchyConstraints(const std::vector<Alignable*> &alis,
00439                                                const std::string &fileName)
00440 {
00441   std::ofstream *filePtr = 0;
00442 
00443   unsigned int nConstraints = 0;
00444   std::vector<Alignable*> aliDaughts;
00445   for (std::vector<Alignable*>::const_iterator iA = alis.begin(), iEnd = alis.end();
00446        iA != iEnd; ++iA) {
00447     aliDaughts.clear();
00448     if (!(*iA)->firstCompsWithParams(aliDaughts)) {
00449       edm::LogWarning("Alignment") << "@SUB=PedeSteerer::hierarchyConstraints"
00450                                    << "Some but not all daughters of "
00451                                    << AlignableObjectId::idToString((*iA)->alignableObjectId())
00452                                    << " with params!";
00453     }
00454 //     edm::LogInfo("Alignment") << "@SUB=PedeSteerer::hierarchyConstraints"
00455 //                            << aliDaughts.size() << " ali param components";
00456     if (aliDaughts.empty()) continue;
00457 //     edm::LogInfo("Alignment") << "@SUB=PedeSteerer::hierarchyConstraints"
00458 //                            << aliDaughts.size() << " alignable components ("
00459 //                            << (*iA)->size() << " in total) for " 
00460 //                            << aliId.alignableTypeName(*iA) 
00461 //                            << ", layer " << aliId.typeAndLayerFromAlignable(*iA).second
00462 //                            << ", position " << (*iA)->globalPosition()
00463 //                            << ", r = " << (*iA)->globalPosition().perp();
00464     if (!filePtr) filePtr = this->createSteerFile(fileName, true);
00465     ++nConstraints;
00466     this->hierarchyConstraint(*iA, aliDaughts, *filePtr);
00467   }
00468 
00469   delete filePtr; // automatically flushes, no problem if NULL ptr.   
00470 
00471   return nConstraints;
00472 }
00473 
00474 //_________________________________________________________________________
00475 void PedeSteerer::hierarchyConstraint(const Alignable *ali,
00476                                       const std::vector<Alignable*> &components,
00477                                       std::ofstream &file) const
00478 {
00479   typedef AlignmentParameterStore::ParameterId ParameterId;
00480 
00481   std::vector<std::vector<ParameterId> > paramIdsVec;
00482   std::vector<std::vector<double> > factorsVec;
00483   const bool allConstr = false; // true; // make configurable?
00484   static bool first = true;
00485   if (allConstr && first) {
00486     edm::LogWarning("Alignment") << "@SUB=PedeSteerer::hierarchyConstraint"
00487                                  << "changed to use all 6 constraints";
00488     first = false;
00489   }
00490   if (!myParameterStore->hierarchyConstraints(ali, components, paramIdsVec, factorsVec, allConstr,
00491                                               theMinHieraConstrCoeff)){
00492     edm::LogWarning("Alignment") << "@SUB=PedeSteerer::hierarchyConstraint"
00493                                  << "Problems from store.";
00494   }
00495 
00496   for (unsigned int iConstr = 0; iConstr < paramIdsVec.size(); ++iConstr) {
00497     std::ostringstream aConstr;
00498 
00499     const std::vector<ParameterId> &parIds = paramIdsVec[iConstr];
00500     const std::vector<double> &factors = factorsVec[iConstr];
00501     unsigned int nParPerConstr = 0; // keep track of used factor/parId pair
00502     // parIds.size() == factors.size() granted by myParameterStore->hierarchyConstraints
00503     for (unsigned int iParam = 0; iParam < parIds.size(); ++iParam) {
00504       Alignable *aliSubComp = parIds[iParam].first;
00505       const unsigned int compParNum = parIds[iParam].second;
00506       if (this->isNoHiera(aliSubComp)) {
00507         if (myIsSteerFileDebug) aConstr << "* Taken out of hierarchy: ";
00508         continue;
00509       }
00510       const unsigned int aliLabel = myLabels->alignableLabel(aliSubComp);
00511       const unsigned int paramLabel = myLabels->parameterLabel(aliLabel, compParNum);
00512       // FIXME: multiply by cmsToPedeFactor(subcomponent)/cmsToPedeFactor(mother) (or vice a versa?)
00513       aConstr << paramLabel << "    " << factors[iParam];
00514       if (myIsSteerFileDebug) { // debug
00515         aConstr << "   ! for param " << compParNum << " of a " 
00516                 << AlignableObjectId::idToString(aliSubComp->alignableObjectId()) << " at " 
00517                 << aliSubComp->globalPosition() << ", r=" << aliSubComp->globalPosition().perp();
00518       }
00519       aConstr << "\n";
00520       ++nParPerConstr; // OK, we used one.
00521     } // end loop on params
00522 
00523     // 
00524     if (nParPerConstr && nParPerConstr >= theMinHieraParPerConstr) { // Enough to make sense?
00525       if (myIsSteerFileDebug) { //debug
00526         file << "\n* Nr. " << iConstr << " of a '"
00527              << AlignableObjectId::idToString(ali->alignableObjectId()) << "' (label "
00528              << myLabels->alignableLabel(const_cast<Alignable*>(ali)) // ugly cast: FIXME!
00529              << "), position " << ali->globalPosition()
00530              << ", r = " << ali->globalPosition().perp();
00531       }
00532       file << "\nConstraint   0.\n" << aConstr.str(); // in future 'Wconstraint'?
00533     } else if (nParPerConstr > 0) { // no warning for trivial case...
00534       edm::LogWarning("Alignment") << "@SUB=PedeSteerer::hierarchyConstraint"
00535                                    << "Skip constraint on " << nParPerConstr
00536                                    << " parameter(s):\n" << aConstr.str();
00537     }
00538   } // end loop on constraints
00539 }
00540 
00541 //_________________________________________________________________________
00542 unsigned int PedeSteerer::presigmas(const std::vector<edm::ParameterSet> &cffPresi,
00543                                     const std::string &fileName,
00544                                     const std::vector<Alignable*> &alis,
00545                                     AlignableTracker *aliTracker, AlignableMuon *aliMuon, AlignableExtras *aliExtras)
00546 {
00547   // We loop on given PSet's, each containing a parameter selection and the presigma value
00548   // The resulting presigmas are stored in a map with Alignable* as key.
00549   // This map, 'fileName' and 'alis' are passed further to create the steering file.
00550 
00551   AlignmentParameterSelector selector(aliTracker, aliMuon, aliExtras);
00552   AlignablePresigmasMap aliPresiMap; // map to store alis with presigmas of their parameters 
00553   for (std::vector<edm::ParameterSet>::const_iterator iSet = cffPresi.begin(), iE = cffPresi.end();
00554        iSet != iE; ++iSet) { // loop on individual PSets defining ali-params with their presigma
00555     selector.clear();
00556     selector.addSelections((*iSet).getParameter<edm::ParameterSet>("Selector"));
00557     const std::vector<Alignable*> &alis = selector.selectedAlignables();
00558     const std::vector<std::vector<char> > &sels =  selector.selectedParameters();
00559     const float presigma = (*iSet).getParameter<double>("presigma");
00560     if (presigma <= 0.) { // given presigma > 0., 0. later used if not (yet) chosen for parameter
00561       throw cms::Exception("BadConfig")
00562         << "[PedeSteerer::presigmas]: Pre-sigma must be > 0., but is " << presigma << ".";
00563     }
00564     // now loop on alis of present selection
00565     for (unsigned int iAli = 0; iAli < alis.size(); ++iAli) {
00566       std::vector<float> &presigmas = aliPresiMap[alis[iAli]]; // existing or empty, so ensure length:
00567       if (presigmas.size() < sels[iAli].size()) presigmas.resize(sels[iAli].size(), 0.);
00568       for (unsigned int iParam = 0; iParam < sels[iAli].size(); ++iParam) { // loop on parameters
00569         if (sels[iAli][iParam] != '0') { // all but '0' means to apply the chosen presigma
00570           if (presigmas[iParam] != 0.) { // reset forbidden (would make it order dependent!)
00571             throw cms::Exception("BadConfig")
00572               << "[PedeSteerer::presigmas]: Try to set pre-sigma " << presigma << ", but already "
00573               << "set " << presigmas[iParam] << " (for a " 
00574               << AlignableObjectId::idToString(alis[iAli]->alignableObjectId()) << ").";
00575           }
00576           presigmas[iParam] = presigma;
00577         } // end if selected for presigma
00578       } // end loop on params
00579     } // end loop on alignables for given selection and presigma
00580   } // end loop on PSets 
00581 
00582   if (aliPresiMap.empty()) return 0;
00583   else return this->presigmasFile(fileName, alis, aliPresiMap);
00584 }
00585 
00586 //_________________________________________________________________________
00587 unsigned int PedeSteerer::presigmasFile(const std::string &fileName,
00588                                         const std::vector<Alignable*> &alis,
00589                                         const AlignablePresigmasMap &aliPresiMap)
00590 {
00591   // Check if 'alis' are in aliPresiMap, 
00592   // if yes apply presigma - but NOT if parameter is fixed!
00593   std::ofstream *filePtr = 0;
00594 
00595   unsigned int nPresiParam = 0;
00596   for (std::vector<Alignable*>::const_iterator iAli = alis.begin(), iAliE = alis.end();
00597        iAli != iAliE; ++iAli) {
00598     // Any presigma chosen for alignable?
00599     AlignablePresigmasMap::const_iterator presigmasIt = aliPresiMap.find(*iAli);
00600     if (presigmasIt == aliPresiMap.end()) continue; // no presigma chosen for alignable
00601 
00602     // Why does the following not work? It does with CMSSW_1_3_X on SLC3...
00603     // const AlignablePresigmasMap::data_type &presigmas = presigmasIt->second;
00604     const std::vector<float> &presigmas = presigmasIt->second; // I want to hide float or double...
00605     for (unsigned int iParam = 0; iParam < presigmas.size(); ++iParam) {
00606       // Now check whether a presigma value > 0. chosen: 
00607       if (presigmas[iParam] <= 0.) continue; // must be positive, '<' checked above
00608       // Do not apply presigma to inactive or fixed values.
00609       if (!(*iAli)->alignmentParameters()->selector()[iParam]) continue;
00610       SelectionUserVariables *selVar 
00611         = dynamic_cast<SelectionUserVariables*>((*iAli)->alignmentParameters()->userVariables());
00612       const char selChar = (selVar ? selVar->fullSelection()[iParam] : '1');
00613       if (selChar == 'f' || selChar == 'F' || selChar == 'c' || selChar == 'C') continue;
00614       // Finally create and write steering file:
00615       if (!filePtr) {
00616         filePtr = this->createSteerFile(fileName, true);
00617         (*filePtr) << "* Presigma values for active parameters: \nParameter\n";
00618       }
00619       const unsigned int aliLabel = myLabels->alignableLabel(*iAli);
00620       (*filePtr) << myLabels->parameterLabel(aliLabel, iParam) << "   0.   " 
00621                  << presigmas[iParam] * fabs(this->cmsToPedeFactor(iParam));
00622       if (myIsSteerFileDebug) {
00623         (*filePtr) << "  ! for a " << AlignableObjectId::idToString((*iAli)->alignableObjectId());
00624       }
00625       (*filePtr) << '\n';
00626 
00627       ++nPresiParam;
00628     } // end loop on parameters for alignables with chosen presigmas
00629   } // end loop on alignables
00630 
00631   delete filePtr; // close properly file
00632   return nPresiParam;
00633 }
00634 
00635 //_________________________________________________________________________
00636 std::ofstream* PedeSteerer::createSteerFile(const std::string &name, bool addToList)
00637 {
00638   const std::string realName(myNoSteerFiles ? "/dev/null" : name.c_str());
00639 
00640   std::ofstream *result = new std::ofstream(realName.c_str(), std::ios::out);
00641   if (!result || !result->is_open()) {
00642     delete result; // needed before exception in case just open failed
00643     throw cms::Exception("FileOpenProblem") << "[PedeSteerer::createSteerFile]" 
00644                                             << "Could not open " << realName 
00645                                             << " as output file.";
00646   } else if (addToList) {
00647     mySteeringFiles.push_back(realName); // keep track
00648   }
00649 
00650   return result;
00651 }
00652 
00653 
00654 //_________________________________________________________________________
00655 std::string PedeSteerer::fileName(const std::string &addendum) const
00656 {
00657 
00658   std::string name(myDirectory);
00659   name += myConfig.getParameter<std::string>("steerFile");
00660   name += addendum;
00661   name += ".txt";
00662 
00663   return name;
00664 }
00665 
00666 //___________________________________________________________________________
00667 void PedeSteerer::buildSubSteer(AlignableTracker *aliTracker, AlignableMuon *aliMuon, AlignableExtras *aliExtras)
00668 {
00669   const std::vector<Alignable*> &alis = myParameterStore->alignables();
00670 
00671   if (theCoordMaster && !theCoordDefiners.empty()) {
00672     const std::string nameCoordFile(this->fileName("Coord"));
00673     this->defineCoordinates(theCoordDefiners, theCoordMaster, nameCoordFile);
00674     edm::LogInfo("Alignment") << "@SUB=PedeSteerer::buildSubSteer" 
00675                               << theCoordDefiners.size() << " highest level objects define the "
00676                               << "coordinate system, steering file " << nameCoordFile << ".";
00677   }
00678 
00679   const std::string nameFixFile(this->fileName("FixPara"));
00680   const std::pair<unsigned int, unsigned int> nFixFixCor(this->fixParameters(alis, nameFixFile));
00681   if (nFixFixCor.first != 0 || nFixFixCor.second != 0) {
00682     edm::LogInfo("Alignment") << "@SUB=PedeSteerer::buildSubSteer" 
00683                               << nFixFixCor.first << " parameters fixed at 0. and "
00684                               << nFixFixCor.second << " at 'original' position, "
00685                               << "steering file " << nameFixFile << ".";
00686   } 
00687 
00688   if (this->buildNoHierarchyCollection(alis)) { // before hierarchyConstraints(..)
00689     edm::LogInfo("Alignment") << "@SUB=PedeSteerer::buildSubSteer"
00690                               << myNoHieraCollection.size()<<" alignables taken out of hierarchy.";
00691   }
00692 
00693   const std::string nameHierarchyFile(this->fileName("Hierarchy"));
00694   unsigned int nConstraint = this->hierarchyConstraints(alis, nameHierarchyFile);
00695   if (nConstraint) {
00696     edm::LogInfo("Alignment") << "@SUB=PedeSteerer::buildSubSteer" 
00697                               << "Hierarchy constraints for " << nConstraint << " alignables, "
00698                               << "steering file " << nameHierarchyFile << ".";
00699   }
00700 
00701   const std::string namePresigmaFile(this->fileName("Presigma"));
00702   unsigned int nPresigma = 
00703     this->presigmas(myConfig.getParameter<std::vector<edm::ParameterSet> >("Presigmas"),
00704                     namePresigmaFile, alis, aliTracker, aliMuon, aliExtras);
00705   if (nPresigma) {
00706     edm::LogInfo("Alignment") << "@SUB=PedeSteerer::buildSubSteer" 
00707                               << "Presigma values set for " << nPresigma << " parameters, "
00708                               << "steering file " << namePresigmaFile << ".";
00709   }
00710 
00711   // Delete all SelectionUserVariables now? They will anyway be overwritten by MillePedeVariables...
00712 }
00713 
00714 //_________________________________________________________________________
00715 std::string PedeSteerer::buildMasterSteer(const std::vector<std::string> &binaryFiles)
00716 {
00717   const std::string nameMasterSteer(this->fileName("Master"));
00718   std::ofstream *mainSteerPtr = this->createSteerFile(nameMasterSteer, false);
00719   if (!mainSteerPtr) return "";
00720 
00721   // add external steering files, if any
00722   std::vector<std::string> addfiles =  myConfig.getParameter<std::vector<std::string> >("additionalSteerFiles");
00723   mySteeringFiles.insert(mySteeringFiles.end(),
00724                   addfiles.begin(),
00725                   addfiles.end());
00726 
00727   // add steering files to master steering file
00728   std::ofstream &mainSteerRef = *mainSteerPtr;
00729   for (unsigned int iFile = 0; iFile < mySteeringFiles.size(); ++iFile) {
00730     mainSteerRef << mySteeringFiles[iFile] << "\n";
00731   }
00732 
00733   // add binary files to master steering file
00734   mainSteerRef << "\nCfiles\n";
00735   for (unsigned int iFile = 0; iFile < binaryFiles.size(); ++iFile) {
00736     mainSteerRef << binaryFiles[iFile] << "\n";
00737   }
00738 
00739   // add method
00740   mainSteerRef << "\nmethod  " << myConfig.getParameter<std::string>("method") << "\n";
00741 
00742   // add further options
00743   const std::vector<std::string> opt(myConfig.getParameter<std::vector<std::string> >("options"));
00744   mainSteerRef << "\n* Outlier treatment and other options \n";
00745   for (unsigned int i = 0; i < opt.size(); ++i) {
00746     mainSteerRef << opt[i] << "\n";
00747   }
00748 
00749   delete mainSteerPtr;  // close (and flush) again
00750 
00751   return nameMasterSteer;
00752 }
00753 
00754 //_________________________________________________________________________
00755 int PedeSteerer::runPede(const std::string &masterSteer) const
00756 {
00757   if (masterSteer.empty()) {
00758     edm::LogError("Alignment") << "@SUB=PedeSteerer::runPede" << "Empty master steer file, stop";
00759     return 0; //false;
00760   }
00761 
00762   std::string command(myConfig.getUntrackedParameter<std::string>("pedeCommand"));
00763   (command += " ") += masterSteer;
00764   const std::string dump(myConfig.getUntrackedParameter<std::string>("pedeDump"));
00765   if (!dump.empty()) {
00766     command += " > ";
00767     (command += myDirectory) += dump;
00768   }
00769 
00770   edm::LogInfo("Alignment") << "@SUB=PedeSteerer::runPede" << "Start running " << command;
00771   // FIXME: Recommended interface to system commands?
00772   int shellReturn = gSystem->Exec(command.c_str());
00773   edm::LogInfo("Alignment") << "@SUB=PedeSteerer::runPede" << "Command returns " << shellReturn;
00774 
00775   return shellReturn;
00776 }