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