CMS 3D CMS Logo

MisalignmentScenarioBuilder.cc
Go to the documentation of this file.
1 
9 #include <string>
10 #include <iostream>
11 #include <sstream>
12 #include <cstdlib>
13 
14 // Framework
17 
18 // Alignment
21 
22 //______________________________________________________________________________
24  : alignableObjectId_(geometry) {}
25 
26 //__________________________________________________________________________________________________
27 // Call for each alignable the more general version with its appropriate level name.
29  // first create a map with one align::Alignables per type (=levelName)
30  using AlignablesMap = std::map<std::string, align::Alignables>;
31  AlignablesMap alisMap;
32  for (align::Alignables::const_iterator iA = alignables.begin(); iA != alignables.end(); ++iA) {
33  const std::string& levelName = alignableObjectId_.idToString((*iA)->alignableObjectId());
34  alisMap[levelName].push_back(*iA); // either first entry of new level or add to an old one
35  }
36 
37  // Now call the more general version for each entry in the map.
38  //
39  // There is a hack to ensure that strip components are called in the same order
40  // as in old version of TrackerScenarioBuilder (TIB,TID,TOB,TEC) while
41  // std::map seems to order alphabetically (TECEndcap,TIBHalfBarrel,TIDEndcap,TOBHalfBarrel).
42  // Order matters due to random sequence. If scenarios are allowed to change
43  // 'numerically', remove this comment and the lines marked with 'HACK'.
44  const AlignablesMap::iterator itTec = alisMap.find("TECEndcap"); // HACK
45  for (AlignablesMap::iterator it = alisMap.begin(); it != alisMap.end(); ++it) {
46  if (it == itTec)
47  continue; // HACK
48  this->decodeMovements_(pSet, it->second, it->first);
49  }
50  if (itTec != alisMap.end())
51  this->decodeMovements_(pSet, itTec->second, itTec->first); // HACK
52 }
53 
54 //__________________________________________________________________________________________________
55 // Decode nested parameter sets: this is the tricky part... Recursively called on components
57  const align::Alignables& alignables,
58  const std::string& levelName) {
59  indent_ += " "; // For indented output!
60 
61  // Retrieve parameters for all components at this level
62  std::ostringstream name;
63  name << levelName << "s";
64  edm::ParameterSet globalParameters = this->getParameterSet_(name.str(), pSet);
65  if (!globalParameters.empty()) {
66  LogDebug("PrintParameters") << indent_ << " *** " << levelName << ": found "
67  << globalParameters.getParameterNames().size() << " global parameters" << std::endl;
68  }
69 
70  // Propagate down parameters from upper level
71  this->propagateParameters_(pSet, name.str(), globalParameters);
72  LogDebug("PrintParameters") << indent_ << " global parameter is now:" << std::endl;
73  this->printParameters_(globalParameters, true);
74 
75  // Loop on alignables
76  int iComponent = 0; // physical numbering starts at 1...
77  for (align::Alignables::const_iterator iter = alignables.begin(); iter != alignables.end(); ++iter) {
78  iComponent++;
79 
80  // Check for special parameters -> merge with global
81  name.str("");
82  name << levelName << iComponent;
83 
84  edm::ParameterSet localParameters = this->getParameterSet_(levelName, iComponent, pSet);
85  LogDebug("PrintParameters") << indent_ << " ** " << name.str() << ": found "
86  << localParameters.getParameterNames().size() << " local parameters" << std::endl;
87  this->mergeParameters_(localParameters, globalParameters);
88 
89  // Retrieve and apply parameters
90  LogDebug("PrintParameters") << indent_ << " parameters to apply:" << std::endl;
91  this->printParameters_(localParameters, true);
92  if (theModifier.modify((*iter), localParameters)) {
94  LogDebug("PrintParameters") << indent_ << "Movements applied to " << name.str();
95  }
96 
97  // Apply movements to components
98  std::vector<std::string> parameterSetNames;
99  localParameters.getParameterSetNames(parameterSetNames, true);
100  if ((*iter)->size() > 0 && !parameterSetNames.empty())
101  // Has components and remaining parameter sets
102  this->decodeMovements_(localParameters, (*iter)->components());
103  }
104 
105  indent_ = indent_.substr(0, indent_.length() - 1);
106 }
107 
108 //__________________________________________________________________________________________________
109 // Merge two sets of parameters into one. The local set overrides the global one
110 // A recursive merging is done on parameter sets.
112  const edm::ParameterSet& globalSet) const {
113  indent_ += " ";
114 
115  // Loop on globalSet. Add to localSet all non-existing parameters
116  std::vector<std::string> globalParameterNames = globalSet.getParameterNames();
117  for (std::vector<std::string>::iterator iter = globalParameterNames.begin(); iter != globalParameterNames.end();
118  iter++) {
119  if (globalSet.existsAs<edm::ParameterSet>(*iter)) {
120  // This is a parameter set: check it
121  edm::ParameterSet subLocalSet = this->getParameterSet_((*iter), localSet);
122  if (subLocalSet.empty()) {
123  // No local subset exists: just insert it
124  localSet.copyFrom(globalSet, (*iter));
125  } else {
126  // Merge with local subset and replace
127  this->mergeParameters_(subLocalSet, globalSet.getParameter<edm::ParameterSet>(*iter));
128  localSet.addParameter<edm::ParameterSet>((*iter), subLocalSet);
129  }
130  } else {
131  // If (*iter) exists, (silently...) not replaced:
132  localSet.copyFrom(globalSet, (*iter));
133  }
134  }
135 
136  indent_ = indent_.substr(0, indent_.length() - 1);
137 }
138 
139 //__________________________________________________________________________________________________
140 // Propagates some parameters from upper level.
141 // Parameter sets are also propagated down (if name different from global name) or merged down.
143  const std::string& globalName,
144  edm::ParameterSet& subSet) const {
145  indent_ += " "; // For indented output!
146 
147  // Propagate some given parameters
148  std::vector<std::string> parameterNames = pSet.getParameterNames();
149  for (std::vector<std::string>::iterator iter = parameterNames.begin(); iter != parameterNames.end(); ++iter) {
150  if (theModifier.isPropagated(*iter)) { // like 'distribution', 'scale', etc.
151  LogDebug("PropagateParameters") << indent_ << " - adding parameter " << (*iter) << std::endl;
152  subSet.copyFrom(pSet, (*iter)); // If existing, is not replaced.
153  }
154  }
155 
156  // Propagate all tracked parameter sets
157  std::vector<std::string> pSetNames;
158  if (pSet.getParameterSetNames(pSetNames, true) > 0) {
159  for (std::vector<std::string>::const_iterator it = pSetNames.begin(); it != pSetNames.end(); ++it) {
160  const std::string rootName = this->rootName_(*it);
161  const std::string globalRoot(this->rootName_(globalName));
162  if (rootName.compare(0, rootName.length(), globalRoot) == 0) {
163  // Parameter for this level: skip
164  LogDebug("PropagateParameters") << indent_ << " - skipping PSet " << (*it) << " from global " << globalName
165  << std::endl;
166  } else if (this->isTopLevel_(*it)) {
167  // Top-level parameters should not be propagated
168  LogDebug("PropagateParameters") << indent_ << " - skipping top-level PSet " << (*it) << " global " << globalName
169  << std::endl;
170 
171  } else if (!this->possiblyPartOf(*it, globalRoot)) {
172  // (*it) is a part of the detector that does not fit to globalName
173  LogDebug("PropagateParameters") << indent_ << " - skipping PSet " << (*it) << " not fitting into global "
174  << globalName << std::endl;
175 
176  } else if (alignableObjectId_.stringToId(rootName) == align::invalid) {
177  // Parameter is not known!
178  throw cms::Exception("BadConfig") << "Unknown parameter set name " << rootName;
179  } else {
180  // Pass down any other: in order to merge PSets, create dummy PSet
181  // only containing this PSet and merge it recursively.
182  LogDebug("PropagateParameters") << indent_ << " - adding PSet " << (*it) << " global " << globalName
183  << std::endl;
184  edm::ParameterSet m_subSet;
185  m_subSet.addParameter<edm::ParameterSet>((*it), pSet.getParameter<edm::ParameterSet>(*it));
186  this->mergeParameters_(subSet, m_subSet);
187  }
188  }
189  }
190 
191  indent_ = indent_.substr(0, indent_.length() - 1);
192 }
193 
194 //__________________________________________________________________________________________________
195 // Get parameter set corresponding to given name.
196 // Return empty parameter set if does not exist.
198  const edm::ParameterSet& pSet) const {
200 
201  // Get list of parameter set names and retrieve requested one
202  std::vector<std::string> parameterSetNames;
203  if (this->hasParameter_(name, pSet)) {
204  result = pSet.getParameter<edm::ParameterSet>(name);
205  }
206 
207  return result;
208 }
209 
210 //__________________________________________________________________________________________________
211 // Get parameter set corresponding to given level name and number.
212 // Return empty parameter set if does not exist.
214  int iComponent,
215  const edm::ParameterSet& pSet) const {
217  unsigned int nFittingPsets = 0;
218 
219  // Get list of parameter set names and look for requested one
220  std::vector<std::string> pNames = pSet.getParameterNames();
221  for (std::vector<std::string>::iterator iter = pNames.begin(); iter != pNames.end(); ++iter) {
222  if (iter->find(levelName) != 0)
223  continue; // parameter not starting with levelName
224 
225  const std::string numberString(*iter, levelName.size());
226  // if (numberString.empty() || numberString == "s") { // "s" only left means we have e.g. 'TOBs'
227  if (numberString.empty()) { // check on "s" not needed, see below
228  continue; // nothing left in levelName to be iComponent...
229  }
230  // now look for numbers (separated by '_', tolerating '__' or ending with '_')
231  size_t lastPos = 0;
232  size_t pos = numberString.find_first_of('_', lastPos);
233  while (std::string::npos != pos || std::string::npos != lastPos) {
234  const std::string digit(numberString.substr(lastPos, pos - lastPos));
235 
236  bool isDigit = !digit.empty();
237  for (std::string::const_iterator dIt = digit.begin(); dIt != digit.end(); ++dIt) {
238  if (!isdigit(*dIt))
239  isDigit = false; // check all 'letters' to be a digit
240  }
241  if (!isDigit) {
242  if (lastPos != 0) { // do not throw if e.g. after 'TOB' ('Det') you find only 's' (Unit<n>)
243  throw cms::Exception("BadConfig")
244  << "[MisalignmentScenarioBuilder::getParameterSet_] "
245  << "Expect only numbers, separated by '_' after " << levelName << " in " << *iter << std::endl;
246  }
247  break;
248  }
249 
250  if (atoi(digit.c_str()) == iComponent) {
251  ++nFittingPsets;
252  LogDebug("getParameterSet_") << indent_ << "found " << *iter << " matching " << levelName << iComponent;
253  result = pSet.getParameter<edm::ParameterSet>(*iter);
254  break;
255  }
256  lastPos = numberString.find_first_not_of('_', pos);
257  pos = numberString.find_first_of('_', lastPos);
258  }
259  } // end loop on names of parameters in pSet
260 
261  if (nFittingPsets > 1) {
262  throw cms::Exception("BadConfig") << "[MisalignmentScenarioBuilder::getParameterSet_] "
263  << "Found " << nFittingPsets << " PSet for " << levelName << " " << iComponent
264  << "." << std::endl;
265  }
266 
267  return result;
268 }
269 
270 //__________________________________________________________________________________________________
272  // Get list of parameter set names and look for requested one
273  std::vector<std::string> names = pSet.getParameterNames();
274 
275  return (std::find(names.begin(), names.end(), name) != names.end());
276 }
277 
278 //__________________________________________________________________________________________________
279 // Print parameter set. If showPsets is 'false', do not print PSets
280 void MisalignmentScenarioBuilder::printParameters_(const edm::ParameterSet& pSet, const bool showPsets) const {
281  std::vector<std::string> parameterNames = pSet.getParameterNames();
282  for (std::vector<std::string>::iterator iter = parameterNames.begin(); iter != parameterNames.end(); ++iter) {
283  if (showPsets || !pSet.existsAs<edm::ParameterSet>(*iter)) {
284  // LogTrace("PrintParameters") << indent_ << " " << (*iter) << " = "
285  // << pSet.retrieve( *iter ).toString() << std::endl;
286  // From Bill Tannenbaum:
287  // You can use
288  // pset.getParameterAsString(aString).
289  // This function was added with the new tag.
290  // However, there is a possible complication if the parameter in question is
291  // itself a ParameterSet or a vector of ParameterSets. In the new format, a
292  // ParameterSet cannot be converted to a string until its ID is calculated,
293  // which happens when it is registered. So, if you get error messages about
294  // not being able to convert an unregistered ParameterSet to a string, you can
295  // do one of two things:
296  // A) You can use ParameterSet::dump() to print the parameter set, instead of
297  // getParameterAsString(). This does not require registering. I'm not sure of
298  // the exact format of the dump output (Rick wrote this, I think).
299  // OR
300  // B) You can use ParameterSet::registerIt() to register the parameter set
301  // before calling getParameterAsString().
302  //
303  // In either case, you can use existsAs to determine which parameters are
304  // themselves parameter sets or vectors of parameter sets.
305  //
306  // Note that in the new parameter set format, ParameterSet::toString() does not
307  // write out nested parameter sets by value. It writes them out by
308  // "reference", i.e it writes the ID.
309  }
310  }
311 }
312 
313 //__________________________________________________________________________________________________
314 bool MisalignmentScenarioBuilder::isTopLevel_(const std::string& parameterSetName) const {
315  // Get root name (strip last character[s])
316  std::string root = this->rootName_(parameterSetName);
317 
318  // tracker stuff treated in overwriting TrackerScenarioBuilder::isTopLevel_(..)
319  if (root == "DTSector")
320  return true;
321  else if (root == "CSCSector")
322  return true;
323  else if (root == "Muon")
324  return true;
325 
326  return false;
327 }
328 
329 //__________________________________________________________________________________________________
330 bool MisalignmentScenarioBuilder::possiblyPartOf(const std::string& /*sub*/, const std::string& /*large*/) const {
331  return true; // possibly overwrite in specific class
332 }
333 
334 //__________________________________________________________________________________________________
335 // Get root name of parameter set (e.g. return 'Rod' from 'Rods' or 'Rod1')
336 const std::string MisalignmentScenarioBuilder::rootName_(const std::string& parameterSetName) const {
337  std::string result{parameterSetName}; // Initialise to full string
338 
339  // Check if string ends with 's'
340  const auto lastChar = parameterSetName.length() - 1;
341  if (parameterSetName[lastChar] == 's') {
342  result = parameterSetName.substr(0, lastChar);
343  } else {
344  // Otherwise, look for numbers at the end
345  // (assumes that numbers at the end are not part of the name)
346  for (auto ichar = lastChar; ichar != 0; --ichar) {
347  if (!isdigit(parameterSetName[ichar])) {
348  result = parameterSetName.substr(0, ichar + 1);
349  break; // Stop at first non-digit
350  }
351  }
352  }
353 
354  LogDebug("PrintParameters") << "Name was " << parameterSetName << ", root is " << result;
355 
356  return result;
357 }
#define LogDebug(id)
T getParameter(std::string const &) const
align::StructureType stringToId(const char *) const
bool empty() const
Definition: ParameterSet.h:190
void decodeMovements_(const edm::ParameterSet &, const align::Alignables &)
Decode movements defined in given parameter set for given set of alignables.
virtual bool possiblyPartOf(const std::string &subStruct, const std::string &largeStruct) const
bool existsAs(std::string const &parameterName, bool trackiness=true) const
checks if a parameter exists as a given type
Definition: ParameterSet.h:160
void printParameters_(const edm::ParameterSet &pSet, const bool showPsets=false) const
Print all parameters and values for given set.
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
const std::string names[nVars_]
const std::string rootName_(const std::string &parameterSetName) const
Get root name of a parameter set (e.g. &#39;Rod&#39; in &#39;Rods&#39; or &#39;Rod1&#39;)
MisalignmentScenarioBuilder(AlignableObjectId::Geometry)
Constructor.
void copyFrom(ParameterSet const &from, std::string const &name)
void addParameter(std::string const &name, T const &value)
Definition: ParameterSet.h:124
void propagateParameters_(const edm::ParameterSet &pSet, const std::string &globalName, edm::ParameterSet &subSet) const
Propagate global parameters to sub-parameters.
std::vector< std::string > getParameterNames() const
virtual bool isTopLevel_(const std::string &parameterSetName) const
Check if given parameter is for a top-level structure.
const char * levelName(LogLevel)
Definition: fwLog.cc:32
AlignableModifier theModifier
Helper class for random movements.
const char * idToString(align::StructureType type) const
std::string indent_
Depth in hierarchy.
bool modify(Alignable *alignable, const edm::ParameterSet &pSet)
Modify given set of alignables according to parameters.
std::vector< Alignable * > Alignables
Definition: Utilities.h:31
void mergeParameters_(edm::ParameterSet &localSet, const edm::ParameterSet &globalSet) const
Merge two sets of parameters into one (the first argument)
bool isPropagated(const std::string &parameterName) const
Check if given parameter should be propagated.
int theModifierCounter
Counter for applied modification.
size_t getParameterSetNames(std::vector< std::string > &output, bool trackiness=true) const
const AlignableObjectId alignableObjectId_
bool hasParameter_(const std::string &name, const edm::ParameterSet &pSet) const
Check if given parameter exists in parameter set.
edm::ParameterSet getParameterSet_(const std::string &name, const edm::ParameterSet &pSet) const