CMS 3D CMS Logo

MillePedeAlignmentAlgorithm.cc
Go to the documentation of this file.
1 
12 
17 
19 
24 #include "Alignment/MillePedeAlignmentAlgorithm/src/Mille.h" // 'unpublished' interface located in src
29 
32 
36 
40 
41 // includes to make known that they inherit from Alignable:
45 
50 
56 
62 
65 
67 
68 #include <fstream>
69 #include <sstream>
70 #include <algorithm>
71 #include <sys/stat.h>
72 
73 #include <TMath.h>
77 
78 // Includes for PXB survey
85 
87 
88 using namespace gbl;
89 
90 
91 // Constructor ----------------------------------------------------------------
92 //____________________________________________________
95  theConfig(cfg),
96  theMode(this->decodeMode(theConfig.getUntrackedParameter<std::string>("mode"))),
97  theDir(theConfig.getUntrackedParameter<std::string>("fileDir")),
98  theAlignmentParameterStore(nullptr),
99  theAlignables(),
100  theMinNumHits(cfg.getParameter<unsigned int>("minNumHits")),
101  theMaximalCor2D(cfg.getParameter<double>("max2Dcorrelation")),
102  firstIOV_(cfg.getUntrackedParameter<AlignmentAlgorithmBase::RunNumber>("firstIOV")),
103  ignoreFirstIOVCheck_(cfg.getUntrackedParameter<bool>("ignoreFirstIOVCheck")),
104  enableAlignableUpdates_(cfg.getUntrackedParameter<bool>("enableAlignableUpdates")),
105  theLastWrittenIov(0),
106  theGblDoubleBinary(cfg.getParameter<bool>("doubleBinary")),
107  runAtPCL_(cfg.getParameter<bool>("runAtPCL")),
108  ignoreHitsWithoutGlobalDerivatives_(cfg.getParameter<bool>("ignoreHitsWithoutGlobalDerivatives")),
109  skipGlobalPositionRcdCheck_(cfg.getParameter<bool>("skipGlobalPositionRcdCheck")),
110  uniqueRunRanges_
111  (align::makeUniqueRunRanges(cfg.getUntrackedParameter<edm::VParameterSet>("RunRangeSelection"),
112  cond::timeTypeSpecs[cond::runnumber].beginValue)),
113  enforceSingleIOVInput_(!(enableAlignableUpdates_ && areIOVsSpecified())),
114  lastProcessedRun_(cond::timeTypeSpecs[cond::runnumber].beginValue)
115 {
116  if (!theDir.empty() && theDir.find_last_of('/') != theDir.size()-1) theDir += '/';// may need '/'
117  edm::LogInfo("Alignment") << "@SUB=MillePedeAlignmentAlgorithm" << "Start in mode '"
119  << "' with output directory '" << theDir << "'.";
120  if (this->isMode(myMilleBit)) {
121  theMille = std::make_unique<Mille>((theDir + theConfig.getParameter<std::string>("binaryFile")).c_str());// add ', false);' for text output);
122  // use same file for GBL
123  theBinary = std::make_unique<MilleBinary>((theDir + theConfig.getParameter<std::string>("binaryFile")).c_str(), theGblDoubleBinary);
124  }
125 }
126 
127 // Destructor ----------------------------------------------------------------
128 //____________________________________________________
130 {
131 }
132 
133 // Call at beginning of job ---------------------------------------------------
134 //____________________________________________________
138 {
139  if (muon) {
140  edm::LogWarning("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::initialize"
141  << "Running with AlignabeMuon not yet tested.";
142  }
143 
147  const auto& iov_alignments =
148  setup.get<TrackerAlignmentRcd>().validityInterval();
149  const auto& iov_surfaces =
150  setup.get<TrackerSurfaceDeformationRcd>().validityInterval();
151  const auto& iov_errors =
152  setup.get<TrackerAlignmentErrorExtendedRcd>().validityInterval();
153 
154  std::ostringstream message;
155  bool throwException{false};
156  if (iov_alignments.first().eventID().run() != MIN_VAL ||
157  iov_alignments.last().eventID().run() != MAX_VAL) {
158  message
159  << "\nTrying to apply " << setup.get<TrackerAlignmentRcd>().key().name()
160  << " with multiple IOVs in tag without specifying 'RunRangeSelection'.\n"
161  << "Validity range is "
162  << iov_alignments.first().eventID().run() << " - "
163  << iov_alignments.last().eventID().run() << "\n";
164  throwException = true;
165  }
166  if (iov_surfaces.first().eventID().run() != MIN_VAL ||
167  iov_surfaces.last().eventID().run() != MAX_VAL) {
168  message
169  << "\nTrying to apply "
170  << setup.get<TrackerSurfaceDeformationRcd>().key().name()
171  << " with multiple IOVs in tag without specifying 'RunRangeSelection'.\n"
172  << "Validity range is "
173  << iov_surfaces.first().eventID().run() << " - "
174  << iov_surfaces.last().eventID().run() << "\n";
175  throwException = true;
176  }
177  if (iov_errors.first().eventID().run() != MIN_VAL ||
178  iov_errors.last().eventID().run() != MAX_VAL) {
179  message
180  << "\nTrying to apply "
181  << setup.get<TrackerAlignmentErrorExtendedRcd>().key().name()
182  << " with multiple IOVs in tag without specifying 'RunRangeSelection'.\n"
183  << "Validity range is "
184  << iov_errors.first().eventID().run() << " - "
185  << iov_errors.last().eventID().run() << "\n";
186  throwException = true;
187  }
188  if (throwException) {
189  throw cms::Exception("DatabaseError")
190  << "@SUB=MillePedeAlignmentAlgorithm::initialize" << message.str();
191  }
192  }
193 
194 
195  //Retrieve tracker topology from geometry
196  edm::ESHandle<TrackerTopology> tTopoHandle;
197  setup.get<TrackerTopologyRcd>().get(tTopoHandle);
198  const TrackerTopology* const tTopo = tTopoHandle.product();
199 
200  //Retrieve the thresolds cuts from DB for the PCL
201  if (runAtPCL_) {
202  edm::ESHandle<AlignPCLThresholds> thresholdHandle;
203  setup.get<AlignPCLThresholdsRcd>().get(thresholdHandle);
204  auto th = thresholdHandle.product();
205  theThresholds = std::make_shared<AlignPCLThresholds>();
206  storeThresholds(th->getNrecords(),th->getThreshold_Map());
207  }
208 
209  theAlignableNavigator = std::make_unique<AlignableNavigator>(extras, tracker, muon);
211  theAlignables = theAlignmentParameterStore->alignables();
212 
213  edm::ParameterSet pedeLabelerCfg(theConfig.getParameter<edm::ParameterSet>("pedeLabeler"));
214  edm::VParameterSet RunRangeSelectionVPSet(theConfig.getUntrackedParameter<edm::VParameterSet>("RunRangeSelection"));
215  pedeLabelerCfg.addUntrackedParameter<edm::VParameterSet>("RunRangeSelection",
216  RunRangeSelectionVPSet);
217 
218  std::string labelerPlugin = "PedeLabeler";
219  if (!RunRangeSelectionVPSet.empty()) {
220  labelerPlugin = "RunRangeDependentPedeLabeler";
221  if (pedeLabelerCfg.exists("plugin")) {
222  std::string labelerPluginCfg = pedeLabelerCfg.getParameter<std::string>("plugin");
223  if ((labelerPluginCfg!="PedeLabeler" && labelerPluginCfg!="RunRangeDependentPedeLabeler") ||
224  !pedeLabelerCfg.getUntrackedParameter<edm::VParameterSet>("parameterInstances").empty()) {
225  throw cms::Exception("BadConfig")
226  << "MillePedeAlignmentAlgorithm::initialize"
227  << "both RunRangeSelection and generic labeler specified in config file. "
228  << "Please get rid of either one of them.\n";
229  }
230  }
231  } else {
232  if (pedeLabelerCfg.exists("plugin")) {
233  labelerPlugin = pedeLabelerCfg.getParameter<std::string>("plugin");
234  }
235  }
236 
237  if (!pedeLabelerCfg.exists("plugin")) {
238  pedeLabelerCfg.addUntrackedParameter<std::string>("plugin", labelerPlugin);
239  }
240 
241  edm::LogInfo("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::initialize"
242  << "Using plugin '" << labelerPlugin << "' to generate labels.";
243 
244  thePedeLabels = std::shared_ptr<PedeLabelerBase>(PedeLabelerPluginFactory::get()
245  ->create(labelerPlugin,
246  PedeLabelerBase::TopLevelAlignables(tracker, muon, extras),
247  pedeLabelerCfg));
248 
249  // 1) Create PedeSteerer: correct alignable positions for coordinate system selection
250  edm::ParameterSet pedeSteerCfg(theConfig.getParameter<edm::ParameterSet>("pedeSteerer"));
251  thePedeSteer = std::make_unique<PedeSteerer>(tracker, muon, extras,
253  pedeSteerCfg, theDir, !this->isMode(myPedeSteerBit));
254 
255  // 2) If requested, directly read in and apply result of previous pede run,
256  // assuming that correction from 1) was also applied to create the result:
257  const std::vector<edm::ParameterSet> mprespset
258  (theConfig.getParameter<std::vector<edm::ParameterSet> >("pedeReaderInputs"));
259  if (!mprespset.empty()) {
260  edm::LogInfo("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::initialize"
261  << "Apply " << mprespset.end() - mprespset.begin()
262  << " previous MillePede constants from 'pedeReaderInputs'.";
263  }
264 
265  // FIXME: add selection of run range via 'pedeReaderInputs'
266  // Note: Results for parameters of IntegratedCalibration's cannot be treated...
267  RunRange runrange(cond::timeTypeSpecs[cond::runnumber].beginValue,
269  for (std::vector<edm::ParameterSet>::const_iterator iSet = mprespset.begin(), iE = mprespset.end();
270  iSet != iE; ++iSet) {
271  // This read will ignore calibrations as long as they are not yet passed to Millepede
272  // during/before initialize(..) - currently addCalibrations(..) is called later in AlignmentProducer
273  if (!this->readFromPede((*iSet), false, runrange)) { // false: do not erase SelectionUserVariables
274  throw cms::Exception("BadConfig")
275  << "MillePedeAlignmentAlgorithm::initialize: Problems reading input constants of "
276  << "pedeReaderInputs entry " << iSet - mprespset.begin() << '.';
277  }
278  theAlignmentParameterStore->applyParameters();
279  // Needed to shut up later warning from checkAliParams:
280  theAlignmentParameterStore->resetParameters();
281  }
282 
283  // 3) Now create steerings with 'final' start position:
284  thePedeSteer->buildSubSteer(tracker, muon, extras);
285 
286  // After (!) 1-3 of PedeSteerer which uses the SelectionUserVariables attached to the parameters:
287  this->buildUserVariables(theAlignables); // for hit statistics and/or pede result
288 
289  if (this->isMode(myMilleBit)) {
290  if (!theConfig.getParameter<std::vector<std::string> >("mergeBinaryFiles").empty() ||
291  !theConfig.getParameter<std::vector<std::string> >("mergeTreeFiles").empty()) {
292  throw cms::Exception("BadConfig")
293  << "'vstring mergeTreeFiles' and 'vstring mergeBinaryFiles' must be empty for "
294  << "modes running mille.";
295  }
296  const std::string moniFile(theConfig.getUntrackedParameter<std::string>("monitorFile"));
297  if (!moniFile.empty()) theMonitor = std::make_unique<MillePedeMonitor>(tTopo, (theDir + moniFile).c_str());
298 
299  // Get trajectory factory. In case nothing found, FrameWork will throw...
300  const edm::ParameterSet fctCfg(theConfig.getParameter<edm::ParameterSet>("TrajectoryFactory"));
301  const std::string fctName(fctCfg.getParameter<std::string>("TrajectoryFactoryName"));
302  theTrajectoryFactory = std::unique_ptr<TrajectoryFactoryBase>(TrajectoryFactoryPlugin::get()
303  ->create(fctName, fctCfg));
304  }
305 
306  if (this->isMode(myPedeSteerBit)) {
307  // Get config for survey and set flag accordingly
308  const edm::ParameterSet pxbSurveyCfg(theConfig.getParameter<edm::ParameterSet>("surveyPixelBarrel"));
309  theDoSurveyPixelBarrel = pxbSurveyCfg.getParameter<bool>("doSurvey");
310  if (theDoSurveyPixelBarrel) this->addPxbSurvey(pxbSurveyCfg);
311  }
312 }
313 
314 //____________________________________________________
316  return true;
317 }
318 
319 //____________________________________________________
320 bool MillePedeAlignmentAlgorithm::addCalibrations(const std::vector<IntegratedCalibrationBase*> &iCals)
321 {
322  theCalibrations.insert(theCalibrations.end(), iCals.begin(), iCals.end());
323  thePedeLabels->addCalibrations(iCals);
324  return true;
325 }
326 
327 //____________________________________________________
329 {
330  theThresholds->setAlignPCLThresholds(nRecords,thresholdMap);
331  return true;
332 }
333 
334 //_____________________________________________________________________________
336 {
337  if (isMode(myMilleBit)) {
338  return true;
339  } else {
340  return false;
341  }
342 }
343 
344 //_____________________________________________________________________________
346 {
347  if (isMode(myPedeReadBit)) {
348  if (runAtPCL_) {
349 
350  MillePedeFileReader mpReader(theConfig.getParameter<edm::ParameterSet>("MillePedeFileReader"),
353  );
354  mpReader.read();
355  return mpReader.storeAlignments();
356  } else {
357  return true;
358  }
359  } else {
360  return false;
361  }
362 }
363 
364 //____________________________________________________
366 {
367  if (this->isMode(myPedeReadBit)) {
368  // restore initial positions, rotations and deformations
371  } else {
373  }
374 
375  // Needed to shut up later warning from checkAliParams:
377  // To avoid that they keep values from previous IOV if no new one in pede result
379 
380  if (!this->readFromPede(theConfig.getParameter<edm::ParameterSet>("pedeReader"), true, runrange)) {
381  edm::LogError("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::setParametersForRunRange"
382  << "Problems reading pede result, but applying!";
383  }
385 
386  this->doIO(++theLastWrittenIov); // pre-increment!
387  }
388 
389  return true;
390 }
391 
392 
393 // Call at end of job ---------------------------------------------------------
394 //____________________________________________________
396 {
397  terminate();
398 }
400 {
401  theMille.reset(); // delete to close binary before running pede below (flush would be enough...)
402  theBinary.reset();
403 
404  std::vector<std::string> files;
405  if (this->isMode(myMilleBit) || !theConfig.getParameter<std::string>("binaryFile").empty()) {
406  files.push_back(theDir + theConfig.getParameter<std::string>("binaryFile"));
407  } else {
408  const std::vector<std::string> plainFiles(theConfig.getParameter<std::vector<std::string> >("mergeBinaryFiles"));
409  files = getExistingFormattedFiles(plainFiles, theDir);
410  // Do some logging:
411  std::string filesForLogOutput;
412  for (const auto& file: files) filesForLogOutput += " " + file + ",";
413  if (filesForLogOutput.length() != 0) filesForLogOutput.pop_back();
414  edm::LogInfo("Alignment")
415  << "Based on the config parameter mergeBinaryFiles, using the following "
416  << "files as input (assigned weights are indicated by ' -- <weight>'):"
417  << filesForLogOutput;
418  }
419 
420  // cache all positions, rotations and deformations
423  if (lastProcessedRun_ < uniqueRunRanges_.back().first) {
424  throw cms::Exception("BadConfig")
425  << "@SUB=MillePedeAlignmentAlgorithm::terminate\n"
426  << "Last IOV of 'RunRangeSelection' has not been processed. "
427  << "Please reconfigure your source to process the runs at least up to "
428  << uniqueRunRanges_.back().first << ".";
429  }
430  auto lastCachedRun = uniqueRunRanges_.front().first;
431  for (const auto& runRange: uniqueRunRanges_) {
432  const auto run = runRange.first;
433  if (std::find(cachedRuns_.begin(), cachedRuns_.end(), run) == cachedRuns_.end()) {
436  } else {
437  lastCachedRun = run;
438  }
439  }
441  }
442 
443  const std::string masterSteer(thePedeSteer->buildMasterSteer(files));// do only if myPedeSteerBit?
444  if (this->isMode(myPedeRunBit)) {
445  thePedeSteer->runPede(masterSteer);
446  }
447 
448  // parameters from pede are not yet applied,
449  // so we can still write start positions (but with hit statistics in case of mille):
450  this->doIO(0);
451  theLastWrittenIov = 0;
452 }
453 
454 std::vector<std::string> MillePedeAlignmentAlgorithm::getExistingFormattedFiles(const std::vector<std::string>& plainFiles, const std::string& theDir) {
455  std::vector<std::string> files;
456  for (const auto& plainFile: plainFiles) {
457  const std::string& theInputFileName = plainFile;
458  int theNumber = 0;
459  while (true) {
460  // Create a formatted version of the filename, with growing numbers
461  // If the parameter doesn't contain a formatting directive, it just stays unchanged
462  char theNumberedInputFileName[200];
463  sprintf(theNumberedInputFileName, theInputFileName.c_str(), theNumber);
464  std::string theCompleteInputFileName = theDir + theNumberedInputFileName;
465  const auto endOfStrippedFileName = theCompleteInputFileName.rfind(" --");
466  const auto strippedInputFileName = theCompleteInputFileName.substr(0, endOfStrippedFileName);
467  // Check if the file exists
468  struct stat buffer;
469  if (stat (strippedInputFileName.c_str(), &buffer) == 0) {
470  // If the file exists, add it to the list
471  files.push_back(theCompleteInputFileName);
472  if (theNumberedInputFileName == theInputFileName) {
473  // If the filename didn't contain a formatting directive, no reason to look any further, break out of the loop
474  break;
475  } else {
476  // Otherwise look for the next number
477  theNumber++;
478  }
479  } else {
480  // The file doesn't exist, break out of the loop
481  break;
482  }
483  }
484  // warning if unformatted (-> theNumber stays at 0) does not exist
485  if (theNumber == 0 && (files.empty() || files.back() != plainFile)) {
486  edm::LogWarning("Alignment")
487  << "The input file '" << plainFile << "' does not exist.";
488  }
489  }
490  return files;
491 }
492 
493 // Run the algorithm on trajectories and tracks -------------------------------
494 //____________________________________________________
496 {
497  if (!this->isMode(myMilleBit)) return; // no theMille created...
498  const auto& tracks = eventInfo.trajTrackPairs();
499 
500  if (theMonitor) { // monitor input tracks
501  for (const auto& iTrajTrack: tracks) {
502  theMonitor->fillTrack(iTrajTrack.second);
503  }
504  }
505 
506  const RefTrajColl trajectories(theTrajectoryFactory->trajectories(setup, tracks, eventInfo.beamSpot()));
507 
508  // Now loop over ReferenceTrajectoryCollection
509  unsigned int refTrajCount = 0; // counter for track monitoring
510  const auto tracksPerTraj = theTrajectoryFactory->tracksPerTrajectory();
511  for (auto iRefTraj = trajectories.cbegin(), iRefTrajE = trajectories.cend();
512  iRefTraj != iRefTrajE; ++iRefTraj, ++refTrajCount) {
513 
514  RefTrajColl::value_type refTrajPtr = *iRefTraj;
515  if (theMonitor) theMonitor->fillRefTrajectory(refTrajPtr);
516 
517  const auto nHitXy = this->addReferenceTrajectory(setup, eventInfo, refTrajPtr);
518 
519  if (theMonitor && (nHitXy.first || nHitXy.second)) {
520  // if trajectory used (i.e. some hits), fill monitoring
521  const auto offset = tracksPerTraj*refTrajCount;
522  for (unsigned int iTrack = 0; iTrack < tracksPerTraj; ++iTrack) {
523  theMonitor->fillUsedTrack(tracks[offset+iTrack].second,
524  nHitXy.first, nHitXy.second);
525  }
526  }
527 
528  } // end of reference trajectory and track loop
529 }
530 
531 //____________________________________________________
532 std::pair<unsigned int, unsigned int>
534  const EventInfo &eventInfo,
535  const RefTrajColl::value_type &refTrajPtr)
536 {
537  std::pair<unsigned int, unsigned int> hitResultXy(0,0);
538  if (refTrajPtr->isValid()) {
539 
540 
541  // GblTrajectory?
542  if (!refTrajPtr->gblInput().empty()) {
543  // by construction: number of GblPoints == number of recHits or == zero !!!
544  unsigned int iHit = 0;
545  unsigned int numPointsWithMeas = 0;
546  std::vector<GblPoint>::iterator itPoint;
547  auto theGblInput = refTrajPtr->gblInput();
548  for (unsigned int iTraj = 0; iTraj < refTrajPtr->gblInput().size(); ++iTraj) {
549  for (itPoint = refTrajPtr->gblInput()[iTraj].first.begin(); itPoint < refTrajPtr->gblInput()[iTraj].first.end(); ++itPoint) {
550  if (this->addGlobalData(setup, eventInfo, refTrajPtr, iHit++, *itPoint) < 0) return hitResultXy;
551  if (itPoint->hasMeasurement() >= 1) ++numPointsWithMeas;
552  }
553  }
554  hitResultXy.first = numPointsWithMeas;
555  // check #hits criterion
556  if (hitResultXy.first == 0 || hitResultXy.first < theMinNumHits) return hitResultXy;
557  // construct GBL trajectory
558  if (refTrajPtr->gblInput().size() == 1) {
559  // from single track
560  GblTrajectory aGblTrajectory( refTrajPtr->gblInput()[0].first, refTrajPtr->nominalField() != 0 );
561  // GBL fit trajectory
562  /*double Chi2;
563  int Ndf;
564  double lostWeight;
565  aGblTrajectory.fit(Chi2, Ndf, lostWeight);
566  std::cout << " GblFit: " << Chi2 << ", " << Ndf << ", " << lostWeight << std::endl; */
567  // write to MP binary file
568  if (aGblTrajectory.isValid() && aGblTrajectory.getNumPoints() >= theMinNumHits) aGblTrajectory.milleOut(*theBinary);
569  }
570  if (refTrajPtr->gblInput().size() == 2) {
571  // from TwoBodyDecay
572  GblTrajectory aGblTrajectory( refTrajPtr->gblInput(), refTrajPtr->gblExtDerivatives(), refTrajPtr->gblExtMeasurements(), refTrajPtr->gblExtPrecisions() );
573  // write to MP binary file
574  if (aGblTrajectory.isValid() && aGblTrajectory.getNumPoints() >= theMinNumHits) aGblTrajectory.milleOut(*theBinary);
575  }
576  } else {
577  // to add hits if all fine:
578  std::vector<AlignmentParameters*> parVec(refTrajPtr->recHits().size());
579  // collect hit statistics, assuming that there are no y-only hits
580  std::vector<bool> validHitVecY(refTrajPtr->recHits().size(), false);
581  // Use recHits from ReferenceTrajectory (since they have the right order!):
582  for (unsigned int iHit = 0; iHit < refTrajPtr->recHits().size(); ++iHit) {
583  const int flagXY = this->addMeasurementData(setup, eventInfo, refTrajPtr, iHit, parVec[iHit]);
584 
585  if (flagXY < 0) { // problem
586  hitResultXy.first = 0;
587  break;
588  } else { // hit is fine, increase x/y statistics
589  if (flagXY >= 1) ++hitResultXy.first;
590  validHitVecY[iHit] = (flagXY >= 2);
591  }
592  } // end loop on hits
593 
594  // add virtual measurements
595  for (unsigned int iVirtualMeas = 0; iVirtualMeas < refTrajPtr->numberOfVirtualMeas(); ++iVirtualMeas) {
596  this->addVirtualMeas(refTrajPtr, iVirtualMeas);
597  }
598 
599  // kill or end 'track' for mille, depends on #hits criterion
600  if (hitResultXy.first == 0 || hitResultXy.first < theMinNumHits) {
601  theMille->kill();
602  hitResultXy.first = hitResultXy.second = 0; //reset
603  } else {
604  theMille->end();
605  // add x/y hit count to MillePedeVariables of parVec,
606  // returning number of y-hits of the reference trajectory
607  hitResultXy.second = this->addHitCount(parVec, validHitVecY);
608  //
609  }
610  }
611 
612  } // end if valid trajectory
613 
614  return hitResultXy;
615 }
616 
617 //____________________________________________________
618 unsigned int
619 MillePedeAlignmentAlgorithm::addHitCount(const std::vector<AlignmentParameters*> &parVec,
620  const std::vector<bool> &validHitVecY) const
621 {
622  // Loop on all hit information in the input arrays and count valid y-hits:
623  unsigned int nHitY = 0;
624  for (unsigned int iHit = 0; iHit < validHitVecY.size(); ++iHit) {
625  Alignable *ali = (parVec[iHit] ? parVec[iHit]->alignable() : nullptr);
626  // Loop upwards on hierarchy of alignables to add hits to all levels
627  // that are currently aligned. If only a non-selected alignable was hit,
628  // (i.e. flagXY == 0 in addReferenceTrajectory(..)), there is no loop at all...
629  while (ali) {
631  if (pars) { // otherwise hierarchy level not selected
632  // cast ensured by previous checks:
633  MillePedeVariables *mpVar = static_cast<MillePedeVariables*>(pars->userVariables());
634  // every hit has an x-measurement, cf. addReferenceTrajectory(..):
635  mpVar->increaseHitsX();
636  if (validHitVecY[iHit]) {
637  mpVar->increaseHitsY();
638  if (pars == parVec[iHit]) ++nHitY; // do not count hits twice
639  }
640  }
641  ali = ali->mother();
642  }
643  }
644 
645  return nHitY;
646 }
647 
648 
650  const edm::EventSetup& setup,
651  bool changed) {
652  if (run.run() < firstIOV_ && !ignoreFirstIOVCheck_) {
653  throw cms::Exception("Alignment")
654  << "@SUB=MillePedeAlignmentAlgorithm::beginRun\n"
655  << "Using data (run = " << run.run()
656  << ") prior to the first defined IOV (" << firstIOV_ << ").";
657  }
658 
659  lastProcessedRun_ = run.run();
660 
661  if (changed && enableAlignableUpdates_) {
662  const auto runNumber = run.run();
664  for (auto runRange = uniqueRunRanges_.crbegin();
665  runRange != uniqueRunRanges_.crend(); ++runRange) {
666  if (runNumber >= runRange->first) {
667  firstRun = runRange->first;
668  break;
669  }
670  }
671  if (std::find(cachedRuns_.begin(), cachedRuns_.end(), firstRun)
672  != cachedRuns_.end()) {
673  const auto& geometryRcd = setup.get<IdealGeometryRecord>();
674  const auto& globalPosRcd = setup.get<GlobalPositionRcd>();
675  const auto& alignmentRcd = setup.get<TrackerAlignmentRcd>();
676  const auto& surfaceRcd = setup.get<TrackerSurfaceDeformationRcd>();
677  const auto& errorRcd = setup.get<TrackerAlignmentErrorExtendedRcd>();
678 
679  std::ostringstream message;
680  bool throwException{false};
681  message
682  << "Trying to cache tracker alignment payloads for a run (" << runNumber
683  << ") in an IOV (" << firstRun << ") that was already cached.\n"
684  << "The following records in your input database tag have an IOV "
685  << "boundary that does not match your IOV definition:\n";
686  if (geometryRcd.validityInterval().first().eventID().run() > firstRun) {
687  message
688  << " - IdealGeometryRecord '" << geometryRcd.key().name()
689  << "' (since "
690  << geometryRcd.validityInterval().first().eventID().run() << ")\n";
691  throwException = true;
692  }
693  if (globalPosRcd.validityInterval().first().eventID().run() > firstRun) {
694  message
695  << " - GlobalPositionRecord '" << globalPosRcd.key().name()
696  << "' (since "
697  << globalPosRcd.validityInterval().first().eventID().run() << ")";
699  message << " --> ignored\n";
700  } else {
701  message << "\n";
702  throwException = true;
703  }
704  }
705  if (alignmentRcd.validityInterval().first().eventID().run() > firstRun) {
706  message
707  << " - TrackerAlignmentRcd '" << alignmentRcd.key().name()
708  << "' (since "
709  << alignmentRcd.validityInterval().first().eventID().run() << ")\n";
710  throwException = true;
711  }
712  if (surfaceRcd.validityInterval().first().eventID().run() > firstRun) {
713  message
714  << " - TrackerSurfaceDeformationRcd '" << surfaceRcd.key().name()
715  << "' (since "
716  << surfaceRcd.validityInterval().first().eventID().run() << ")\n";
717  throwException = true;
718  }
719  if (errorRcd.validityInterval().first().eventID().run() > firstRun) {
720  message
721  << " - TrackerAlignmentErrorExtendedRcd '" << errorRcd.key().name()
722  << "' (since "
723  << errorRcd.validityInterval().first().eventID().run() << ")\n";
724  throwException = true;
725  }
726 
727  if (throwException) {
728  throw cms::Exception("Alignment")
729  << "@SUB=MillePedeAlignmentAlgorithm::beginRun\n" << message.str();
730  }
731  } else {
732  cachedRuns_.push_back(firstRun);
734  }
735  }
736 }
737 
738 //____________________________________________________
740  const edm::EventSetup &setup)
741 {
742  if(runInfo.tkLasBeams() && runInfo.tkLasBeamTsoses()){
743  // LAS beam treatment
744  this->addLaserData(eventInfo, *(runInfo.tkLasBeams()), *(runInfo.tkLasBeamTsoses()));
745  }
746  if(this->isMode(myMilleBit)) theMille->flushOutputFile();
747 }
748 
749 // Implementation of endRun that DOES get called. (Because we need it.)
751  if(this->isMode(myMilleBit)) theMille->flushOutputFile();
752 }
753 
754 //____________________________________________________
756 {
757  if (!runAtPCL_) return;
758  if(this->isMode(myMilleBit)) theMille->resetOutputFile();
759 }
760 
761 //____________________________________________________
763 {
764  if (!runAtPCL_) return;
765  if(this->isMode(myMilleBit)) theMille->flushOutputFile();
766 }
767 
768 
769 //____________________________________________________
771  const EventInfo &eventInfo,
773  unsigned int iHit,
774  AlignmentParameters *&params)
775 {
776  params = nullptr;
777  theFloatBufferX.clear();
778  theFloatBufferY.clear();
779  theIntBuffer.clear();
780 
781  const TrajectoryStateOnSurface &tsos = refTrajPtr->trajectoryStates()[iHit];
782  const ConstRecHitPointer &recHitPtr = refTrajPtr->recHits()[iHit];
783  // ignore invalid hits
784  if (!recHitPtr->isValid()) return 0;
785 
786  // First add the derivatives from IntegratedCalibration's,
787  // should even be OK if problems for "usual" derivatives from Alignables
788  this->globalDerivativesCalibration(recHitPtr, tsos, setup, eventInfo, // input
790 
791  // get AlignableDet/Unit for this hit
792  AlignableDetOrUnitPtr alidet(theAlignableNavigator->alignableFromDetId(recHitPtr->geographicalId()));
793 
794  if (!this->globalDerivativesHierarchy(eventInfo,
795  tsos, alidet, alidet, theFloatBufferX, // 2x alidet, sic!
796  theFloatBufferY, theIntBuffer, params)) {
797  return -1; // problem
799  return 0; // empty for X: no alignable for hit, nor calibrations
800  } else {
801  // store measurement even if no alignable or calibrations
802  // -> measurement used for pede-internal track-fit
803  return this->callMille(refTrajPtr, iHit, theIntBuffer, theFloatBufferX, theFloatBufferY);
804  }
805 }
806 
807 //____________________________________________________
808 
811  unsigned int iHit, GblPoint &gblPoint)
812 {
813  AlignmentParameters* params = nullptr;
814  std::vector<double> theDoubleBufferX, theDoubleBufferY;
815  theDoubleBufferX.clear();
816  theDoubleBufferY.clear();
817  theIntBuffer.clear();
818  int iret = 0;
819 
820  const TrajectoryStateOnSurface &tsos = refTrajPtr->trajectoryStates()[iHit];
821  const ConstRecHitPointer &recHitPtr = refTrajPtr->recHits()[iHit];
822  // ignore invalid hits
823  if (!recHitPtr->isValid()) return 0;
824 
825  // get AlignableDet/Unit for this hit
826  AlignableDetOrUnitPtr alidet(theAlignableNavigator->alignableFromDetId(recHitPtr->geographicalId()));
827 
828  if (!this->globalDerivativesHierarchy(eventInfo,
829  tsos, alidet, alidet, theDoubleBufferX, // 2x alidet, sic!
830  theDoubleBufferY, theIntBuffer, params)) {
831  return -1; // problem
832  }
833  //calibration parameters
834  int globalLabel;
835  std::vector<IntegratedCalibrationBase::ValuesIndexPair> derivs;
836  for (auto iCalib = theCalibrations.begin(); iCalib != theCalibrations.end(); ++iCalib) {
837  // get all derivatives of this calibration // const unsigned int num =
838  (*iCalib)->derivatives(derivs, *recHitPtr, tsos, setup, eventInfo);
839  for (auto iValuesInd = derivs.begin(); iValuesInd != derivs.end(); ++iValuesInd) {
840  // transfer label and x/y derivatives
841  globalLabel = thePedeLabels->calibrationLabel(*iCalib, iValuesInd->second);
842  if (globalLabel > 0 && globalLabel <= 2147483647) {
843  theIntBuffer.push_back(globalLabel);
844  theDoubleBufferX.push_back(iValuesInd->first.first);
845  theDoubleBufferY.push_back(iValuesInd->first.second);
846  } else {
847  edm::LogError("Alignment")
848  << "@SUB=MillePedeAlignmentAlgorithm::addGlobalData"
849  << "Invalid label " << globalLabel << " <= 0 or > 2147483647";
850  }
851  }
852  }
853  unsigned int numGlobals = theIntBuffer.size();
854  if (numGlobals > 0)
855  {
856  Eigen::Matrix<double, 2, Eigen::Dynamic> globalDer{2, numGlobals};
857  for (unsigned int i = 0; i < numGlobals; ++i) {
858  globalDer(0,i) = theDoubleBufferX[i];
859  globalDer(1,i) = theDoubleBufferY[i];
860  }
861  gblPoint.addGlobals( theIntBuffer, globalDer );
862  iret = 1;
863  }
864  return iret;
865 }
866 
867 //____________________________________________________
870  const TrajectoryStateOnSurface &tsos,
871  Alignable *ali, const AlignableDetOrUnitPtr &alidet,
872  std::vector<float> &globalDerivativesX,
873  std::vector<float> &globalDerivativesY,
874  std::vector<int> &globalLabels,
875  AlignmentParameters *&lowestParams) const
876 {
877  // derivatives and labels are recursively attached
878  if (!ali) return true; // no mother might be OK
879 
880  if (false && theMonitor && alidet != ali) theMonitor->fillFrameToFrame(alidet, ali);
881 
882  AlignmentParameters *params = ali->alignmentParameters();
883 
884  if (params) {
885  if (!lowestParams) lowestParams = params; // set parameters of lowest level
886 
887  bool hasSplitParameters = thePedeLabels->hasSplitParameters(ali);
888  const unsigned int alignableLabel = thePedeLabels->alignableLabel(ali);
889 
890  if (0 == alignableLabel) { // FIXME: what about regardAllHits in Markus' code?
891  edm::LogWarning("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::globalDerivativesHierarchy"
892  << "Label not found, skip Alignable.";
893  return false;
894  }
895 
896  const std::vector<bool> &selPars = params->selector();
897  const AlgebraicMatrix derivs(params->derivatives(tsos, alidet));
898 
899  // cols: 2, i.e. x&y, rows: parameters, usually RigidBodyAlignmentParameters::N_PARAM
900  for (unsigned int iSel = 0; iSel < selPars.size(); ++iSel) {
901  if (selPars[iSel]) {
902  globalDerivativesX.push_back(derivs[iSel][kLocalX]
903  /thePedeSteer->cmsToPedeFactor(iSel));
904  if (hasSplitParameters==true) {
905  globalLabels.push_back(thePedeLabels->parameterLabel(ali, iSel, eventInfo, tsos));
906  } else {
907  globalLabels.push_back(thePedeLabels->parameterLabel(alignableLabel, iSel));
908  }
909  globalDerivativesY.push_back(derivs[iSel][kLocalY]
910  /thePedeSteer->cmsToPedeFactor(iSel));
911  }
912  }
913  // Exclude mothers if Alignable selected to be no part of a hierarchy:
914  if (thePedeSteer->isNoHiera(ali)) return true;
915  }
916  // Call recursively for mother, will stop if mother == 0:
917  return this->globalDerivativesHierarchy(eventInfo,
918  tsos, ali->mother(), alidet,
919  globalDerivativesX, globalDerivativesY,
920  globalLabels, lowestParams);
921 }
922 
923 //____________________________________________________
926  const TrajectoryStateOnSurface &tsos,
927  Alignable *ali, const AlignableDetOrUnitPtr &alidet,
928  std::vector<double> &globalDerivativesX,
929  std::vector<double> &globalDerivativesY,
930  std::vector<int> &globalLabels,
931  AlignmentParameters *&lowestParams) const
932 {
933  // derivatives and labels are recursively attached
934  if (!ali) return true; // no mother might be OK
935 
936  if (false && theMonitor && alidet != ali) theMonitor->fillFrameToFrame(alidet, ali);
937 
938  AlignmentParameters *params = ali->alignmentParameters();
939 
940  if (params) {
941  if (!lowestParams) lowestParams = params; // set parameters of lowest level
942 
943  bool hasSplitParameters = thePedeLabels->hasSplitParameters(ali);
944  const unsigned int alignableLabel = thePedeLabels->alignableLabel(ali);
945 
946  if (0 == alignableLabel) { // FIXME: what about regardAllHits in Markus' code?
947  edm::LogWarning("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::globalDerivativesHierarchy"
948  << "Label not found, skip Alignable.";
949  return false;
950  }
951 
952  const std::vector<bool> &selPars = params->selector();
953  const AlgebraicMatrix derivs(params->derivatives(tsos, alidet));
954  int globalLabel;
955 
956  // cols: 2, i.e. x&y, rows: parameters, usually RigidBodyAlignmentParameters::N_PARAM
957  for (unsigned int iSel = 0; iSel < selPars.size(); ++iSel) {
958  if (selPars[iSel]) {
959  if (hasSplitParameters==true) {
960  globalLabel = thePedeLabels->parameterLabel(ali, iSel, eventInfo, tsos);
961  } else {
962  globalLabel = thePedeLabels->parameterLabel(alignableLabel, iSel);
963  }
964  if (globalLabel > 0 && globalLabel <= 2147483647) {
965  globalLabels.push_back(globalLabel);
966  globalDerivativesX.push_back(derivs[iSel][kLocalX] / thePedeSteer->cmsToPedeFactor(iSel));
967  globalDerivativesY.push_back(derivs[iSel][kLocalY] / thePedeSteer->cmsToPedeFactor(iSel));
968  } else {
969  edm::LogError("Alignment")
970  << "@SUB=MillePedeAlignmentAlgorithm::globalDerivativesHierarchy"
971  << "Invalid label " << globalLabel << " <= 0 or > 2147483647";
972  }
973  }
974  }
975  // Exclude mothers if Alignable selected to be no part of a hierarchy:
976  if (thePedeSteer->isNoHiera(ali)) return true;
977  }
978  // Call recursively for mother, will stop if mother == 0:
979  return this->globalDerivativesHierarchy(eventInfo,
980  tsos, ali->mother(), alidet,
981  globalDerivativesX, globalDerivativesY,
982  globalLabels, lowestParams);
983 }
984 
985 //____________________________________________________
988  const TrajectoryStateOnSurface &tsos,
989  const edm::EventSetup &setup, const EventInfo &eventInfo,
990  std::vector<float> &globalDerivativesX,
991  std::vector<float> &globalDerivativesY,
992  std::vector<int> &globalLabels) const
993 {
994  std::vector<IntegratedCalibrationBase::ValuesIndexPair> derivs;
995  for (auto iCalib = theCalibrations.begin(); iCalib != theCalibrations.end(); ++iCalib) {
996  // get all derivatives of this calibration // const unsigned int num =
997  (*iCalib)->derivatives(derivs, *recHit, tsos, setup, eventInfo);
998  for (auto iValuesInd = derivs.begin(); iValuesInd != derivs.end(); ++iValuesInd) {
999  // transfer label and x/y derivatives
1000  globalLabels.push_back(thePedeLabels->calibrationLabel(*iCalib, iValuesInd->second));
1001  globalDerivativesX.push_back(iValuesInd->first.first);
1002  globalDerivativesY.push_back(iValuesInd->first.second);
1003  }
1004  }
1005 }
1006 
1007 // //____________________________________________________
1008 // void MillePedeAlignmentAlgorithm
1009 // ::callMille(const ReferenceTrajectoryBase::ReferenceTrajectoryPtr &refTrajPtr,
1010 // unsigned int iTrajHit, MeasurementDirection xOrY,
1011 // const std::vector<float> &globalDerivatives, const std::vector<int> &globalLabels)
1012 // {
1013 // const unsigned int xyIndex = iTrajHit*2 + xOrY;
1014 // // FIXME: here for residuum and sigma we could use KALMAN-Filter results
1015 // const float residuum =
1016 // refTrajPtr->measurements()[xyIndex] - refTrajPtr->trajectoryPositions()[xyIndex];
1017 // const float covariance = refTrajPtr->measurementErrors()[xyIndex][xyIndex];
1018 // const float sigma = (covariance > 0. ? TMath::Sqrt(covariance) : 0.);
1019 
1020 // const AlgebraicMatrix &locDerivMatrix = refTrajPtr->derivatives();
1021 
1022 // std::vector<float> localDerivs(locDerivMatrix.num_col());
1023 // for (unsigned int i = 0; i < localDerivs.size(); ++i) {
1024 // localDerivs[i] = locDerivMatrix[xyIndex][i];
1025 // }
1026 
1027 // // &(vector[0]) is valid - as long as vector is not empty
1028 // // cf. http://www.parashift.com/c++-faq-lite/containers.html#faq-34.3
1029 // theMille->mille(localDerivs.size(), &(localDerivs[0]),
1030 // globalDerivatives.size(), &(globalDerivatives[0]), &(globalLabels[0]),
1031 // residuum, sigma);
1032 // if (theMonitor) {
1033 // theMonitor->fillDerivatives(refTrajPtr->recHits()[iTrajHit],localDerivs, globalDerivatives,
1034 // (xOrY == kLocalY));
1035 // theMonitor->fillResiduals(refTrajPtr->recHits()[iTrajHit],
1036 // refTrajPtr->trajectoryStates()[iTrajHit],
1037 // iTrajHit, residuum, sigma, (xOrY == kLocalY));
1038 // }
1039 // }
1040 
1041 //____________________________________________________
1043 {
1044  // FIXME: Check whether this is a reliable and recommended way to find out...
1045 
1046  if (recHit->dimension() < 2) {
1047  return false; // some muon and TIB/TOB stuff really has RecHit1D
1048  } else if (recHit->detUnit()) { // detunit in strip is 1D, in pixel 2D
1049  return recHit->detUnit()->type().isTrackerPixel();
1050  } else { // stereo strips (FIXME: endcap trouble due to non-parallel strips (wedge sensors)?)
1051  if (dynamic_cast<const ProjectedSiStripRecHit2D*>(recHit->hit())) { // check persistent hit
1052  // projected: 1D measurement on 'glued' module
1053  return false;
1054  } else {
1055  return true;
1056  }
1057  }
1058 }
1059 
1060 //__________________________________________________________________________________________________
1061 bool MillePedeAlignmentAlgorithm::readFromPede(const edm::ParameterSet &mprespset, bool setUserVars,
1062  const RunRange &runrange)
1063 {
1064  bool allEmpty = this->areEmptyParams(theAlignables);
1065 
1066  PedeReader reader(mprespset, *thePedeSteer, *thePedeLabels, runrange);
1067  std::vector<Alignable*> alis;
1068  bool okRead = reader.read(alis, setUserVars); // also may set params of IntegratedCalibration's
1069  bool numMatch = true;
1070 
1071  std::stringstream out;
1072  out << "Read " << alis.size() << " alignables";
1073  if (alis.size() != theAlignables.size()) {
1074  out << " while " << theAlignables.size() << " in store";
1075  numMatch = false; // FIXME: Should we check one by one? Or transfer 'alis' to the store?
1076  }
1077  if (!okRead) out << ", but problems in reading";
1078  if (!allEmpty) out << ", possibly overwriting previous settings";
1079  out << ".";
1080 
1081  if (okRead && allEmpty) {
1082  if (numMatch) { // as many alignables with result as trying to align
1083  edm::LogInfo("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::readFromPede" << out.str();
1084  } else if (!alis.empty()) { // dead module do not get hits and no pede result
1085  edm::LogWarning("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::readFromPede" << out.str();
1086  } else { // serious problem: no result read - and not all modules can be dead...
1087  edm::LogError("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::readFromPede" << out.str();
1088  return false;
1089  }
1090  return true;
1091  }
1092  // the rest is not OK:
1093  edm::LogError("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::readFromPede" << out.str();
1094  return false;
1095 }
1096 
1097 //__________________________________________________________________________________________________
1098 bool MillePedeAlignmentAlgorithm::areEmptyParams(const std::vector<Alignable*> &alignables) const
1099 {
1100 
1101  for (std::vector<Alignable*>::const_iterator iAli = alignables.begin();
1102  iAli != alignables.end(); ++iAli) {
1103  const AlignmentParameters *params = (*iAli)->alignmentParameters();
1104  if (params) {
1105  const auto& parVec(params->parameters());
1106  const auto& parCov(params->covariance());
1107  for (int i = 0; i < parVec.num_row(); ++i) {
1108  if (parVec[i] != 0.) return false;
1109  for (int j = i; j < parCov.num_col(); ++j) {
1110  if (parCov[i][j] != 0.) return false;
1111  }
1112  }
1113  }
1114  }
1115 
1116  return true;
1117 }
1118 
1119 //__________________________________________________________________________________________________
1121 {
1122  unsigned int result = 0;
1123 
1124  const std::string outFilePlain(theConfig.getParameter<std::string>("treeFile"));
1125  if (outFilePlain.empty()) {
1126  edm::LogInfo("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::doIO"
1127  << "treeFile parameter empty => skip writing for 'loop' " << loop;
1128  return result;
1129  }
1130 
1131  const std::string outFile(theDir + outFilePlain);
1132 
1133  AlignmentIORoot aliIO;
1134  int ioerr = 0;
1135  if (loop == 0) {
1136  aliIO.writeAlignableOriginalPositions(theAlignables, outFile.c_str(), loop, false, ioerr);
1137  if (ioerr) {
1138  edm::LogError("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::doIO"
1139  << "Problem " << ioerr << " in writeAlignableOriginalPositions";
1140  ++result;
1141  }
1142  } else if (loop == 1) {
1143  // only for first iov add hit counts, else 2x, 3x,... number of hits in IOV 2, 3,...
1144  const std::vector<std::string> inFiles
1145  (theConfig.getParameter<std::vector<std::string> >("mergeTreeFiles"));
1146  const std::vector<std::string> binFiles
1147  (theConfig.getParameter<std::vector<std::string> >("mergeBinaryFiles"));
1148  if (inFiles.size() != binFiles.size()) {
1149  edm::LogWarning("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::doIO"
1150  << "'vstring mergeTreeFiles' and 'vstring mergeBinaryFiles' "
1151  << "differ in size";
1152  }
1153  this->addHitStatistics(0, outFile, inFiles); // add hit info from tree 0 in 'infiles'
1154  }
1155  MillePedeVariablesIORoot millePedeIO;
1156  millePedeIO.writeMillePedeVariables(theAlignables, outFile.c_str(), loop, false, ioerr);
1157  if (ioerr) {
1158  edm::LogError("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::doIO"
1159  << "Problem " << ioerr << " writing MillePedeVariables";
1160  ++result;
1161  }
1162 
1163  aliIO.writeOrigRigidBodyAlignmentParameters(theAlignables, outFile.c_str(), loop, false, ioerr);
1164  if (ioerr) {
1165  edm::LogError("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::doIO" << "Problem " << ioerr
1166  << " in writeOrigRigidBodyAlignmentParameters, " << loop;
1167  ++result;
1168  }
1169  aliIO.writeAlignableAbsolutePositions(theAlignables, outFile.c_str(), loop, false, ioerr);
1170  if (ioerr) {
1171  edm::LogError("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::doIO" << "Problem " << ioerr
1172  << " in writeAlignableAbsolutePositions, " << loop;
1173  ++result;
1174  }
1175 
1176  return result;
1177 }
1178 
1179 //__________________________________________________________________________________________________
1180 void MillePedeAlignmentAlgorithm::buildUserVariables(const std::vector<Alignable*> &alis) const
1181 {
1182  for (const auto& iAli: alis) {
1183  AlignmentParameters *params = iAli->alignmentParameters();
1184  if (!params) {
1185  throw cms::Exception("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::buildUserVariables"
1186  << "No parameters for alignable";
1187  }
1188  MillePedeVariables *userVars = dynamic_cast<MillePedeVariables*>(params->userVariables());
1189  if (userVars) { // Just re-use existing, keeping label and numHits:
1190  for (unsigned int iPar = 0; iPar < userVars->size(); ++iPar) {
1191  // if (params->hierarchyLevel() > 0) {
1192  //std::cout << params->hierarchyLevel() << "\nBefore: " << userVars->parameter()[iPar];
1193  // }
1194  userVars->setAllDefault(iPar);
1195  //std::cout << "\nAfter: " << userVars->parameter()[iPar] << std::endl;
1196  }
1197  } else { // Nothing yet or erase wrong type:
1198  userVars = new MillePedeVariables(params->size(), thePedeLabels->alignableLabel(iAli),
1199  thePedeLabels->alignableTracker()->objectIdProvider().typeToName(iAli->alignableObjectId()));
1200  params->setUserVariables(userVars);
1201  }
1202  }
1203 }
1204 
1205 //__________________________________________________________________________________________________
1207 {
1208  if (mode == "full") {
1210  } else if (mode == "mille") {
1211  return myMilleBit; // + myPedeSteerBit; // sic! Including production of steerig file. NO!
1212  } else if (mode == "pede") {
1214  } else if (mode == "pedeSteer") {
1215  return myPedeSteerBit;
1216  } else if (mode == "pedeRun") {
1217  return myPedeSteerBit + myPedeRunBit + myPedeReadBit; // sic! Including steering and reading of result.
1218  } else if (mode == "pedeRead") {
1219  return myPedeReadBit;
1220  }
1221 
1222  throw cms::Exception("BadConfig")
1223  << "Unknown mode '" << mode
1224  << "', use 'full', 'mille', 'pede', 'pedeRun', 'pedeSteer' or 'pedeRead'.";
1225 
1226  return 0;
1227 }
1228 
1229 //__________________________________________________________________________________________________
1231  const std::vector<std::string> &inFiles) const
1232 {
1233  bool allOk = true;
1234  int ierr = 0;
1235  MillePedeVariablesIORoot millePedeIO;
1236  for (std::vector<std::string>::const_iterator iFile = inFiles.begin();
1237  iFile != inFiles.end(); ++iFile) {
1238  const std::string inFile(theDir + *iFile);
1239  const std::vector<AlignmentUserVariables*> mpVars =
1240  millePedeIO.readMillePedeVariables(theAlignables, inFile.c_str(), fromIov, ierr);
1241  if (ierr || !this->addHits(theAlignables, mpVars)) {
1242  edm::LogError("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::addHitStatistics"
1243  << "Error " << ierr << " reading from " << inFile
1244  << ", tree " << fromIov << ", or problems in addHits";
1245  allOk = false;
1246  }
1247  for (std::vector<AlignmentUserVariables*>::const_iterator i = mpVars.begin();
1248  i != mpVars.end(); ++i) {
1249  delete *i; // clean created objects
1250  }
1251  }
1252 
1253  return allOk;
1254 }
1255 
1256 //__________________________________________________________________________________________________
1257 bool MillePedeAlignmentAlgorithm::addHits(const std::vector<Alignable*> &alis,
1258  const std::vector<AlignmentUserVariables*> &mpVars) const
1259 {
1260  bool allOk = (mpVars.size() == alis.size());
1261  std::vector<AlignmentUserVariables*>::const_iterator iUser = mpVars.begin();
1262  for (std::vector<Alignable*>::const_iterator iAli = alis.begin();
1263  iAli != alis.end() && iUser != mpVars.end(); ++iAli, ++iUser) {
1264  MillePedeVariables *mpVarNew = dynamic_cast<MillePedeVariables*>(*iUser);
1265  AlignmentParameters *ps = (*iAli)->alignmentParameters();
1266  MillePedeVariables *mpVarOld = (ps ? dynamic_cast<MillePedeVariables*>(ps->userVariables()) : nullptr);
1267  if (!mpVarNew || !mpVarOld || mpVarOld->size() != mpVarNew->size()) {
1268  allOk = false;
1269  continue; // FIXME error etc.?
1270  }
1271 
1272  mpVarOld->increaseHitsX(mpVarNew->hitsX());
1273  mpVarOld->increaseHitsY(mpVarNew->hitsY());
1274  }
1275 
1276  return allOk;
1277 }
1278 
1279 //__________________________________________________________________________________________________
1280 template <typename GlobalDerivativeMatrix>
1281 void MillePedeAlignmentAlgorithm::makeGlobDerivMatrix(const std::vector<float> &globalDerivativesx,
1282  const std::vector<float> &globalDerivativesy,
1283  Eigen::MatrixBase<GlobalDerivativeMatrix>& aGlobalDerivativesM)
1284 {
1285  static_assert(GlobalDerivativeMatrix::RowsAtCompileTime == 2,
1286  "global derivative matrix must have two rows");
1287 
1288  for (size_t i = 0; i < globalDerivativesx.size(); ++i) {
1289  aGlobalDerivativesM(0,i) = globalDerivativesx[i];
1290  aGlobalDerivativesM(1,i) = globalDerivativesy[i];
1291  }
1292 }
1293 
1294 //__________________________________________________________________________________________________
1295 template <typename CovarianceMatrix,
1296  typename LocalDerivativeMatrix,
1297  typename ResidualMatrix,
1298  typename GlobalDerivativeMatrix>
1300 (Eigen::MatrixBase<CovarianceMatrix>& aHitCovarianceM,
1301  Eigen::MatrixBase<LocalDerivativeMatrix>& aLocalDerivativesM,
1302  Eigen::MatrixBase<ResidualMatrix>& aHitResidualsM,
1303  Eigen::MatrixBase<GlobalDerivativeMatrix>& aGlobalDerivativesM) const
1304 {
1305  static_assert(std::is_same<typename LocalDerivativeMatrix::Scalar,
1306  typename ResidualMatrix::Scalar>::value,
1307  "'aLocalDerivativesM' and 'aHitResidualsM' must have the "
1308  "same underlying scalar type");
1309  static_assert(std::is_same<typename LocalDerivativeMatrix::Scalar,
1311  "'aLocalDerivativesM' and 'aGlobalDerivativesM' must have the "
1312  "same underlying scalar type");
1313 
1314  Eigen::SelfAdjointEigenSolver<typename CovarianceMatrix::PlainObject> myDiag{aHitCovarianceM};
1315  // eigenvectors of real symmetric matrices are orthogonal, i.e. invert == transpose
1316  auto aTranfoToDiagonalSystemInv =
1317  myDiag.eigenvectors().transpose().template cast<typename LocalDerivativeMatrix::Scalar>();
1318 
1319  aHitCovarianceM = myDiag.eigenvalues().asDiagonal();
1320  aLocalDerivativesM = aTranfoToDiagonalSystemInv * aLocalDerivativesM;
1321  aHitResidualsM = aTranfoToDiagonalSystemInv * aHitResidualsM;
1322  if (aGlobalDerivativesM.size() > 0) {
1323  // diagonalize only if measurement depends on alignables or calibrations
1324  aGlobalDerivativesM = aTranfoToDiagonalSystemInv * aGlobalDerivativesM;
1325  }
1326 }
1327 
1328 //__________________________________________________________________________________________________
1329 template <typename CovarianceMatrix,
1330  typename ResidualMatrix,
1331  typename LocalDerivativeMatrix>
1334  unsigned int iVirtualMeas,
1335  Eigen::MatrixBase<CovarianceMatrix>& aHitCovarianceM,
1336  Eigen::MatrixBase<ResidualMatrix>& aHitResidualsM,
1337  Eigen::MatrixBase<LocalDerivativeMatrix>& aLocalDerivativesM)
1338 {
1339  // This Method is valid for 1D measurements only
1340 
1341  const unsigned int xIndex = iVirtualMeas + refTrajPtr->numberOfHitMeas();
1342 
1343  aHitCovarianceM(0,0)=refTrajPtr->measurementErrors()[xIndex][xIndex];
1344  aHitResidualsM(0,0)= refTrajPtr->measurements()[xIndex];
1345 
1346  const auto& locDerivMatrix = refTrajPtr->derivatives();
1347  for (int i = 0; i < locDerivMatrix.num_col(); ++i) {
1348  aLocalDerivativesM(0,i) = locDerivMatrix[xIndex][i];
1349  }
1350 }
1351 
1352 //__________________________________________________________________________________________________
1353 template <typename CovarianceMatrix,
1354  typename ResidualMatrix,
1355  typename LocalDerivativeMatrix>
1358  unsigned int iTrajHit,
1359  Eigen::MatrixBase<CovarianceMatrix>& aHitCovarianceM,
1360  Eigen::MatrixBase<ResidualMatrix>& aHitResidualsM,
1361  Eigen::MatrixBase<LocalDerivativeMatrix>& aLocalDerivativesM)
1362 {
1363  // This Method is valid for 2D measurements only
1364 
1365  const unsigned int xIndex = iTrajHit*2;
1366  const unsigned int yIndex = iTrajHit*2+1;
1367 
1368  aHitCovarianceM(0,0)=refTrajPtr->measurementErrors()[xIndex][xIndex];
1369  aHitCovarianceM(0,1)=refTrajPtr->measurementErrors()[xIndex][yIndex];
1370  aHitCovarianceM(1,0)=refTrajPtr->measurementErrors()[yIndex][xIndex];
1371  aHitCovarianceM(1,1)=refTrajPtr->measurementErrors()[yIndex][yIndex];
1372 
1373  aHitResidualsM(0,0)= refTrajPtr->measurements()[xIndex] - refTrajPtr->trajectoryPositions()[xIndex];
1374  aHitResidualsM(1,0)= refTrajPtr->measurements()[yIndex] - refTrajPtr->trajectoryPositions()[yIndex];
1375 
1376  const auto& locDerivMatrix = refTrajPtr->derivatives();
1377  for (int i = 0; i < locDerivMatrix.num_col(); ++i) {
1378  aLocalDerivativesM(0,i) = locDerivMatrix[xIndex][i];
1379  aLocalDerivativesM(1,i) = locDerivMatrix[yIndex][i];
1380  }
1381 }
1382 
1383 //__________________________________________________________________________________________________
1386  unsigned int iTrajHit, const std::vector<int> &globalLabels,
1387  const std::vector<float> &globalDerivativesX,
1388  const std::vector<float> &globalDerivativesY)
1389 {
1390  const ConstRecHitPointer aRecHit(refTrajPtr->recHits()[iTrajHit]);
1391 
1392  if((aRecHit)->dimension() == 1) {
1393  return this->callMille1D(refTrajPtr, iTrajHit, globalLabels, globalDerivativesX);
1394  } else {
1395  return this->callMille2D(refTrajPtr, iTrajHit, globalLabels,
1396  globalDerivativesX, globalDerivativesY);
1397  }
1398 }
1399 
1400 
1401 //__________________________________________________________________________________________________
1404  unsigned int iTrajHit, const std::vector<int> &globalLabels,
1405  const std::vector<float> &globalDerivativesX)
1406 {
1407  const ConstRecHitPointer aRecHit(refTrajPtr->recHits()[iTrajHit]);
1408  const unsigned int xIndex = iTrajHit*2; // the even ones are local x
1409 
1410  // local derivatives
1411  const AlgebraicMatrix &locDerivMatrix = refTrajPtr->derivatives();
1412  const int nLocal = locDerivMatrix.num_col();
1413  std::vector<float> localDerivatives(nLocal);
1414  for (unsigned int i = 0; i < localDerivatives.size(); ++i) {
1415  localDerivatives[i] = locDerivMatrix[xIndex][i];
1416  }
1417 
1418  // residuum and error
1419  float residX = refTrajPtr->measurements()[xIndex] - refTrajPtr->trajectoryPositions()[xIndex];
1420  float hitErrX = TMath::Sqrt(refTrajPtr->measurementErrors()[xIndex][xIndex]);
1421 
1422  // number of global derivatives
1423  const int nGlobal = globalDerivativesX.size();
1424 
1425  // &(localDerivatives[0]) etc. are valid - as long as vector is not empty
1426  // cf. http://www.parashift.com/c++-faq-lite/containers.html#faq-34.3
1427  theMille->mille(nLocal, &(localDerivatives[0]), nGlobal, &(globalDerivativesX[0]),
1428  &(globalLabels[0]), residX, hitErrX);
1429 
1430  if (theMonitor) {
1431  theMonitor->fillDerivatives(aRecHit, &(localDerivatives[0]), nLocal,
1432  &(globalDerivativesX[0]), nGlobal, &(globalLabels[0]));
1433  theMonitor->fillResiduals(aRecHit, refTrajPtr->trajectoryStates()[iTrajHit],
1434  iTrajHit, residX, hitErrX, false);
1435  }
1436 
1437  return 1;
1438 }
1439 
1440 //__________________________________________________________________________________________________
1443  unsigned int iTrajHit, const std::vector<int> &globalLabels,
1444  const std::vector<float> &globalDerivativesx,
1445  const std::vector<float> &globalDerivativesy)
1446 {
1447  const ConstRecHitPointer aRecHit(refTrajPtr->recHits()[iTrajHit]);
1448 
1449  if((aRecHit)->dimension() != 2) {
1450  edm::LogError("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::callMille2D"
1451  << "You try to call method for 2D hits for a "
1452  << (aRecHit)->dimension()
1453  << "D Hit. Hit gets ignored!";
1454  return -1;
1455  }
1456 
1457  Eigen::Matrix<double, 2, 2> aHitCovarianceM;
1458  Eigen::Matrix<float, 2, 1> aHitResidualsM;
1459  Eigen::Matrix<float, 2, Eigen::Dynamic>
1460  aLocalDerivativesM{2, refTrajPtr->derivatives().num_col()};
1461  // below method fills above 3 matrices
1462  this->addRefTrackData2D(refTrajPtr, iTrajHit, aHitCovarianceM,aHitResidualsM,aLocalDerivativesM);
1463  Eigen::Matrix<float, 2, Eigen::Dynamic>
1464  aGlobalDerivativesM{2, globalDerivativesx.size()};
1465  this->makeGlobDerivMatrix(globalDerivativesx, globalDerivativesy, aGlobalDerivativesM);
1466 
1467  // calculates correlation between Hit measurements
1468  // FIXME: Should take correlation (and resulting transformation) from original hit,
1469  // not 2x2 matrix from ReferenceTrajectory: That can come from error propagation etc.!
1470  const double corr = aHitCovarianceM(0,1) / sqrt(aHitCovarianceM(0,0) * aHitCovarianceM(1,1));
1471  if (theMonitor) theMonitor->fillCorrelations2D(corr, aRecHit);
1472  bool diag = false; // diagonalise only tracker TID, TEC
1473  switch(aRecHit->geographicalId().subdetId()) {
1474  case SiStripDetId::TID:
1475  case SiStripDetId::TEC:
1476  if (aRecHit->geographicalId().det() == DetId::Tracker && TMath::Abs(corr) > theMaximalCor2D) {
1477  this->diagonalize(aHitCovarianceM, aLocalDerivativesM, aHitResidualsM, aGlobalDerivativesM);
1478  diag = true;
1479  }
1480  break;
1481  default:;
1482  }
1483 
1484  float newResidX = aHitResidualsM(0,0);
1485  float newResidY = aHitResidualsM(1,0);
1486  float newHitErrX = TMath::Sqrt(aHitCovarianceM(0,0));
1487  float newHitErrY = TMath::Sqrt(aHitCovarianceM(1,1));
1488 
1489  // change from column major (Eigen default) to row major to have row entries
1490  // in continuous memory
1491  std::vector<float> newLocalDerivs(aLocalDerivativesM.size());
1492  Eigen::Map<Eigen::Matrix<float, 2, Eigen::Dynamic, Eigen::RowMajor> >
1493  (newLocalDerivs.data(),
1494  aLocalDerivativesM.rows(),
1495  aLocalDerivativesM.cols()) = aLocalDerivativesM;
1496  float* newLocalDerivsX = &(newLocalDerivs[0]);
1497  float* newLocalDerivsY = &(newLocalDerivs[aLocalDerivativesM.cols()]);
1498 
1499  // change from column major (Eigen default) to row major to have row entries
1500  // in continuous memory
1501  std::vector<float> newGlobDerivs(aGlobalDerivativesM.size());
1502  Eigen::Map<Eigen::Matrix<float, 2, Eigen::Dynamic, Eigen::RowMajor> >
1503  (newGlobDerivs.data(),
1504  aGlobalDerivativesM.rows(),
1505  aGlobalDerivativesM.cols()) = aGlobalDerivativesM;
1506  float* newGlobDerivsX = &(newGlobDerivs[0]);
1507  float* newGlobDerivsY = &(newGlobDerivs[aGlobalDerivativesM.cols()]);
1508 
1509  const int nLocal = aLocalDerivativesM.cols();
1510  const int nGlobal = aGlobalDerivativesM.cols();
1511 
1512  if (diag && (newHitErrX > newHitErrY)) { // also for 2D hits?
1513  // measurement with smaller error is x-measurement (for !is2D do not fill y-measurement):
1514  std::swap(newResidX, newResidY);
1515  std::swap(newHitErrX, newHitErrY);
1516  std::swap(newLocalDerivsX, newLocalDerivsY);
1517  std::swap(newGlobDerivsX, newGlobDerivsY);
1518  }
1519 
1520  // &(globalLabels[0]) is valid - as long as vector is not empty
1521  // cf. http://www.parashift.com/c++-faq-lite/containers.html#faq-34.3
1522  theMille->mille(nLocal, newLocalDerivsX, nGlobal, newGlobDerivsX,
1523  &(globalLabels[0]), newResidX, newHitErrX);
1524 
1525  if (theMonitor) {
1526  theMonitor->fillDerivatives(aRecHit, newLocalDerivsX, nLocal, newGlobDerivsX,
1527  nGlobal, &(globalLabels[0]));
1528  theMonitor->fillResiduals(aRecHit, refTrajPtr->trajectoryStates()[iTrajHit],
1529  iTrajHit, newResidX, newHitErrX, false);
1530  }
1531  const bool isReal2DHit = this->is2D(aRecHit); // strip is 1D (except matched hits)
1532  if (isReal2DHit) {
1533  theMille->mille(nLocal, newLocalDerivsY, nGlobal, newGlobDerivsY,
1534  &(globalLabels[0]), newResidY, newHitErrY);
1535  if (theMonitor) {
1536  theMonitor->fillDerivatives(aRecHit, newLocalDerivsY, nLocal, newGlobDerivsY,
1537  nGlobal, &(globalLabels[0]));
1538  theMonitor->fillResiduals(aRecHit, refTrajPtr->trajectoryStates()[iTrajHit],
1539  iTrajHit, newResidY, newHitErrY, true);// true: y
1540  }
1541  }
1542 
1543  return (isReal2DHit ? 2 : 1);
1544 }
1545 
1546 //__________________________________________________________________________________________________
1548 ::addVirtualMeas(const ReferenceTrajectoryBase::ReferenceTrajectoryPtr &refTrajPtr, unsigned int iVirtualMeas)
1549 {
1550  Eigen::Matrix<double, 1, 1> aHitCovarianceM;
1551  Eigen::Matrix<float, 1, 1> aHitResidualsM;
1552  Eigen::Matrix<float, 1, Eigen::Dynamic>
1553  aLocalDerivativesM{1, refTrajPtr->derivatives().num_col()};
1554  // below method fills above 3 'matrices'
1555  this->addRefTrackVirtualMeas1D(refTrajPtr, iVirtualMeas, aHitCovarianceM, aHitResidualsM, aLocalDerivativesM);
1556 
1557  // no global parameters (use dummy 0)
1558  auto aGlobalDerivativesM = Eigen::Matrix<float, 1, 1>::Zero();
1559 
1560  float newResidX = aHitResidualsM(0,0);
1561  float newHitErrX = TMath::Sqrt(aHitCovarianceM(0,0));
1562  std::vector<float> newLocalDerivsX(aLocalDerivativesM.size());
1563  Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> >
1564  (newLocalDerivsX.data(),
1565  aLocalDerivativesM.rows(),
1566  aLocalDerivativesM.cols()) = aLocalDerivativesM;
1567 
1568  std::vector<float> newGlobDerivsX(aGlobalDerivativesM.size());
1569  Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> >
1570  (newGlobDerivsX.data(),
1571  aGlobalDerivativesM.rows(),
1572  aGlobalDerivativesM.cols()) = aGlobalDerivativesM;
1573 
1574  const int nLocal = aLocalDerivativesM.cols();
1575  const int nGlobal = 0;
1576 
1577  theMille->mille(nLocal, newLocalDerivsX.data(), nGlobal, newGlobDerivsX.data(),
1578  &nGlobal, newResidX, newHitErrX);
1579 }
1580 
1581 //____________________________________________________
1583  const TkFittedLasBeamCollection &lasBeams,
1584  const TsosVectorCollection &lasBeamTsoses)
1585 {
1586  TsosVectorCollection::const_iterator iTsoses = lasBeamTsoses.begin();
1587  for(TkFittedLasBeamCollection::const_iterator iBeam = lasBeams.begin(), iEnd = lasBeams.end();
1588  iBeam != iEnd; ++iBeam, ++iTsoses){ // beam/tsoses parallel!
1589 
1590  edm::LogInfo("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::addLaserData"
1591  << "Beam " << iBeam->getBeamId() << " with "
1592  << iBeam->parameters().size() << " parameters and "
1593  << iBeam->getData().size() << " hits.\n There are "
1594  << iTsoses->size() << " TSOSes.";
1595 
1596  this->addLasBeam(eventInfo, *iBeam, *iTsoses);
1597  }
1598 }
1599 
1600 //____________________________________________________
1602  const TkFittedLasBeam &lasBeam,
1603  const std::vector<TrajectoryStateOnSurface> &tsoses)
1604 {
1605  AlignmentParameters *dummyPtr = nullptr; // for globalDerivativesHierarchy()
1606  std::vector<float> lasLocalDerivsX; // buffer for local derivatives
1607  const unsigned int beamLabel = thePedeLabels->lasBeamLabel(lasBeam.getBeamId());// for global par
1608 
1609  for (unsigned int iHit = 0; iHit < tsoses.size(); ++iHit) {
1610  if (!tsoses[iHit].isValid()) continue;
1611  // clear buffer
1612  theFloatBufferX.clear();
1613  theFloatBufferY.clear();
1614  theIntBuffer.clear();
1615  lasLocalDerivsX.clear();
1616  // get alignables and global parameters
1617  const SiStripLaserRecHit2D &hit = lasBeam.getData()[iHit];
1618  AlignableDetOrUnitPtr lasAli(theAlignableNavigator->alignableFromDetId(hit.getDetId()));
1619  this->globalDerivativesHierarchy(eventInfo,
1620  tsoses[iHit], lasAli, lasAli,
1622  // fill derivatives vector from derivatives matrix
1623  for (unsigned int nFitParams = 0;
1624  nFitParams < static_cast<unsigned int>(lasBeam.parameters().size());
1625  ++nFitParams) {
1626  const float derivative = lasBeam.derivatives()[iHit][nFitParams];
1627  if (nFitParams < lasBeam.firstFixedParameter()) { // first local beam parameters
1628  lasLocalDerivsX.push_back(derivative);
1629  } else { // now global ones
1630  const unsigned int numPar = nFitParams - lasBeam.firstFixedParameter();
1631  theIntBuffer.push_back(thePedeLabels->parameterLabel(beamLabel, numPar));
1632  theFloatBufferX.push_back(derivative);
1633  }
1634  } // end loop over parameters
1635 
1636  const float residual = hit.localPosition().x() - tsoses[iHit].localPosition().x();
1637  // error from file or assume 0.003
1638  const float error = 0.003; // hit.localPositionError().xx(); sqrt???
1639 
1640  theMille->mille(lasLocalDerivsX.size(), &(lasLocalDerivsX[0]), theFloatBufferX.size(),
1641  &(theFloatBufferX[0]), &(theIntBuffer[0]), residual, error);
1642  } // end of loop over hits
1643 
1644  theMille->end();
1645 }
1646 
1648 {
1649  // do some printing, if requested
1650  const bool doOutputOnStdout(pxbSurveyCfg.getParameter<bool>("doOutputOnStdout"));
1651  if (doOutputOnStdout) {
1652  edm::LogInfo("Alignment")
1653  << "@SUB=MillePedeAlignmentAlgorithm::addPxbSurvey"
1654  << "# Output from addPxbSurvey follows below because "
1655  << "doOutputOnStdout is set to True";
1656  }
1657 
1658  // instantiate a dicer object
1659  SurveyPxbDicer dicer(pxbSurveyCfg.getParameter<std::vector<edm::ParameterSet> >("toySurveyParameters"), pxbSurveyCfg.getParameter<unsigned int>("toySurveySeed"));
1660  std::ofstream outfile(pxbSurveyCfg.getUntrackedParameter<std::string>("toySurveyFile").c_str());
1661 
1662  // read data from file
1663  std::vector<SurveyPxbImageLocalFit> measurements;
1664  std::string filename(pxbSurveyCfg.getParameter<edm::FileInPath>("infile").fullPath());
1666 
1667  // loop over photographs (=measurements) and perform the fit
1668  for(std::vector<SurveyPxbImageLocalFit>::size_type i=0; i!=measurements.size(); i++)
1669  {
1670  if (doOutputOnStdout) {
1671  edm::LogInfo("Alignment")
1672  << "@SUB=MillePedeAlignmentAlgorithm::addPxbSurvey"
1673  << "Module " << i << ": ";
1674  }
1675 
1676  // get the Alignables and their surfaces
1677  AlignableDetOrUnitPtr mod1(theAlignableNavigator->alignableFromDetId(measurements[i].getIdFirst()));
1678  AlignableDetOrUnitPtr mod2(theAlignableNavigator->alignableFromDetId(measurements[i].getIdSecond()));
1679  const AlignableSurface& surf1 = mod1->surface();
1680  const AlignableSurface& surf2 = mod2->surface();
1681 
1682  // the position of the fiducial points in local frame of a PXB module
1683  const LocalPoint fidpoint0(-0.91,+3.30);
1684  const LocalPoint fidpoint1(+0.91,+3.30);
1685  const LocalPoint fidpoint2(+0.91,-3.30);
1686  const LocalPoint fidpoint3(-0.91,-3.30);
1687 
1688  // We choose the local frame of the first module as reference,
1689  // so take the fidpoints of the second module and calculate their
1690  // positions in the reference frame
1691  const GlobalPoint surf2point0(surf2.toGlobal(fidpoint0));
1692  const GlobalPoint surf2point1(surf2.toGlobal(fidpoint1));
1693  const LocalPoint fidpoint0inSurf1frame(surf1.toLocal(surf2point0));
1694  const LocalPoint fidpoint1inSurf1frame(surf1.toLocal(surf2point1));
1695 
1696  // Create the vector for the fit
1698  fidpointvec.push_back(fidpoint0inSurf1frame);
1699  fidpointvec.push_back(fidpoint1inSurf1frame);
1700  fidpointvec.push_back(fidpoint2);
1701  fidpointvec.push_back(fidpoint3);
1702 
1703  // if toy survey is requested, dice the values now
1704  if (pxbSurveyCfg.getParameter<bool>("doToySurvey"))
1705  {
1706  dicer.doDice(fidpointvec,measurements[i].getIdPair(), outfile);
1707  }
1708 
1709  // do the fit
1710  measurements[i].doFit(fidpointvec, thePedeLabels->alignableLabel(mod1), thePedeLabels->alignableLabel(mod2));
1711  SurveyPxbImageLocalFit::localpars_t a; // local pars from fit
1712  a = measurements[i].getLocalParameters();
1713  const SurveyPxbImageLocalFit::value_t chi2 = measurements[i].getChi2();
1714 
1715  // do some reporting, if requested
1716  if (doOutputOnStdout)
1717  {
1718  edm::LogInfo("Alignment")
1719  << "@SUB=MillePedeAlignmentAlgorithm::addPxbSurvey"
1720  << "a: " << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3]
1721  << " S= " << sqrt(a[2]*a[2]+a[3]*a[3])
1722  << " phi= " << atan(a[3]/a[2])
1723  << " chi2= " << chi2 << std::endl;
1724  }
1725  if (theMonitor)
1726  {
1727  theMonitor->fillPxbSurveyHistsChi2(chi2);
1728  theMonitor->fillPxbSurveyHistsLocalPars(a[0],a[1],sqrt(a[2]*a[2]+a[3]*a[3]),atan(a[3]/a[2]));
1729  }
1730 
1731  // pass the results from the local fit to mille
1733  {
1734  theMille->mille((int)measurements[i].getLocalDerivsSize(),
1735  measurements[i].getLocalDerivsPtr(j),
1736  (int)measurements[i].getGlobalDerivsSize(),
1737  measurements[i].getGlobalDerivsPtr(j),
1738  measurements[i].getGlobalDerivsLabelPtr(j),
1739  measurements[i].getResiduum(j),
1740  measurements[i].getSigma(j));
1741  }
1742  theMille->end();
1743  }
1744  outfile.close();
1745 }
1746 
1747 
1749  const auto runRangeSelection =
1750  theConfig.getUntrackedParameter<edm::VParameterSet>("RunRangeSelection");
1751 
1752  if (runRangeSelection.empty()) return false;
1753 
1754  const auto runRanges =
1755  align::makeNonOverlappingRunRanges(runRangeSelection,
1756  cond::timeTypeSpecs[cond::runnumber].beginValue);
1757 
1758  return !(runRanges.empty());
1759 }
RunNumber_t run() const
Definition: EventID.h:39
bool processesEvents() override
Returns whether MP should process events in the current configuration.
unsigned int hitsX() const
get number of hits for x-measurement
const TimeTypeSpecs timeTypeSpecs[]
Definition: Time.cc:22
T getParameter(std::string const &) const
unsigned int firstFixedParameter() const
void globalDerivativesCalibration(const TransientTrackingRecHit::ConstRecHitPointer &recHit, const TrajectoryStateOnSurface &tsos, const edm::EventSetup &setup, const EventInfo &eventInfo, std::vector< float > &globalDerivativesX, std::vector< float > &globalDerivativesY, std::vector< int > &globalLabels) const
adding derivatives from integrated calibrations
T getUntrackedParameter(std::string const &, T const &) const
std::vector< AlignmentUserVariables * > readMillePedeVariables(const std::vector< Alignable * > &alivec, const char *filename, int iter, int &ierr)
unsigned int size() const
number of parameters
void resetParameters(void)
reset parameters, correlations, user variables
bool supportsCalibrations() override
Returns whether MP supports calibrations.
std::unique_ptr< MillePedeMonitor > theMonitor
void increaseHitsX(unsigned int add=1)
increase hits for x-measurement
bool read(std::vector< Alignable * > &alignables, bool setUserVars)
Definition: PedeReader.cc:54
bool setParametersForRunRange(const RunRange &runrange) override
RunNumber_t run() const
Definition: RunBase.h:40
Derivative< X, A >::type derivative(const A &_)
Definition: Derivative.h:18
virtual void endRun(const EventInfo &, const EndRunInfo &, const edm::EventSetup &)
Run on run products, e.g. TkLAS.
std::vector< coord_t > fidpoint_t
std::shared_ptr< AlignPCLThresholds > theThresholds
void diagonalize(Eigen::MatrixBase< CovarianceMatrix > &aHitCovarianceM, Eigen::MatrixBase< LocalDerivativeMatrix > &aLocalDerivativesM, Eigen::MatrixBase< ResidualMatrix > &aHitResidualsM, Eigen::MatrixBase< GlobalDerivativeMatrix > &aGlobalDerivativesM) const
const EventID & eventID() const
Definition: IOVSyncValue.h:42
double Scalar
Definition: Definitions.h:27
void increaseHitsY(unsigned int add=1)
increase hits for y-measurement
Time_t beginValue
Definition: Time.h:45
std::vector< Alignable * > theAlignables
void endLuminosityBlock(const edm::EventSetup &) override
called at end of luminosity block
TrajectoryFactoryBase::ReferenceTrajectoryCollection RefTrajColl
std::vector< ParameterSet > VParameterSet
Definition: ParameterSet.h:33
std::unique_ptr< TrajectoryFactoryBase > theTrajectoryFactory
void writeAlignableOriginalPositions(const align::Alignables &alivec, const char *filename, int iter, bool validCheck, int &ierr)
write Alignable original (before misalignment) absolute positions
std::unique_ptr< gbl::MilleBinary > theBinary
const Time_t MIN_VAL(0)
int addGlobalData(const edm::EventSetup &setup, const EventInfo &eventInfo, const ReferenceTrajectoryBase::ReferenceTrajectoryPtr &refTrajPtr, unsigned int iHit, gbl::GblPoint &gblPoint)
bool exists(std::string const &parameterName) const
checks if a parameter exists
bool globalDerivativesHierarchy(const EventInfo &eventInfo, const TrajectoryStateOnSurface &tsos, Alignable *ali, const AlignableDetOrUnitPtr &alidet, std::vector< float > &globalDerivativesX, std::vector< float > &globalDerivativesY, std::vector< int > &globalLabels, AlignmentParameters *&lowestParams) const
recursively adding derivatives and labels, false if problems
def setup(process, global_tag, zero_tesla=False)
Definition: GeneralSetup.py:1
void restoreCachedTransformations(void)
restore the previously cached position, rotation and other parameters
std::shared_ptr< PedeLabelerBase > thePedeLabels
void applyParameters(void)
Obsolete: Use AlignableNavigator::alignableDetFromDetId and alignableFromAlignableDet.
std::vector< std::string > getExistingFormattedFiles(const std::vector< std::string > &plainFiles, const std::string &theDir)
unsigned int addHitCount(const std::vector< AlignmentParameters * > &parVec, const std::vector< bool > &validHitVecY) const
bool addCalibrations(const std::vector< IntegratedCalibrationBase * > &iCals) override
Pass integrated calibrations to Millepede (they are not owned by Millepede!)
const AlgebraicMatrix & derivatives() const
matrix of local derivatives: columns are parameters, rows are hits
const std::vector< bool > & selector(void) const
Get alignment parameter selector vector.
int callMille2D(const ReferenceTrajectoryBase::ReferenceTrajectoryPtr &refTrajPtr, unsigned int iTrajHit, const std::vector< int > &globalLabels, const std::vector< float > &globalDerivativesx, const std::vector< float > &globalDerivativesy)
math::Error< 5 >::type CovarianceMatrix
#define nullptr
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:20
uint16_t size_type
void addLasBeam(const EventInfo &eventInfo, const TkFittedLasBeam &lasBeam, const std::vector< TrajectoryStateOnSurface > &tsoses)
AlignmentParameters * alignmentParameters() const
Get the AlignmentParameters.
Definition: Alignable.h:61
const ConstTrajTrackPairCollection & trajTrackPairs() const
define event information passed to algorithms
unsigned int doIO(int loop) const
int callMille(const ReferenceTrajectoryBase::ReferenceTrajectoryPtr &refTrajPtr, unsigned int iTrajHit, const std::vector< int > &globalLabels, const std::vector< float > &globalDerivativesX, const std::vector< float > &globalDerivativesY)
calls callMille1D or callMille2D
TransientTrackingRecHit::ConstRecHitPointer ConstRecHitPointer
U second(std::pair< T, U > const &p)
const AlgebraicVector & parameters(void) const
Get alignment parameters.
void beginLuminosityBlock(const edm::EventSetup &) override
called at begin of luminosity block (resets Mille binary in mille mode)
std::vector< align::RunNumber > cachedRuns_
std::string doDice(const fidpoint_t &fidpointvec, const idPair_t &id, const bool rotate=false)
AlignmentUserVariables * userVariables(void) const
Get pointer to user variables.
int callMille1D(const ReferenceTrajectoryBase::ReferenceTrajectoryPtr &refTrajPtr, unsigned int iTrajHit, const std::vector< int > &globalLabels, const std::vector< float > &globalDerivativesX)
calls Mille for 1D hits
void addLaserData(const EventInfo &eventInfo, const TkFittedLasBeamCollection &tkLasBeams, const TsosVectorCollection &tkLasBeamTsoses)
int addMeasurementData(const edm::EventSetup &setup, const EventInfo &eventInfo, const ReferenceTrajectoryBase::ReferenceTrajectoryPtr &refTrajPtr, unsigned int iHit, AlignmentParameters *&params)
bool isMode(unsigned int testMode) const
void beginRun(const edm::Run &run, const edm::EventSetup &setup, bool changed) override
called at begin of run
align::RotationType toLocal(const align::RotationType &) const
Return in local frame a rotation given in global frame.
CLHEP::HepMatrix AlgebraicMatrix
const std::vector< Scalar > & parameters() const
parallel to derivatives()
RunRanges makeNonOverlappingRunRanges(const edm::VParameterSet &runRanges, const RunNumber &defaultRun)
Definition: Utilities.cc:218
void makeGlobDerivMatrix(const std::vector< float > &globalDerivativesx, const std::vector< float > &globalDerivativesy, Eigen::MatrixBase< GlobalDerivativeMatrix > &aGlobalDerivativesM)
std::shared_ptr< TrackingRecHit const > ConstRecHitPointer
void swap(edm::DataFrameContainer &lhs, edm::DataFrameContainer &rhs)
T sqrt(T t)
Definition: SSEVec.h:18
RunRanges makeUniqueRunRanges(const edm::VParameterSet &runRanges, const RunNumber &defaultRun)
Definition: Utilities.cc:263
unsigned int getBeamId(void) const
return the full beam identifier
Definition: TkLasBeam.h:25
AlignmentParameterStore * theAlignmentParameterStore
directory for all kind of files
unsigned int hitsY() const
get number of hits for y-measurement
T Abs(T a)
Definition: MathUtil.h:49
bool is2D(const TransientTrackingRecHit::ConstRecHitPointer &recHit) const
true if hit belongs to 2D detector (currently tracker specific)
void addRefTrackVirtualMeas1D(const ReferenceTrajectoryBase::ReferenceTrajectoryPtr &refTrajPtr, unsigned int iVirtualMeas, Eigen::MatrixBase< CovarianceMatrix > &aHitCovarianceM, Eigen::MatrixBase< ResidualMatrix > &aHitResidualsM, Eigen::MatrixBase< LocalDerivativeMatrix > &aLocalDerivativesM)
adds data for a specific virtual measurement from reference trajectory
void addRefTrackData2D(const ReferenceTrajectoryBase::ReferenceTrajectoryPtr &refTrajPtr, unsigned int iTrajHit, Eigen::MatrixBase< CovarianceMatrix > &aHitCovarianceM, Eigen::MatrixBase< ResidualMatrix > &aHitResidualsM, Eigen::MatrixBase< LocalDerivativeMatrix > &aLocalDerivativesM)
adds data from reference trajectory from a specific Hit
const TkFittedLasBeamCollection * tkLasBeams() const
Definition: value.py:1
std::unique_ptr< PedeSteerer > thePedeSteer
bool storeAlignments() override
Returns whether MP produced results to be stored.
void terminate() override
Called at end of job.
void initialize(const edm::EventSetup &setup, AlignableTracker *tracker, AlignableMuon *muon, AlignableExtras *extras, AlignmentParameterStore *store) override
Called at beginning of job.
const AlignableSurface & surface() const
Return the Surface (global position and orientation) of the object.
Definition: Alignable.h:135
JetCorrectorParameters corr
Definition: classes.h:5
bool addHits(const std::vector< Alignable * > &alis, const std::vector< AlignmentUserVariables * > &mpVars) const
std::vector< ConstRecHitPointer > ConstRecHitContainer
void writeMillePedeVariables(const std::vector< Alignable * > &alivec, const char *filename, int iter, bool validCheck, int &ierr)
bool addHitStatistics(int fromLoop, const std::string &outFile, const std::vector< std::string > &inFiles) const
bool areEmptyParams(const std::vector< Alignable * > &alignables) const
void addVirtualMeas(const ReferenceTrajectoryBase::ReferenceTrajectoryPtr &refTrajPtr, unsigned int iVirtualMeas)
adds data for virtual measurements from reference trajectory
bool readFromPede(const edm::ParameterSet &mprespset, bool setUserVars, const RunRange &runrange)
read pede input defined by &#39;psetName&#39;, flag to create/not create MillePedeVariables ...
std::pair< unsigned int, unsigned int > addReferenceTrajectory(const edm::EventSetup &setup, const EventInfo &eventInfo, const ReferenceTrajectoryBase::ReferenceTrajectoryPtr &refTrajPtr)
fill mille for a trajectory, returning number of x/y hits ([0,0] if &#39;bad&#39; trajectory) ...
std::vector< ReferenceTrajectoryPtr > ReferenceTrajectoryCollection
const SiStripDetId & getDetId(void) const
virtual bool storeThresholds(const int &nRecords, const AlignPCLThresholds::threshold_map &thresholdMap)
void setUserVariables(AlignmentUserVariables *auv)
Set pointer to user variables.
std::vector< IntegratedCalibrationBase * > theCalibrations
int size(void) const
Get number of parameters.
void addUntrackedParameter(std::string const &name, T const &value)
Definition: ParameterSet.h:208
Class to hold one picture of the BPix survey.
const T & get() const
Definition: EventSetup.h:55
std::vector< value_t > localpars_t
std::map< std::string, AlignPCLThreshold > threshold_map
void run(const edm::EventSetup &setup, const EventInfo &eventInfo) override
Run the algorithm on trajectories and tracks.
void buildUserVariables(const std::vector< Alignable * > &alignables) const
add MillePedeVariables for each AlignmentParameters (exception if no parameters...)
LocalPoint localPosition() const override
MillePedeAlignmentAlgorithm(const edm::ParameterSet &cfg)
Constructor.
Definition: plugin.cc:24
HLT enums.
~MillePedeAlignmentAlgorithm() override
Destructor.
std::vector< TkFittedLasBeam > TkFittedLasBeamCollection
double a
Definition: hdecay.h:121
const reco::BeamSpot & beamSpot() const
align::GlobalPoints toGlobal(const align::LocalPoints &) const
Return in global coord given a set of local points.
void cacheTransformations(void)
cache the current position, rotation and other parameters
TransientTrackingRecHit::ConstRecHitContainer ConstRecHitContainer
std::string fullPath() const
Definition: FileInPath.cc:184
firstRun
Definition: dataset.py:933
static const count_t nMsrmts
void writeAlignableAbsolutePositions(const align::Alignables &alivec, const char *filename, int iter, bool validCheck, int &ierr)
write Alignable current absolute positions
eventInfo
add run, event number and lumi section
void addPxbSurvey(const edm::ParameterSet &pxbSurveyCfg)
add measurement data from PXB survey
const IOVSyncValue & first() const
unsigned int decodeMode(const std::string &mode) const
std::unique_ptr< AlignableNavigator > theAlignableNavigator
Time_t endValue
Definition: Time.h:46
const std::vector< SiStripLaserRecHit2D > & getData(void) const
access the collection of hits
Definition: TkLasBeam.h:28
void writeOrigRigidBodyAlignmentParameters(const align::Alignables &alivec, const char *filename, int iter, bool validCheck, int &ierr)
write RigidBodyAlignmentParameters as applied on top of original positions
std::vector< std::vector< TrajectoryStateOnSurface > > TsosVectorCollection
define run information passed to algorithms (in endRun)
const TsosVectorCollection * tkLasBeamTsoses() const
might be null!
const AlgebraicSymMatrix & covariance(void) const
Get parameter covariance matrix.
Constructor of the full muon geometry.
Definition: AlignableMuon.h:37
uint32_t dimension(pat::CandKinResolution::Parametrization parametrization)
Returns the number of free parameters in a parametrization (3 or 4)
ValidityInterval const & validityInterval() const
virtual AlgebraicMatrix derivatives(const TrajectoryStateOnSurface &tsos, const AlignableDetOrUnitPtr &alidet) const =0
Get derivatives of selected parameters.
T const * product() const
Definition: ESHandle.h:86
Alignable * mother() const
Return pointer to container alignable (if any)
Definition: Alignable.h:94
const Time_t MAX_VAL(std::numeric_limits< Time_t >::max())
void throwException(const std::string &message, const std::string &methodName)
Definition: Exception.cc:14
T get(const Candidate &c)
Definition: component.h:55
bool setAllDefault(unsigned int nParam)
set default values for all data concerning nParam (false if nParam out of range)
Definition: Run.h:43