CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/Alignment/CommonAlignment/src/MisalignmentScenarioBuilder.cc

Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 #include <string>
00010 #include <iostream>
00011 #include <sstream>
00012 #include <stdlib.h>
00013 
00014 // Framework
00015 #include "FWCore/Utilities/interface/Exception.h"
00016 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00017 
00018 // Alignment
00019 #include "Alignment/CommonAlignment/interface/MisalignmentScenarioBuilder.h"
00020 #include "Alignment/CommonAlignment/interface/Alignable.h" 
00021 
00022 //__________________________________________________________________________________________________
00023 // Call for each alignable the more general version with its appropriate level name. 
00024 void MisalignmentScenarioBuilder::decodeMovements_(const edm::ParameterSet &pSet, 
00025                                                    const std::vector<Alignable*> &alignables)
00026 {
00027 
00028   // first create a map with one std::vector<Alignable*> per type (=levelName)
00029   typedef std::map<std::string, std::vector<Alignable*> > AlignablesMap;
00030   AlignablesMap alisMap;
00031   for (std::vector<Alignable*>::const_iterator iA = alignables.begin(); iA != alignables.end(); ++iA) {
00032     const std::string &levelName = AlignableObjectId::idToString((*iA)->alignableObjectId());
00033     alisMap[levelName].push_back(*iA); // either first entry of new level or add to an old one
00034   }
00035 
00036   // Now call the more general version for each entry in the map.
00037   //
00038   // There is a hack to ensure that strip components are called in the same order
00039   // as in old version of TrackerScenarioBuilder (TIB,TID,TOB,TEC) while 
00040   // std::map seems to order alphabetically (TECEndcap,TIBHalfBarrel,TIDEndcap,TOBHalfBarrel).
00041   // Order matters due to random sequence. If scenarios are allowed to change
00042   // 'numerically', remove this comment and the lines marked with 'HACK'.
00043   const AlignablesMap::iterator itTec = alisMap.find("TECEndcap"); // HACK
00044   for (AlignablesMap::iterator it = alisMap.begin(); it != alisMap.end(); ++it) {
00045     if (it == itTec) continue; // HACK
00046     this->decodeMovements_(pSet, it->second, it->first);
00047   }
00048   if (itTec != alisMap.end()) this->decodeMovements_(pSet, itTec->second, itTec->first); // HACK
00049 }
00050 
00051 
00052 //__________________________________________________________________________________________________
00053 // Decode nested parameter sets: this is the tricky part... Recursively called on components
00054 void MisalignmentScenarioBuilder::decodeMovements_(const edm::ParameterSet &pSet, 
00055                                                    const std::vector<Alignable*> &alignables,
00056                                                    const std::string &levelName)
00057 {
00058 
00059   indent_ += " "; // For indented output!
00060 
00061   // Retrieve parameters for all components at this level
00062   std::ostringstream name;
00063   name << levelName << "s";
00064   edm::ParameterSet globalParameters = this->getParameterSet_( name.str(), pSet );
00065   if ( !globalParameters.empty() ) {
00066     LogDebug("PrintParameters") << indent_ << " *** " << levelName << ": found "
00067                                 << globalParameters.getParameterNames().size() 
00068                                 << " global parameters" << std::endl;
00069   }
00070   
00071   // Propagate down parameters from upper level
00072   this->propagateParameters_( pSet, name.str(), globalParameters );
00073   LogDebug("PrintParameters") << indent_ << " global parameter is now:" << std::endl;
00074   this->printParameters_( globalParameters, true );
00075 
00076   // Loop on alignables
00077   int iComponent = 0; // physical numbering starts at 1...
00078   for (std::vector<Alignable*>::const_iterator iter = alignables.begin();
00079        iter != alignables.end(); ++iter) {
00080     iComponent++;
00081 
00082     // Check for special parameters -> merge with global
00083     name.str("");
00084     name << levelName << iComponent;
00085 
00086     edm::ParameterSet localParameters = this->getParameterSet_( levelName, iComponent, pSet );
00087     LogDebug("PrintParameters") << indent_ << " ** " << name.str() << ": found "
00088                                 << localParameters.getParameterNames().size() 
00089                                 << " local parameters"  << std::endl;
00090     this->mergeParameters_( localParameters, globalParameters );
00091           
00092     // Retrieve and apply parameters
00093     LogDebug("PrintParameters")  << indent_ << " parameters to apply:" << std::endl;
00094     this->printParameters_( localParameters, true );
00095     if ( theModifier.modify( (*iter), localParameters ) ) {
00096       theModifierCounter++;
00097       LogDebug("PrintParameters") << indent_ << "Movements applied to " << name.str();
00098     }
00099 
00100     // Apply movements to components
00101     std::vector<std::string> parameterSetNames;
00102     localParameters.getParameterSetNames( parameterSetNames, true );
00103     if ( (*iter)->size() > 0 && parameterSetNames.size() > 0 )
00104       // Has components and remaining parameter sets
00105       this->decodeMovements_( localParameters, (*iter)->components() );
00106   }
00107 
00108   indent_ = indent_.substr( 0, indent_.length()-1 );
00109 
00110 }
00111 
00112 
00113 
00114 //__________________________________________________________________________________________________
00115 // Merge two sets of parameters into one. The local set overrides the global one
00116 // A recursive merging is done on parameter sets.
00117 void MisalignmentScenarioBuilder::mergeParameters_( edm::ParameterSet& localSet, 
00118                                                     const edm::ParameterSet& globalSet ) const
00119 {
00120 
00121   indent_ += " ";
00122 
00123   // Loop on globalSet. Add to localSet all non-existing parameters
00124   std::vector<std::string> globalParameterNames = globalSet.getParameterNames();
00125   for ( std::vector<std::string>::iterator iter = globalParameterNames.begin();
00126         iter != globalParameterNames.end(); iter ++ ) {
00127 
00128     if (globalSet.existsAs<edm::ParameterSet>(*iter)) {
00129       // This is a parameter set: check it
00130       edm::ParameterSet subLocalSet = this->getParameterSet_( (*iter), localSet );
00131       if ( subLocalSet.empty() ) {
00132         // No local subset exists: just insert it
00133         localSet.copyFrom(globalSet, (*iter));
00134       } else {
00135         // Merge with local subset and replace
00136         this->mergeParameters_( subLocalSet, globalSet.getParameter<edm::ParameterSet>(*iter) );
00137         localSet.addParameter<edm::ParameterSet>( (*iter), subLocalSet );
00138       }
00139     } else {
00140       // If (*iter) exists, (silently...) not replaced:
00141       localSet.copyFrom(globalSet, (*iter));
00142     }
00143   }
00144 
00145   indent_ = indent_.substr( 0, indent_.length()-1 );
00146 
00147 }
00148 
00149 
00150 //__________________________________________________________________________________________________
00151 // Propagates some parameters from upper level.
00152 // Parameter sets are also propagated down (if name different from global name) or merged down.
00153 void MisalignmentScenarioBuilder::propagateParameters_( const edm::ParameterSet& pSet, 
00154                                                         const std::string& globalName,
00155                                                         edm::ParameterSet& subSet ) const
00156 {
00157   indent_ += " "; // For indented output!
00158 
00159   // Propagate some given parameters
00160   std::vector<std::string> parameterNames = pSet.getParameterNames();
00161   for ( std::vector<std::string>::iterator iter = parameterNames.begin();
00162         iter != parameterNames.end(); iter++ ) {
00163     if ( theModifier.isPropagated( *iter ) ) { // like 'distribution', 'scale', etc.
00164       LogDebug("PropagateParameters") << indent_ << " - adding parameter " << (*iter) << std::endl;
00165       subSet.copyFrom(pSet, (*iter)); // If existing, is not replaced.
00166     }
00167   }
00168 
00169   // Propagate all tracked parameter sets
00170   std::vector<std::string> pSetNames;
00171   if ( pSet.getParameterSetNames( pSetNames, true ) > 0 ) {
00172     for ( std::vector<std::string>::const_iterator it = pSetNames.begin();
00173           it != pSetNames.end(); it++ ) {
00174       const std::string rootName = this->rootName_(*it);
00175       const std::string globalRoot(this->rootName_(globalName));
00176       if (rootName.compare(0, rootName.length(), globalRoot) == 0) {
00177         // Parameter for this level: skip
00178         LogDebug("PropagateParameters") << indent_ << " - skipping PSet " << (*it) << " from global "
00179                                         << globalName << std::endl;
00180       } else if ( this->isTopLevel_(*it) ) {
00181         // Top-level parameters should not be propagated
00182         LogDebug("PropagateParameters") << indent_  
00183                                         << " - skipping top-level PSet " << (*it) 
00184                                         << " global " << globalName << std::endl;
00185 
00186       } else if (!this->possiblyPartOf(*it, globalRoot)) {
00187         // (*it) is a part of the detector that does not fit to globalName
00188         LogDebug("PropagateParameters") << indent_ 
00189                                         << " - skipping PSet " << (*it) 
00190                                         << " not fitting into global " << globalName << std::endl;
00191 
00192       } else if ( AlignableObjectId::stringToId( rootName ) == align::invalid ) {
00193         // Parameter is not known!
00194         throw cms::Exception("BadConfig") << "Unknown parameter set name " << rootName;
00195       } else {
00196         // Pass down any other: in order to merge PSets, create dummy PSet
00197         // only containing this PSet and merge it recursively.
00198         LogDebug("PropagateParameters") << indent_ << " - adding PSet " << (*it) 
00199                                         << " global " << globalName << std::endl;
00200         edm::ParameterSet m_subSet;
00201         m_subSet.addParameter<edm::ParameterSet>( (*it), 
00202                                                   pSet.getParameter<edm::ParameterSet>(*it) );
00203         this->mergeParameters_( subSet, m_subSet );
00204       }  
00205     }
00206   }
00207 
00208   indent_ = indent_.substr( 0, indent_.length()-1 );
00209 }
00210 
00211 
00212 //__________________________________________________________________________________________________
00213 // Get parameter set corresponding to given name.
00214 // Return empty parameter set if does not exist.
00215 edm::ParameterSet MisalignmentScenarioBuilder::getParameterSet_( const std::string& name,
00216                                                                  const edm::ParameterSet& pSet ) const
00217 {
00218 
00219   edm::ParameterSet result;
00220 
00221   // Get list of parameter set names and retrieve requested one
00222   std::vector<std::string> parameterSetNames;
00223   if ( this->hasParameter_( name, pSet ) ) {
00224     result = pSet.getParameter<edm::ParameterSet>( name );
00225   }
00226 
00227   return result;
00228 }
00229 
00230 //__________________________________________________________________________________________________
00231 // Get parameter set corresponding to given level name and number.
00232 // Return empty parameter set if does not exist.
00233 edm::ParameterSet MisalignmentScenarioBuilder::getParameterSet_( const std::string& levelName, int iComponent, 
00234                                                                  const edm::ParameterSet& pSet ) const
00235 {
00236   edm::ParameterSet result;
00237   unsigned int nFittingPsets = 0;
00238 
00239   // Get list of parameter set names and look for requested one
00240   std::vector<std::string> pNames = pSet.getParameterNames();
00241   for (std::vector<std::string>::iterator iter = pNames.begin(); iter != pNames.end(); ++iter) {
00242     if (iter->find(levelName) != 0) continue; // parameter not starting with levelName
00243 
00244     const std::string numberString(*iter, levelName.size());
00245     //    if (numberString.empty() || numberString == "s") { // "s" only left means we have e.g. 'TOBs' 
00246     if (numberString.empty()) { // check on "s" not needed, see below
00247       continue;  // nothing left in levelName to be iComponent...
00248     }
00249     // now look for numbers (separated by '_', tolerating '__' or ending with '_')
00250     size_t lastPos = 0;
00251     size_t pos     = numberString.find_first_of('_', lastPos);
00252     while (std::string::npos != pos || std::string::npos != lastPos) {
00253       const std::string digit(numberString.substr(lastPos, pos - lastPos));
00254 
00255       bool isDigit = !digit.empty();
00256       for (std::string::const_iterator dIt = digit.begin(); dIt != digit.end(); ++dIt) {
00257         if (!isdigit(*dIt)) isDigit = false; // check all 'letters' to be a digit
00258       }
00259       if (!isDigit) {
00260         if (lastPos != 0) { // do not throw if e.g. after 'TOB' ('Det') you find only 's' (Unit<n>)
00261           throw cms::Exception("BadConfig") << "[MisalignmentScenarioBuilder::getParameterSet_] "
00262                                             << "Expect only numbers, separated by '_' after " 
00263                                             << levelName << " in " << *iter << std::endl;
00264         }
00265         break;
00266       }
00267 
00268       if (atoi(digit.c_str()) == iComponent) {
00269         ++nFittingPsets;
00270         LogDebug("getParameterSet_") << indent_ << "found " << *iter << " matching "
00271                                      << levelName << iComponent;
00272         result = pSet.getParameter<edm::ParameterSet>(*iter);
00273         break;
00274       }
00275       lastPos = numberString.find_first_not_of('_', pos);
00276       pos     = numberString.find_first_of('_', lastPos);
00277     }
00278   } // end loop on names of parameters in pSet
00279   
00280   if (nFittingPsets > 1) {
00281     throw cms::Exception("BadConfig") << "[MisalignmentScenarioBuilder::getParameterSet_] "
00282                                       << "Found " << nFittingPsets << " PSet for " 
00283                                       << levelName << " " << iComponent << "." << std::endl;
00284   }
00285 
00286   return result;
00287 }
00288 
00289 //__________________________________________________________________________________________________
00290 bool MisalignmentScenarioBuilder::hasParameter_( const std::string& name,
00291                                                  const edm::ParameterSet& pSet ) const
00292 {
00293 
00294   // Get list of parameter set names and look for requested one
00295   std::vector<std::string> names = pSet.getParameterNames();
00296 
00297   return ( std::find( names.begin(), names.end(), name ) != names.end() );
00298 
00299 }
00300 
00301 
00302 //__________________________________________________________________________________________________
00303 // Print parameter set. If showPsets is 'false', do not print PSets
00304 void MisalignmentScenarioBuilder::printParameters_( const edm::ParameterSet& pSet, 
00305                                                     const bool showPsets ) const
00306 {
00307 
00308   std::vector<std::string> parameterNames = pSet.getParameterNames();
00309   for ( std::vector<std::string>::iterator iter = parameterNames.begin();
00310         iter != parameterNames.end(); iter++ ) {
00311     if (showPsets || !pSet.existsAs<edm::ParameterSet>(*iter)) {
00312 //       LogTrace("PrintParameters") << indent_ << "   " << (*iter) << " = " 
00313 //                                << pSet.retrieve( *iter ).toString() << std::endl;
00314 // From Bill Tannenbaum:
00315 // You can use
00316 //   pset.getParameterAsString(aString).
00317 // This function was added with the new tag.
00318 //   However, there is a possible complication if the parameter in question is
00319 //   itself a ParameterSet or a vector of ParameterSets.  In the new format, a
00320 //   ParameterSet cannot be converted to a string until its ID is calculated,
00321 //   which happens when it is registered.  So, if you get error messages about
00322 //   not being able to convert an unregistered ParameterSet to a string, you can
00323 //   do one of two things:
00324 // A) You can use ParameterSet::dump() to print the parameter set, instead of
00325 //    getParameterAsString().  This does not require registering.  I'm not sure of
00326 //    the exact format of the dump output (Rick wrote this, I think).
00327 // OR
00328 // B) You can use ParameterSet::registerIt() to register the parameter set
00329 //    before calling getParameterAsString().
00330 //
00331 // In either case, you can use existsAs to determine which parameters are
00332 // themselves parameter sets or vectors of parameter sets.
00333 //
00334 // Note that in the new parameter set format, ParameterSet::toString() does not
00335 // write out nested parameter sets by value.  It writes them out by
00336 // "reference", i.e it writes the ID.
00337     }
00338   }
00339 }
00340 
00341 
00342 //__________________________________________________________________________________________________
00343 bool MisalignmentScenarioBuilder::isTopLevel_( const std::string& parameterSetName ) const
00344 {
00345   // Get root name (strip last character[s])
00346   std::string root = this->rootName_( parameterSetName );
00347 
00348   // tracker stuff treated in overwriting TrackerScenarioBuilder::isTopLevel_(..) 
00349   if ( root == "DTSector" ) return true;
00350   else if ( root == "CSCSector" ) return true;
00351   else if ( root == "Muon" ) return true;
00352 
00353   return false;
00354 
00355 }
00356 
00357 //__________________________________________________________________________________________________
00358 bool MisalignmentScenarioBuilder::possiblyPartOf(const std::string & /*sub*/, const std::string &/*large*/) const
00359 {
00360   return true; // possibly overwrite in specific class
00361 }
00362 
00363 
00364 //__________________________________________________________________________________________________
00365 // Get root name of parameter set (e.g. return 'Rod' from 'Rods' or 'Rod1')
00366 const std::string 
00367 MisalignmentScenarioBuilder::rootName_( const std::string& parameterSetName ) const
00368 {
00369 
00370   std::string result = parameterSetName; // Initialise to full string
00371   
00372   // Check if string ends with 's'
00373   const int lastChar = parameterSetName.length()-1;
00374   if ( parameterSetName[lastChar] == 's' ) {
00375     result =  parameterSetName.substr( 0, lastChar );
00376   } else {
00377     // Otherwise, look for numbers (assumes names have no numbers inside...)
00378     for ( unsigned int ichar = 0; ichar<parameterSetName.length(); ichar++ ) {
00379       if ( isdigit(parameterSetName[ichar]) ) {
00380         result = parameterSetName.substr( 0, ichar );
00381         break; // Stop at first digit
00382       }
00383     }
00384   }
00385 
00386   LogDebug("PrintParameters") << "Name was " << parameterSetName << ", root is " << result;
00387 
00388   return result;
00389 
00390 }