CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/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       static AlignableObjectId objId; // static since costly constructor FIXME?
00450       edm::LogWarning("Alignment") << "@SUB=PedeSteerer::hierarchyConstraints"
00451                                    << "Some but not all daughters of "
00452                                    << objId. typeToName((*iA)->alignableObjectId())
00453                                    << " with params!";
00454     }
00455 //     edm::LogInfo("Alignment") << "@SUB=PedeSteerer::hierarchyConstraints"
00456 //                            << aliDaughts.size() << " ali param components";
00457     if (aliDaughts.empty()) continue;
00458 //     edm::LogInfo("Alignment") << "@SUB=PedeSteerer::hierarchyConstraints"
00459 //                            << aliDaughts.size() << " alignable components ("
00460 //                            << (*iA)->size() << " in total) for " 
00461 //                            << aliId.alignableTypeName(*iA) 
00462 //                            << ", layer " << aliId.typeAndLayerFromAlignable(*iA).second
00463 //                            << ", position " << (*iA)->globalPosition()
00464 //                            << ", r = " << (*iA)->globalPosition().perp();
00465     if (!filePtr) filePtr = this->createSteerFile(fileName, true);
00466     ++nConstraints;
00467     this->hierarchyConstraint(*iA, aliDaughts, *filePtr);
00468   }
00469 
00470   delete filePtr; // automatically flushes, no problem if NULL ptr.   
00471 
00472   return nConstraints;
00473 }
00474 
00475 //_________________________________________________________________________
00476 void PedeSteerer::hierarchyConstraint(const Alignable *ali,
00477                                       const std::vector<Alignable*> &components,
00478                                       std::ofstream &file) const
00479 {
00480   typedef AlignmentParameterStore::ParameterId ParameterId;
00481 
00482   std::vector<std::vector<ParameterId> > paramIdsVec;
00483   std::vector<std::vector<double> > factorsVec;
00484   const bool allConstr = false; // true; // make configurable?
00485   static bool first = true;
00486   if (allConstr && first) {
00487     edm::LogWarning("Alignment") << "@SUB=PedeSteerer::hierarchyConstraint"
00488                                  << "changed to use all 6 constraints";
00489     first = false;
00490   }
00491   if (!myParameterStore->hierarchyConstraints(ali, components, paramIdsVec, factorsVec, allConstr,
00492                                               theMinHieraConstrCoeff)){
00493     edm::LogWarning("Alignment") << "@SUB=PedeSteerer::hierarchyConstraint"
00494                                  << "Problems from store.";
00495   }
00496 
00497   for (unsigned int iConstr = 0; iConstr < paramIdsVec.size(); ++iConstr) {
00498     std::ostringstream aConstr;
00499 
00500     const std::vector<ParameterId> &parIds = paramIdsVec[iConstr];
00501     const std::vector<double> &factors = factorsVec[iConstr];
00502     unsigned int nParPerConstr = 0; // keep track of used factor/parId pair
00503     // parIds.size() == factors.size() granted by myParameterStore->hierarchyConstraints
00504     for (unsigned int iParam = 0; iParam < parIds.size(); ++iParam) {
00505       Alignable *aliSubComp = parIds[iParam].first;
00506       const unsigned int compParNum = parIds[iParam].second;
00507       if (this->isNoHiera(aliSubComp)) {
00508         if (myIsSteerFileDebug) aConstr << "* Taken out of hierarchy: ";
00509         continue;
00510       }
00511       const unsigned int aliLabel = myLabels->alignableLabel(aliSubComp);
00512       const unsigned int paramLabel = myLabels->parameterLabel(aliLabel, compParNum);
00513       // FIXME: multiply by cmsToPedeFactor(subcomponent)/cmsToPedeFactor(mother) (or vice a versa?)
00514       aConstr << paramLabel << "    " << factors[iParam];
00515       if (myIsSteerFileDebug) { // debug
00516         AlignableObjectId objId; // costly constructor, but only debug here...
00517         aConstr << "   ! for param " << compParNum << " of a " 
00518                 << objId.typeToName(aliSubComp->alignableObjectId()) << " at " 
00519                 << aliSubComp->globalPosition() << ", r=" << aliSubComp->globalPosition().perp();
00520       }
00521       aConstr << "\n";
00522       ++nParPerConstr; // OK, we used one.
00523     } // end loop on params
00524 
00525     // 
00526     if (nParPerConstr && nParPerConstr >= theMinHieraParPerConstr) { // Enough to make sense?
00527       if (myIsSteerFileDebug) { //debug
00528         AlignableObjectId objId; // costly constructor, but only debug here...
00529         file << "\n* Nr. " << iConstr << " of a '"
00530              << objId.typeToName(ali->alignableObjectId()) << "' (label "
00531              << myLabels->alignableLabel(const_cast<Alignable*>(ali)) // ugly cast: FIXME!
00532              << "), position " << ali->globalPosition()
00533              << ", r = " << ali->globalPosition().perp();
00534       }
00535       file << "\nConstraint   0.\n" << aConstr.str(); // in future 'Wconstraint'?
00536     } else if (nParPerConstr > 0) { // no warning for trivial case...
00537       edm::LogWarning("Alignment") << "@SUB=PedeSteerer::hierarchyConstraint"
00538                                    << "Skip constraint on " << nParPerConstr
00539                                    << " parameter(s):\n" << aConstr.str();
00540     }
00541   } // end loop on constraints
00542 }
00543 
00544 //_________________________________________________________________________
00545 unsigned int PedeSteerer::presigmas(const std::vector<edm::ParameterSet> &cffPresi,
00546                                     const std::string &fileName,
00547                                     const std::vector<Alignable*> &alis,
00548                                     AlignableTracker *aliTracker, AlignableMuon *aliMuon, AlignableExtras *aliExtras)
00549 {
00550   // We loop on given PSet's, each containing a parameter selection and the presigma value
00551   // The resulting presigmas are stored in a map with Alignable* as key.
00552   // This map, 'fileName' and 'alis' are passed further to create the steering file.
00553 
00554   AlignmentParameterSelector selector(aliTracker, aliMuon, aliExtras);
00555   AlignablePresigmasMap aliPresiMap; // map to store alis with presigmas of their parameters 
00556   for (std::vector<edm::ParameterSet>::const_iterator iSet = cffPresi.begin(), iE = cffPresi.end();
00557        iSet != iE; ++iSet) { // loop on individual PSets defining ali-params with their presigma
00558     selector.clear();
00559     selector.addSelections((*iSet).getParameter<edm::ParameterSet>("Selector"));
00560     const std::vector<Alignable*> &alis = selector.selectedAlignables();
00561     const std::vector<std::vector<char> > &sels =  selector.selectedParameters();
00562     const float presigma = (*iSet).getParameter<double>("presigma");
00563     if (presigma <= 0.) { // given presigma > 0., 0. later used if not (yet) chosen for parameter
00564       throw cms::Exception("BadConfig")
00565         << "[PedeSteerer::presigmas]: Pre-sigma must be > 0., but is " << presigma << ".";
00566     }
00567     // now loop on alis of present selection
00568     for (unsigned int iAli = 0; iAli < alis.size(); ++iAli) {
00569       std::vector<float> &presigmas = aliPresiMap[alis[iAli]]; // existing or empty, so ensure length:
00570       if (presigmas.size() < sels[iAli].size()) presigmas.resize(sels[iAli].size(), 0.);
00571       for (unsigned int iParam = 0; iParam < sels[iAli].size(); ++iParam) { // loop on parameters
00572         if (sels[iAli][iParam] != '0') { // all but '0' means to apply the chosen presigma
00573           if (presigmas[iParam] != 0.) { // reset forbidden (would make it order dependent!)
00574             throw cms::Exception("BadConfig")
00575               << "[PedeSteerer::presigmas]: Try to set pre-sigma " << presigma << ", but already "
00576               << "set " << presigmas[iParam] << " (for a " 
00577               << AlignableObjectId().typeToName(alis[iAli]->alignableObjectId()) << ").";
00578           }
00579           presigmas[iParam] = presigma;
00580         } // end if selected for presigma
00581       } // end loop on params
00582     } // end loop on alignables for given selection and presigma
00583   } // end loop on PSets 
00584 
00585   if (aliPresiMap.empty()) return 0;
00586   else return this->presigmasFile(fileName, alis, aliPresiMap);
00587 }
00588 
00589 //_________________________________________________________________________
00590 unsigned int PedeSteerer::presigmasFile(const std::string &fileName,
00591                                         const std::vector<Alignable*> &alis,
00592                                         const AlignablePresigmasMap &aliPresiMap)
00593 {
00594   // Check if 'alis' are in aliPresiMap, 
00595   // if yes apply presigma - but NOT if parameter is fixed!
00596   std::ofstream *filePtr = 0;
00597   const AlignableObjectId aliObjId;
00598 
00599   unsigned int nPresiParam = 0;
00600   for (std::vector<Alignable*>::const_iterator iAli = alis.begin(), iAliE = alis.end();
00601        iAli != iAliE; ++iAli) {
00602     // Any presigma chosen for alignable?
00603     AlignablePresigmasMap::const_iterator presigmasIt = aliPresiMap.find(*iAli);
00604     if (presigmasIt == aliPresiMap.end()) continue; // no presigma chosen for alignable
00605 
00606     // Why does the following not work? It does with CMSSW_1_3_X on SLC3...
00607     // const AlignablePresigmasMap::data_type &presigmas = presigmasIt->second;
00608     const std::vector<float> &presigmas = presigmasIt->second; // I want to hide float or double...
00609     for (unsigned int iParam = 0; iParam < presigmas.size(); ++iParam) {
00610       // Now check whether a presigma value > 0. chosen: 
00611       if (presigmas[iParam] <= 0.) continue; // must be positive, '<' checked above
00612       // Do not apply presigma to inactive or fixed values.
00613       if (!(*iAli)->alignmentParameters()->selector()[iParam]) continue;
00614       SelectionUserVariables *selVar 
00615         = dynamic_cast<SelectionUserVariables*>((*iAli)->alignmentParameters()->userVariables());
00616       const char selChar = (selVar ? selVar->fullSelection()[iParam] : '1');
00617       if (selChar == 'f' || selChar == 'F' || selChar == 'c' || selChar == 'C') continue;
00618       // Finally create and write steering file:
00619       if (!filePtr) {
00620         filePtr = this->createSteerFile(fileName, true);
00621         (*filePtr) << "* Presigma values for active parameters: \nParameter\n";
00622       }
00623       const unsigned int aliLabel = myLabels->alignableLabel(*iAli);
00624       (*filePtr) << myLabels->parameterLabel(aliLabel, iParam) << "   0.   " 
00625                  << presigmas[iParam] * fabs(this->cmsToPedeFactor(iParam));
00626       if (myIsSteerFileDebug) {
00627         (*filePtr) << "  ! for a " << aliObjId.typeToName((*iAli)->alignableObjectId());
00628       }
00629       (*filePtr) << '\n';
00630 
00631       ++nPresiParam;
00632     } // end loop on parameters for alignables with chosen presigmas
00633   } // end loop on alignables
00634 
00635   delete filePtr; // close properly file
00636   return nPresiParam;
00637 }
00638 
00639 //_________________________________________________________________________
00640 std::ofstream* PedeSteerer::createSteerFile(const std::string &name, bool addToList)
00641 {
00642   const std::string realName(myNoSteerFiles ? "/dev/null" : name.c_str());
00643 
00644   std::ofstream *result = new std::ofstream(realName.c_str(), std::ios::out);
00645   if (!result || !result->is_open()) {
00646     delete result; // needed before exception in case just open failed
00647     throw cms::Exception("FileOpenProblem") << "[PedeSteerer::createSteerFile]" 
00648                                             << "Could not open " << realName 
00649                                             << " as output file.";
00650   } else if (addToList) {
00651     mySteeringFiles.push_back(realName); // keep track
00652   }
00653 
00654   return result;
00655 }
00656 
00657 
00658 //_________________________________________________________________________
00659 std::string PedeSteerer::fileName(const std::string &addendum) const
00660 {
00661 
00662   std::string name(myDirectory);
00663   name += myConfig.getParameter<std::string>("steerFile");
00664   name += addendum;
00665   name += ".txt";
00666 
00667   return name;
00668 }
00669 
00670 //___________________________________________________________________________
00671 void PedeSteerer::buildSubSteer(AlignableTracker *aliTracker, AlignableMuon *aliMuon, AlignableExtras *aliExtras)
00672 {
00673   const std::vector<Alignable*> &alis = myParameterStore->alignables();
00674 
00675   if (theCoordMaster && !theCoordDefiners.empty()) {
00676     const std::string nameCoordFile(this->fileName("Coord"));
00677     this->defineCoordinates(theCoordDefiners, theCoordMaster, nameCoordFile);
00678     edm::LogInfo("Alignment") << "@SUB=PedeSteerer::buildSubSteer" 
00679                               << theCoordDefiners.size() << " highest level objects define the "
00680                               << "coordinate system, steering file " << nameCoordFile << ".";
00681   }
00682 
00683   const std::string nameFixFile(this->fileName("FixPara"));
00684   const std::pair<unsigned int, unsigned int> nFixFixCor(this->fixParameters(alis, nameFixFile));
00685   if (nFixFixCor.first != 0 || nFixFixCor.second != 0) {
00686     edm::LogInfo("Alignment") << "@SUB=PedeSteerer::buildSubSteer" 
00687                               << nFixFixCor.first << " parameters fixed at 0. and "
00688                               << nFixFixCor.second << " at 'original' position, "
00689                               << "steering file " << nameFixFile << ".";
00690   } 
00691 
00692   if (this->buildNoHierarchyCollection(alis)) { // before hierarchyConstraints(..)
00693     edm::LogInfo("Alignment") << "@SUB=PedeSteerer::buildSubSteer"
00694                               << myNoHieraCollection.size()<<" alignables taken out of hierarchy.";
00695   }
00696 
00697   const std::string nameHierarchyFile(this->fileName("Hierarchy"));
00698   unsigned int nConstraint = this->hierarchyConstraints(alis, nameHierarchyFile);
00699   if (nConstraint) {
00700     edm::LogInfo("Alignment") << "@SUB=PedeSteerer::buildSubSteer" 
00701                               << "Hierarchy constraints for " << nConstraint << " alignables, "
00702                               << "steering file " << nameHierarchyFile << ".";
00703   }
00704 
00705   const std::string namePresigmaFile(this->fileName("Presigma"));
00706   unsigned int nPresigma = 
00707     this->presigmas(myConfig.getParameter<std::vector<edm::ParameterSet> >("Presigmas"),
00708                     namePresigmaFile, alis, aliTracker, aliMuon, aliExtras);
00709   if (nPresigma) {
00710     edm::LogInfo("Alignment") << "@SUB=PedeSteerer::buildSubSteer" 
00711                               << "Presigma values set for " << nPresigma << " parameters, "
00712                               << "steering file " << namePresigmaFile << ".";
00713   }
00714 
00715   // Delete all SelectionUserVariables now? They will anyway be overwritten by MillePedeVariables...
00716 }
00717 
00718 //_________________________________________________________________________
00719 std::string PedeSteerer::buildMasterSteer(const std::vector<std::string> &binaryFiles)
00720 {
00721   const std::string nameMasterSteer(this->fileName("Master"));
00722   std::ofstream *mainSteerPtr = this->createSteerFile(nameMasterSteer, false);
00723   if (!mainSteerPtr) return "";
00724 
00725   // add external steering files, if any
00726   std::vector<std::string> addfiles =  myConfig.getParameter<std::vector<std::string> >("additionalSteerFiles");
00727   mySteeringFiles.insert(mySteeringFiles.end(),
00728                   addfiles.begin(),
00729                   addfiles.end());
00730 
00731   // add steering files to master steering file
00732   std::ofstream &mainSteerRef = *mainSteerPtr;
00733   for (unsigned int iFile = 0; iFile < mySteeringFiles.size(); ++iFile) {
00734     mainSteerRef << mySteeringFiles[iFile] << "\n";
00735   }
00736 
00737   // add binary files to master steering file
00738   mainSteerRef << "\nCfiles\n";
00739   for (unsigned int iFile = 0; iFile < binaryFiles.size(); ++iFile) {
00740     mainSteerRef << binaryFiles[iFile] << "\n";
00741   }
00742 
00743   // add method
00744   mainSteerRef << "\nmethod  " << myConfig.getParameter<std::string>("method") << "\n";
00745 
00746   // add further options
00747   const std::vector<std::string> opt(myConfig.getParameter<std::vector<std::string> >("options"));
00748   mainSteerRef << "\n* Outlier treatment and other options \n";
00749   for (unsigned int i = 0; i < opt.size(); ++i) {
00750     mainSteerRef << opt[i] << "\n";
00751   }
00752 
00753   delete mainSteerPtr;  // close (and flush) again
00754 
00755   return nameMasterSteer;
00756 }
00757 
00758 //_________________________________________________________________________
00759 int PedeSteerer::runPede(const std::string &masterSteer) const
00760 {
00761   if (masterSteer.empty()) {
00762     edm::LogError("Alignment") << "@SUB=PedeSteerer::runPede" << "Empty master steer file, stop";
00763     return 0; //false;
00764   }
00765 
00766   std::string command(myConfig.getUntrackedParameter<std::string>("pedeCommand"));
00767   (command += " ") += masterSteer;
00768   const std::string dump(myConfig.getUntrackedParameter<std::string>("pedeDump"));
00769   if (!dump.empty()) {
00770     command += " > ";
00771     (command += myDirectory) += dump;
00772   }
00773 
00774   edm::LogInfo("Alignment") << "@SUB=PedeSteerer::runPede" << "Start running " << command;
00775   // FIXME: Recommended interface to system commands?
00776   int shellReturn = gSystem->Exec(command.c_str());
00777   edm::LogInfo("Alignment") << "@SUB=PedeSteerer::runPede" << "Command returns " << shellReturn;
00778 
00779   return shellReturn;
00780 }