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
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
|
/**
* \file PedeSteerer.cc
*
* \author : Gero Flucke
* date : October 2006
* $Revision: 1.42 $
* $Date: 2013/06/18 15:47:55 $
* (last update by $Author: jbehr $)
*/
#include "PedeSteerer.h"
#include "PedeSteererWeakModeConstraints.h"
#include "Alignment/MillePedeAlignmentAlgorithm/interface/PedeLabelerBase.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include "Alignment/CommonAlignment/interface/Alignable.h"
#include "Alignment/CommonAlignment/interface/Utilities.h"
#include "Alignment/CommonAlignmentAlgorithm/interface/AlignmentParameterStore.h"
#include "Alignment/CommonAlignmentAlgorithm/interface/AlignmentParameterSelector.h"
#include "Alignment/CommonAlignmentAlgorithm/interface/SelectionUserVariables.h"
#include "Alignment/CommonAlignmentParametrization/interface/AlignmentParametersFactory.h"
#include "Alignment/CommonAlignmentParametrization/interface/RigidBodyAlignmentParameters.h"
#include "Alignment/TrackerAlignment/interface/TrackerAlignableId.h"
// for 'type identification' as Alignable
#include "Alignment/TrackerAlignment/interface/AlignableTracker.h"
#include "Alignment/MuonAlignment/interface/AlignableMuon.h"
#include "Alignment/CommonAlignment/interface/AlignableExtras.h"
// GF doubts the need of these includes from include checker campaign:
#include <FWCore/Framework/interface/EventSetup.h>
#include <Geometry/CommonDetUnit/interface/GeomDet.h>
#include <Geometry/CommonDetUnit/interface/GeomDetType.h>
#include <DataFormats/GeometrySurface/interface/LocalError.h>
#include <Geometry/DTGeometry/interface/DTLayer.h>
// end of doubt
#include "DataFormats/GeometryVector/interface/GlobalPoint.h"
#include <atomic>
#include <fstream>
#include <sstream>
#include <algorithm>
// from ROOT
#include <TSystem.h>
#include <TMath.h>
#include <iostream>
//_________________________________________________________________________
PedeSteerer::PedeSteerer(AlignableTracker *aliTracker,
AlignableMuon *aliMuon,
AlignableExtras *aliExtras,
AlignmentParameterStore *store,
const PedeLabelerBase *labels,
const edm::ParameterSet &config,
const std::string &defaultDir,
bool noSteerFiles)
: myParameterStore(store),
myLabels(labels),
alignableObjectId_{AlignableObjectId::commonObjectIdProvider(aliTracker, aliMuon)},
myConfig(config),
myDirectory(myConfig.getUntrackedParameter<std::string>("fileDir")),
myRunDirectory(myConfig.getUntrackedParameter<std::string>("runDir")),
myNoSteerFiles(noSteerFiles),
myIsSteerFileDebug(myConfig.getUntrackedParameter<bool>("steerFileDebug")),
myParameterSign(myConfig.getUntrackedParameter<int>("parameterSign")),
theMinHieraConstrCoeff(myConfig.getParameter<double>("minHieraConstrCoeff")),
theMinHieraParPerConstr(myConfig.getParameter<unsigned int>("minHieraParPerConstr")),
theConstrPrecision(myConfig.getParameter<unsigned int>("constrPrecision")),
theCoordMaster(nullptr) {
if (myParameterSign != 1 && myParameterSign != -1) {
cms::Exception("BadConfig") << "Expect PedeSteerer.parameterSign = +/-1, "
<< "found " << myParameterSign << ".";
}
// Correct directory, needed before asking for fileName(..):
if (myDirectory.empty())
myDirectory = defaultDir;
if (!myDirectory.empty() && myDirectory.find_last_of('/') != myDirectory.size() - 1) {
myDirectory += '/'; // directory may need '/'
}
if (myRunDirectory.empty())
myRunDirectory = defaultDir;
if (!myRunDirectory.empty() && myRunDirectory.find_last_of('/') != myRunDirectory.size() - 1) {
myRunDirectory += '/'; // directory may need '/'
myDirectory = myRunDirectory;
}
const auto &alis = myParameterStore->alignables();
if (!this->checkParameterChoices(alis)) {
} // anyway thrown exception
// Coordinate system selection and correction before everything
theCoordDefiners = this->selectCoordinateAlis(alis);
if (!theCoordDefiners.empty()) { // Create steering with constraints to define coordinate system:
// OK, some hacks:
// - we want a composite with global coordinates where tracker and muon are components
// (to call RigidBodyAl.Param.->globalParameters() in correctToReferenceSystem(..))
// - so we create a AlignableComposite and add tracker and muon
// - but the addComponent(..) method is so cute that it calculates position from
// daughters' deepComponents()
// - so we want to move it back to (0,0,0), but ali->move(..) would move daughters as well
// => move only the surface back
// - this master object does not have a label for its parameters
// => some warnings if debug output selected in pedeSteer files
// - we must not delete our new master (little mem. leak...) since that would delete
// the daughters as well!
if (aliTracker) {
theCoordMaster = new AlignableComposite(aliTracker->id(), align::invalid);
theCoordMaster->addComponent(aliTracker);
} else if (aliMuon) {
theCoordMaster = new AlignableComposite(aliMuon->id(), align::invalid);
} else {
throw cms::Exception("BadConfig") << "[PedeSteerer]"
<< "Cannot define global coordinate system "
<< "with neither tracker nor muon!";
}
if (aliMuon)
theCoordMaster->addComponent(aliMuon); // tracker is already added if existing
if (aliExtras) { // tracker and/or muon are already added if existing
align::Alignables allExtras = aliExtras->components();
for (const auto &it : allExtras)
theCoordMaster->addComponent(it);
}
theCoordMaster->recenterSurface();
if (this->isCorrectToRefSystem(theCoordDefiners)) { // defined by 's' (MC): 'correct' misalignment
this->correctToReferenceSystem(); // really before 'defineCoordinates'?
}
}
}
//___________________________________________________________________________
PedeSteerer::~PedeSteerer() {
// delete theCoordMaster; NO, see above
}
//_________________________________________________________________________
bool PedeSteerer::isNoHiera(const Alignable *ali) const {
return (myNoHieraCollection.find(ali) != myNoHieraCollection.end());
}
//_________________________________________________________________________
double PedeSteerer::cmsToPedeFactor(unsigned int parNum) const {
return 1.; // mmh, otherwise would need to FIXME hierarchyConstraint...
switch (parNum) {
case RigidBodyAlignmentParameters::dx:
case RigidBodyAlignmentParameters::dy:
return 1000.; // cm to mum *1/10 to get smaller values
case RigidBodyAlignmentParameters::dz:
return 2500.; // cm to mum *1/4
case RigidBodyAlignmentParameters::dalpha:
case RigidBodyAlignmentParameters::dbeta:
return 1000.; // rad to mrad (no first guess for sensitivity yet)
case RigidBodyAlignmentParameters::dgamma:
return 10000.; // rad to mrad *10 to get larger values
default:
return 1.;
}
}
//_________________________________________________________________________
unsigned int PedeSteerer::buildNoHierarchyCollection(const align::Alignables &alis) {
myNoHieraCollection.clear(); // just in case of re-use...
for (const auto &iAli : alis) {
AlignmentParameters *params = iAli->alignmentParameters();
SelectionUserVariables *selVar = dynamic_cast<SelectionUserVariables *>(params->userVariables());
if (!selVar)
continue;
// Now check whether taking out of hierarchy is selected - must be consistent!
unsigned int numNoHieraPar = 0;
unsigned int numHieraPar = 0;
for (unsigned int iParam = 0; static_cast<int>(iParam) < params->size(); ++iParam) {
const char selector = selVar->fullSelection()[iParam];
if (selector == 'C' || selector == 'F' || selector == 'H') {
++numNoHieraPar;
} else if (selector == 'c' || selector == 'f' || selector == '1' || selector == 'r' || selector == 's') {
++numHieraPar;
} // else ... accept '0' as undetermined
}
if (numNoHieraPar) { // Selected to be taken out.
if (numHieraPar) { // Inconsistent: Some parameters still in hierarchy ==> exception!
throw cms::Exception("BadConfig")
<< "[PedeSteerer::buildNoHierarchyCollection] All active parameters of alignables to be "
<< " taken out of the hierarchy must be marked with capital letters 'C', 'F' or 'H'!";
}
bool isInHiera = false; // Check whether Alignable is really part of hierarchy:
auto mother = iAli;
while ((mother = mother->mother())) {
if (mother->alignmentParameters())
isInHiera = true; // could 'break;', but loop is short
}
// Complain, but keep collection short if not in hierarchy:
if (isInHiera)
myNoHieraCollection.insert(iAli);
else
edm::LogWarning("Alignment") << "@SUB=PedeSteerer::buildNoHierarchyCollection"
<< "Alignable not in hierarchy, no need to remove it!";
}
} // end loop on alignables
return myNoHieraCollection.size();
}
//_________________________________________________________________________
bool PedeSteerer::checkParameterChoices(const align::Alignables &alis) const {
for (const auto &iAli : alis) {
AlignmentParameters *paras = iAli->alignmentParameters();
SelectionUserVariables *selVar = dynamic_cast<SelectionUserVariables *>(paras->userVariables());
if (!selVar)
continue;
for (unsigned int iParam = 0; static_cast<int>(iParam) < paras->size(); ++iParam) {
const char sel = selVar->fullSelection()[iParam];
if (sel != 'f' && sel != 'F' && sel != 'c' && sel != 'C' && sel != '0' && sel != '1' && sel != 'H' &&
sel != 'r' && sel != 's') {
throw cms::Exception("BadConfig")
<< "[PedeSteerer::unknownParameterChoices] "
<< "Unexpected parameter selector '" << sel
<< "', use \n'f/F' (fix),\n'c/C' (fix at correct pos.),\n'1/H' (free),\n"
<< "'r/s' (free, but defining reference system, trying to correct misalignment if 's')"
<< " or \n'0' (ignore).\n"
<< "Capital letters mean that the Alignable is taken out of a possible hierarchy,\n"
<< "but must be used consistently for all its parameters.";
return false; // unreached
}
}
}
return true;
}
//_________________________________________________________________________
std::pair<unsigned int, unsigned int> PedeSteerer::fixParameters(const align::Alignables &alis,
const std::string &fileName) {
// return number of parameters fixed at 0. and fixed at original position
std::pair<unsigned int, unsigned int> numFixNumFixCor(0, 0);
std::ofstream *filePtr = nullptr;
for (const auto &iAli : alis) {
AlignmentParameters *params = iAli->alignmentParameters();
SelectionUserVariables *selVar = dynamic_cast<SelectionUserVariables *>(params->userVariables());
if (!selVar)
continue;
for (unsigned int iParam = 0; static_cast<int>(iParam) < params->size(); ++iParam) {
const unsigned int nInstances = myLabels->numberOfParameterInstances(iAli, iParam);
for (unsigned int iInstance = 0; iInstance < nInstances; ++iInstance) {
int whichFix = this->fixParameter(iAli, iInstance, iParam, selVar->fullSelection()[iParam], filePtr, fileName);
if (whichFix == 1) {
++(numFixNumFixCor.first);
} else if (whichFix == -1) {
++(numFixNumFixCor.second);
}
}
}
}
delete filePtr; // automatically flushes, no problem if NULL ptr.
return numFixNumFixCor;
}
//_________________________________________________________________________
int PedeSteerer::fixParameter(Alignable *ali,
unsigned int iInstance,
unsigned int iParam,
char selector,
std::ofstream *&filePtr,
const std::string &fileName) {
int result = 0;
float fixAt = 0.;
if (selector == 'c' || selector == 'C') {
if (ali->alignmentParameters()->type() != AlignmentParametersFactory::kRigidBody) {
throw cms::Exception("BadConfig")
<< "PedeSteerer::fixParameter: correction (c/C) possible only for RigidBodyParameters";
}
fixAt = -this->parameterSign() * RigidBodyAlignmentParameters(ali, true).parameters()[iParam];
result = -1;
} else if (selector == 'f' || selector == 'F') {
result = 1;
}
if (result) {
if (!filePtr) {
filePtr = this->createSteerFile(fileName, true);
(*filePtr) << "Parameter\n";
}
std::ofstream &file = *filePtr;
const unsigned int aliLabel = myLabels->alignableLabelFromParamAndInstance(ali, iParam, iInstance);
file << myLabels->parameterLabel(aliLabel, iParam) << " " << fixAt * this->cmsToPedeFactor(iParam) << " -1.0";
if (myIsSteerFileDebug) { // debug
const GlobalPoint position(ali->globalPosition());
file << " * id " << ali->id() << ", eta " << position.eta() << ", z " << position.z() << ", r "
<< position.perp() << ", phi " << position.phi();
}
file << "\n";
}
return result;
}
//_________________________________________________________________________
align::Alignables PedeSteerer::selectCoordinateAlis(const align::Alignables &alis) const {
align::Alignables coordAlis;
for (const auto &iAli : alis) {
AlignmentParameters *params = iAli->alignmentParameters();
SelectionUserVariables *selVar = dynamic_cast<SelectionUserVariables *>(params->userVariables());
if (!selVar)
continue;
unsigned int refParam = 0;
unsigned int nonRefParam = 0;
for (unsigned int iParam = 0; static_cast<int>(iParam) < params->size(); ++iParam) {
const char selector = selVar->fullSelection()[iParam];
if (selector == 'r' || selector == 's') {
++refParam;
} else if (selector != '0' && selector != 'f') { // allow also 'c'?
++nonRefParam;
}
}
// Check whether some 'r/s' selection string. If yes and selection makes sense, add to result:
if (refParam) {
if (nonRefParam) {
throw cms::Exception("BadConfig")
<< "[PedeSteerer::selectCoordinateAlis] All active parameters of alignables defining "
<< "the coordinate system must be marked with 'r/s' (or fixed, 'f')!";
} else {
auto mother = iAli;
while ((mother = mother->mother())) {
if (mother->alignmentParameters()) {
throw cms::Exception("BadConfig") << "[PedeSteerer::selectCoordinateAlis] "
<< "Alignables defining the coordinate system must "
<< "be highest level!";
}
}
coordAlis.push_back(iAli);
}
}
} // end loop on alignables
return coordAlis;
}
//_________________________________________________________________________
void PedeSteerer::defineCoordinates(const align::Alignables &alis, Alignable *aliMaster, const std::string &fileName) {
std::ofstream *filePtr = this->createSteerFile(fileName, true);
(*filePtr) << "* Constraints to define coordinate system:\n";
if (!aliMaster || aliMaster->alignmentParameters()) {
throw cms::Exception("BadConfig") << "[PedeSteerer::defineCoordinates] "
<< "No master alignable or it has parameters!";
}
if (myIsSteerFileDebug) { // See constructor comments about hack:
edm::LogError("Alignment") << "@SUB=PedeSteerer::defineCoordinates"
<< "Ignore following LogicErrors from PedeLabeler.";
}
AlignmentParameters *par = new RigidBodyAlignmentParameters(aliMaster, false);
aliMaster->setAlignmentParameters(par); // hierarchyConstraint needs parameters
this->hierarchyConstraint(aliMaster, alis, *filePtr);
aliMaster->setAlignmentParameters(nullptr); // erase dummy parameters
delete filePtr; // automatically flushes, no problem if NULL ptr.
}
//_________________________________________________________________________
bool PedeSteerer::isCorrectToRefSystem(const align::Alignables &coordDefiners) const {
bool doCorrect = false;
bool doNotCorrect = false;
for (const auto &it : coordDefiners) {
SelectionUserVariables *selVar =
(it->alignmentParameters() ? dynamic_cast<SelectionUserVariables *>(it->alignmentParameters()->userVariables())
: nullptr);
if (!selVar)
continue; // is an error!?
for (unsigned int i = 0; i < selVar->fullSelection().size(); ++i) {
if (selVar->fullSelection()[i] == 'r')
doNotCorrect = true;
else if (selVar->fullSelection()[i] == 's')
doCorrect = true;
}
}
if (doCorrect && doNotCorrect) {
throw cms::Exception("BadConfig")
<< "[PedeSteerer::doCorrectToRefSystem]: Parameter selection 's' and 'r' must not coexist!";
}
return doCorrect;
}
//_________________________________________________________________________
void PedeSteerer::correctToReferenceSystem() {
typedef RigidBodyAlignmentParameters RbPars;
if (!theCoordMaster || theCoordDefiners.empty())
return; // nothing was defined
align::Alignables definerDets; // or ...DetUnits
for (const auto &it :
theCoordDefiners) { // find lowest level objects of alignables that define the coordinate system
const auto &comp = it->deepComponents();
definerDets.insert(definerDets.end(), comp.begin(), comp.end());
}
for (unsigned int iLoop = 0;; ++iLoop) { // iterate: shifts and rotations are not independent
AlgebraicVector meanPars(RbPars::N_PARAM);
for (const auto &it : definerDets) { // sum up mean displacements/misrotations:
meanPars += RbPars(it, true).globalParameters(); // requires theCoordMaster has global frame
}
meanPars /= definerDets.size();
const align::Scalar squareSum = meanPars.normsq();
if (squareSum < 1.e-20)
break; // sqrt(1.e-20)=1.e-10: close enough to stop iterating
if (iLoop == 0) {
edm::LogInfo("Alignment") << "@SUB=PedeSteerer::correctToReferenceSystem"
<< "Loop " << iLoop << " "
<< "Mean misalignment of dets of defined coordinate system"
<< (squareSum < 1.e-20 ? ":" : " (will be iteratively corrected to < 1.e-10):")
<< meanPars;
}
if (iLoop >= 5) { // 3 iterations should be safe, use 5 for 'more' safety...
edm::LogError("Alignment") << "@SUB=PedeSteerer::correctToReferenceSystem"
<< "No convergence in " << iLoop << " iterations, "
<< "remaining misalignment: " << meanPars;
break;
}
const GlobalVector globalShift(meanPars[RbPars::dx], meanPars[RbPars::dy], meanPars[RbPars::dz]);
theCoordMaster->move(-globalShift); // sign to revert
align::EulerAngles globalAngles(3);
globalAngles[0] = meanPars[RbPars::dalpha];
globalAngles[1] = meanPars[RbPars::dbeta];
globalAngles[2] = meanPars[RbPars::dgamma];
theCoordMaster->rotateInGlobalFrame(align::toMatrix(-globalAngles)); // sign to revert
}
}
//_________________________________________________________________________
unsigned int PedeSteerer::hierarchyConstraints(const align::Alignables &alis, const std::string &fileName) {
std::ofstream *filePtr = nullptr;
unsigned int nConstraints = 0;
align::Alignables aliDaughts;
for (const auto &iA : alis) {
aliDaughts.clear();
if (!(iA->firstCompsWithParams(aliDaughts))) {
edm::LogWarning("Alignment") << "@SUB=PedeSteerer::hierarchyConstraints"
<< "Some but not all daughters of "
<< alignableObjectId_.idToString(iA->alignableObjectId()) << " with params!";
}
// edm::LogInfo("Alignment") << "@SUB=PedeSteerer::hierarchyConstraints"
// << aliDaughts.size() << " ali param components";
if (aliDaughts.empty())
continue;
// edm::LogInfo("Alignment") << "@SUB=PedeSteerer::hierarchyConstraints"
// << aliDaughts.size() << " alignable components ("
// << iA->size() << " in total) for "
// << aliId.alignableTypeName(iA)
// << ", layer " << aliId.typeAndLayerFromAlignable(iA).second
// << ", position " << (iA)->globalPosition()
// << ", r = " << (iA)->globalPosition().perp();
if (!filePtr)
filePtr = this->createSteerFile(fileName, true);
++nConstraints;
this->hierarchyConstraint(iA, aliDaughts, *filePtr);
}
delete filePtr; // automatically flushes, no problem if NULL ptr.
return nConstraints;
}
//_________________________________________________________________________
void PedeSteerer::hierarchyConstraint(const Alignable *ali,
const align::Alignables &components,
std::ofstream &file) const {
typedef AlignmentParameterStore::ParameterId ParameterId;
std::vector<std::vector<ParameterId> > paramIdsVec;
std::vector<std::vector<double> > factorsVec;
const bool allConstr = false; // true; // make configurable?
static std::atomic<bool> allConstrWarning{false};
bool expected{false};
if (allConstr && allConstrWarning.compare_exchange_strong(expected, true)) {
edm::LogWarning("Alignment") << "@SUB=PedeSteerer::hierarchyConstraint"
<< "changed to use all 6 constraints";
}
if (!myParameterStore->hierarchyConstraints(
ali, components, paramIdsVec, factorsVec, allConstr, theMinHieraConstrCoeff)) {
edm::LogWarning("Alignment") << "@SUB=PedeSteerer::hierarchyConstraint"
<< "Problems from store.";
}
for (unsigned int iConstr = 0; iConstr < paramIdsVec.size(); ++iConstr) {
std::ostringstream aConstr;
const std::vector<ParameterId> &parIds = paramIdsVec[iConstr];
const std::vector<double> &factors = factorsVec[iConstr];
unsigned int nParPerConstr = 0; // keep track of used factor/parId pair
// parIds.size() == factors.size() granted by myParameterStore->hierarchyConstraints
for (unsigned int iParam = 0; iParam < parIds.size(); ++iParam) {
Alignable *aliSubComp = parIds[iParam].first;
const unsigned int compParNum = parIds[iParam].second;
if (this->isNoHiera(aliSubComp)) {
if (myIsSteerFileDebug)
aConstr << "* Taken out of hierarchy: ";
continue;
}
const unsigned int aliLabel = myLabels->alignableLabel(aliSubComp);
const unsigned int paramLabel = myLabels->parameterLabel(aliLabel, compParNum);
// FIXME: multiply by cmsToPedeFactor(subcomponent)/cmsToPedeFactor(mother) (or vice a versa?)
if (theConstrPrecision > 0)
aConstr << paramLabel << " " << std::setprecision(theConstrPrecision) << factors[iParam];
else
aConstr << paramLabel << " " << factors[iParam];
if (myIsSteerFileDebug) { // debug
aConstr << " ! for param " << compParNum << " of a "
<< alignableObjectId_.idToString(aliSubComp->alignableObjectId()) << " at "
<< aliSubComp->globalPosition() << ", r=" << aliSubComp->globalPosition().perp();
}
aConstr << "\n";
++nParPerConstr; // OK, we used one.
} // end loop on params
//
if (nParPerConstr && nParPerConstr >= theMinHieraParPerConstr) { // Enough to make sense?
if (myIsSteerFileDebug) { //debug
file << "\n* Nr. " << iConstr << " of a '" << alignableObjectId_.idToString(ali->alignableObjectId())
<< "' (label " << myLabels->alignableLabel(const_cast<Alignable *>(ali)) // ugly cast: FIXME!
<< "), position " << ali->globalPosition() << ", r = " << ali->globalPosition().perp();
}
file << "\nConstraint 0.\n" << aConstr.str(); // in future 'Wconstraint'?
} else if (nParPerConstr > 0) { // no warning for trivial case...
edm::LogWarning("Alignment") << "@SUB=PedeSteerer::hierarchyConstraint"
<< "Skip constraint on " << nParPerConstr << " parameter(s):\n"
<< aConstr.str();
}
} // end loop on constraints
}
//_________________________________________________________________________
unsigned int PedeSteerer::presigmas(const std::vector<edm::ParameterSet> &cffPresi,
const std::string &fileName,
const align::Alignables &alis,
AlignableTracker *aliTracker,
AlignableMuon *aliMuon,
AlignableExtras *aliExtras) {
// We loop on given PSet's, each containing a parameter selection and the presigma value
// The resulting presigmas are stored in a map with Alignable* as key.
// This map, 'fileName' and 'alis' are passed further to create the steering file.
AlignmentParameterSelector selector(aliTracker, aliMuon, aliExtras);
AlignablePresigmasMap aliPresiMap; // map to store alis with presigmas of their parameters
for (std::vector<edm::ParameterSet>::const_iterator iSet = cffPresi.begin(), iE = cffPresi.end(); iSet != iE;
++iSet) { // loop on individual PSets defining ali-params with their presigma
selector.clear();
selector.addSelections((*iSet).getParameter<edm::ParameterSet>("Selector"));
const auto &alis = selector.selectedAlignables();
const std::vector<std::vector<char> > &sels = selector.selectedParameters();
const float presigma = (*iSet).getParameter<double>("presigma");
if (presigma <= 0.) { // given presigma > 0., 0. later used if not (yet) chosen for parameter
throw cms::Exception("BadConfig") << "[PedeSteerer::presigmas]: Pre-sigma must be > 0., but is " << presigma
<< ".";
}
// now loop on alis of present selection
for (unsigned int iAli = 0; iAli < alis.size(); ++iAli) {
std::vector<float> &presigmas = aliPresiMap[alis[iAli]]; // existing or empty, so ensure length:
if (presigmas.size() < sels[iAli].size())
presigmas.resize(sels[iAli].size(), 0.);
for (unsigned int iParam = 0; iParam < sels[iAli].size(); ++iParam) { // loop on parameters
if (sels[iAli][iParam] != '0') { // all but '0' means to apply the chosen presigma
if (presigmas[iParam] != 0.) { // reset forbidden (would make it order dependent!)
throw cms::Exception("BadConfig")
<< "[PedeSteerer::presigmas]: Try to set pre-sigma " << presigma << ", but already "
<< "set " << presigmas[iParam] << " (for a "
<< alignableObjectId_.idToString(alis[iAli]->alignableObjectId()) << ").";
}
presigmas[iParam] = presigma;
} // end if selected for presigma
} // end loop on params
} // end loop on alignables for given selection and presigma
} // end loop on PSets
if (aliPresiMap.empty())
return 0;
else
return this->presigmasFile(fileName, alis, aliPresiMap);
}
//_________________________________________________________________________
unsigned int PedeSteerer::presigmasFile(const std::string &fileName,
const align::Alignables &alis,
const AlignablePresigmasMap &aliPresiMap) {
// Check if 'alis' are in aliPresiMap,
// if yes apply presigma - but NOT if parameter is fixed!
std::ofstream *filePtr = nullptr;
unsigned int nPresiParam = 0;
for (const auto &iAli : alis) {
// Any presigma chosen for alignable?
AlignablePresigmasMap::const_iterator presigmasIt = aliPresiMap.find(iAli);
if (presigmasIt == aliPresiMap.end())
continue; // no presigma chosen for alignable
// Why does the following not work? It does with CMSSW_1_3_X on SLC3...
// const AlignablePresigmasMap::data_type &presigmas = presigmasIt->second;
const std::vector<float> &presigmas = presigmasIt->second; // I want to hide float or double...
for (unsigned int iParam = 0; iParam < presigmas.size(); ++iParam) {
// Now check whether a presigma value > 0. chosen:
if (presigmas[iParam] <= 0.)
continue; // must be positive, '<' checked above
// Do not apply presigma to inactive or fixed values.
if (!(iAli->alignmentParameters()->selector()[iParam]))
continue;
SelectionUserVariables *selVar =
dynamic_cast<SelectionUserVariables *>(iAli->alignmentParameters()->userVariables());
const char selChar = (selVar ? selVar->fullSelection()[iParam] : '1');
if (selChar == 'f' || selChar == 'F' || selChar == 'c' || selChar == 'C')
continue;
// Finally create and write steering file:
if (!filePtr) {
filePtr = this->createSteerFile(fileName, true);
(*filePtr) << "* Presigma values for active parameters: \nParameter\n";
}
const unsigned int aliLabel = myLabels->alignableLabel(iAli);
(*filePtr) << myLabels->parameterLabel(aliLabel, iParam) << " 0. "
<< presigmas[iParam] * fabs(this->cmsToPedeFactor(iParam));
if (myIsSteerFileDebug) {
(*filePtr) << " ! for a " << alignableObjectId_.idToString((iAli)->alignableObjectId());
}
(*filePtr) << '\n';
++nPresiParam;
} // end loop on parameters for alignables with chosen presigmas
} // end loop on alignables
delete filePtr; // close properly file
return nPresiParam;
}
//_________________________________________________________________________
std::ofstream *PedeSteerer::createSteerFile(const std::string &name, bool addToList) {
const std::string realName(myNoSteerFiles ? "/dev/null" : name.c_str());
std::ofstream *result = new std::ofstream(realName.c_str(), std::ios::out);
if (!result || !result->is_open()) {
delete result; // needed before exception in case just open failed
throw cms::Exception("FileOpenProblem") << "[PedeSteerer::createSteerFile]"
<< "Could not open " << realName << " as output file.";
} else if (addToList) {
mySteeringFiles.push_back(realName); // keep track
}
return result;
}
//_________________________________________________________________________
std::string PedeSteerer::fileName(const std::string &addendum) const {
std::string name(myDirectory);
name += myConfig.getParameter<std::string>("steerFile");
name += addendum;
name += ".txt";
return name;
}
//___________________________________________________________________________
void PedeSteerer::buildSubSteer(AlignableTracker *aliTracker, AlignableMuon *aliMuon, AlignableExtras *aliExtras) {
const auto &alis = myParameterStore->alignables();
if (theCoordMaster && !theCoordDefiners.empty()) {
const std::string nameCoordFile(this->fileName("Coord"));
this->defineCoordinates(theCoordDefiners, theCoordMaster, nameCoordFile);
edm::LogInfo("Alignment") << "@SUB=PedeSteerer::buildSubSteer" << theCoordDefiners.size()
<< " highest level objects define the "
<< "coordinate system, steering file " << nameCoordFile << ".";
}
const std::string nameFixFile(this->fileName("FixPara"));
const std::pair<unsigned int, unsigned int> nFixFixCor(this->fixParameters(alis, nameFixFile));
if (nFixFixCor.first != 0 || nFixFixCor.second != 0) {
edm::LogInfo("Alignment") << "@SUB=PedeSteerer::buildSubSteer" << nFixFixCor.first << " parameters fixed at 0. and "
<< nFixFixCor.second << " at 'original' position, "
<< "steering file " << nameFixFile << ".";
}
if (this->buildNoHierarchyCollection(alis)) { // before hierarchyConstraints(..)
edm::LogInfo("Alignment") << "@SUB=PedeSteerer::buildSubSteer" << myNoHieraCollection.size()
<< " alignables taken out of hierarchy.";
}
const std::string nameHierarchyFile(this->fileName("Hierarchy"));
unsigned int nConstraint = this->hierarchyConstraints(alis, nameHierarchyFile);
if (nConstraint) {
edm::LogInfo("Alignment") << "@SUB=PedeSteerer::buildSubSteer"
<< "Hierarchy constraints for " << nConstraint << " alignables, "
<< "steering file " << nameHierarchyFile << ".";
}
//construct the systematic geometry deformations
if (!(myConfig.getParameter<std::vector<edm::ParameterSet> >("constraints")).empty()) {
PedeSteererWeakModeConstraints GeometryConstraints(
aliTracker,
myLabels,
myConfig.getParameter<std::vector<edm::ParameterSet> >("constraints"),
myConfig.getParameter<std::string>("steerFile"));
//prepare the output files
//Get the data structure in which the configuration data are stored.
//The relation between the ostream* and the corresponding file name needs to be filled
auto &ConstraintsConfigContainer = GeometryConstraints.getConfigData();
//loop over all configured constraints
for (auto &it : ConstraintsConfigContainer) {
//each level has its own constraint which means the output is stored in a separate file
for (const auto &ilevelsFilename : it.levelsFilenames_) {
it.mapFileName_.insert(
std::make_pair(ilevelsFilename.second, this->createSteerFile(ilevelsFilename.second, true)));
}
}
unsigned int nGeometryConstraint = GeometryConstraints.constructConstraints(alis);
if (nGeometryConstraint) {
edm::LogInfo("Alignment") << "@SUB=PedeSteerer::buildSubSteer"
<< "Geometry constraints for " << nGeometryConstraint << " alignables.";
}
}
const std::string namePresigmaFile(this->fileName("Presigma"));
unsigned int nPresigma = this->presigmas(myConfig.getParameter<std::vector<edm::ParameterSet> >("Presigmas"),
namePresigmaFile,
alis,
aliTracker,
aliMuon,
aliExtras);
if (nPresigma) {
edm::LogInfo("Alignment") << "@SUB=PedeSteerer::buildSubSteer"
<< "Presigma values set for " << nPresigma << " parameters, "
<< "steering file " << namePresigmaFile << ".";
}
// Delete all SelectionUserVariables now? They will anyway be overwritten by MillePedeVariables...
}
//_________________________________________________________________________
std::string PedeSteerer::buildMasterSteer(const std::vector<std::string> &binaryFiles) {
const std::string nameMasterSteer(this->fileName("Master"));
std::ofstream *mainSteerPtr = this->createSteerFile(nameMasterSteer, false);
if (!mainSteerPtr)
return "";
// add external steering files, if any
std::vector<std::string> addfiles = myConfig.getParameter<std::vector<std::string> >("additionalSteerFiles");
mySteeringFiles.insert(mySteeringFiles.end(), addfiles.begin(), addfiles.end());
// add steering files to master steering file
std::ofstream &mainSteerRef = *mainSteerPtr;
for (unsigned int iFile = 0; iFile < mySteeringFiles.size(); ++iFile) {
mainSteerRef << mySteeringFiles[iFile] << "\n";
}
// add binary files to master steering file
mainSteerRef << "\nCfiles\n";
for (unsigned int iFile = 0; iFile < binaryFiles.size(); ++iFile) {
if (myRunDirectory.empty())
mainSteerRef << binaryFiles[iFile] << "\n";
else
mainSteerRef << "../" + binaryFiles[iFile] << "\n";
}
// add method
mainSteerRef << "\nmethod " << myConfig.getParameter<std::string>("method") << "\n";
// add further options
const std::vector<std::string> opt(myConfig.getParameter<std::vector<std::string> >("options"));
mainSteerRef << "\n* Outlier treatment and other options \n";
for (unsigned int i = 0; i < opt.size(); ++i) {
mainSteerRef << opt[i] << "\n";
}
delete mainSteerPtr; // close (and flush) again
return nameMasterSteer;
}
//_________________________________________________________________________
int PedeSteerer::runPede(const std::string &masterSteer) const {
if (masterSteer.empty()) {
edm::LogError("Alignment") << "@SUB=PedeSteerer::runPede"
<< "Empty master steer file, stop";
return 0; //false;
}
// Change pede command if running in different directory
std::string command;
if (myRunDirectory.empty()) {
command = myConfig.getUntrackedParameter<std::string>("pedeCommand");
(command += " ") += masterSteer;
} else {
command = "(cd " + myRunDirectory + " && ";
command += myConfig.getUntrackedParameter<std::string>("pedeCommand");
(command += " ") += "../" + masterSteer;
command += ")";
}
const std::string dump(myConfig.getUntrackedParameter<std::string>("pedeDump"));
if (!dump.empty()) {
command += " > ";
(command += myDirectory) += dump;
}
edm::LogInfo("Alignment") << "@SUB=PedeSteerer::runPede"
<< "Start running " << command;
// FIXME: Recommended interface to system commands?
int shellReturn = gSystem->Exec(command.c_str());
edm::LogInfo("Alignment") << "@SUB=PedeSteerer::runPede"
<< "Command returns " << shellReturn;
return shellReturn;
}
|