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  align::Alignables 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 //__________________________________________________________________________________________________
1099 {
1100 
1101  for (const auto& iAli: alignables) {
1102  const AlignmentParameters *params = iAli->alignmentParameters();
1103  if (params) {
1104  const auto& parVec(params->parameters());
1105  const auto& parCov(params->covariance());
1106  for (int i = 0; i < parVec.num_row(); ++i) {
1107  if (parVec[i] != 0.) return false;
1108  for (int j = i; j < parCov.num_col(); ++j) {
1109  if (parCov[i][j] != 0.) return false;
1110  }
1111  }
1112  }
1113  }
1114 
1115  return true;
1116 }
1117 
1118 //__________________________________________________________________________________________________
1120 {
1121  unsigned int result = 0;
1122 
1123  const std::string outFilePlain(theConfig.getParameter<std::string>("treeFile"));
1124  if (outFilePlain.empty()) {
1125  edm::LogInfo("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::doIO"
1126  << "treeFile parameter empty => skip writing for 'loop' " << loop;
1127  return result;
1128  }
1129 
1130  const std::string outFile(theDir + outFilePlain);
1131 
1132  AlignmentIORoot aliIO;
1133  int ioerr = 0;
1134  if (loop == 0) {
1135  aliIO.writeAlignableOriginalPositions(theAlignables, outFile.c_str(), loop, false, ioerr);
1136  if (ioerr) {
1137  edm::LogError("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::doIO"
1138  << "Problem " << ioerr << " in writeAlignableOriginalPositions";
1139  ++result;
1140  }
1141  } else if (loop == 1) {
1142  // only for first iov add hit counts, else 2x, 3x,... number of hits in IOV 2, 3,...
1143  const std::vector<std::string> inFiles
1144  (theConfig.getParameter<std::vector<std::string> >("mergeTreeFiles"));
1145  const std::vector<std::string> binFiles
1146  (theConfig.getParameter<std::vector<std::string> >("mergeBinaryFiles"));
1147  if (inFiles.size() != binFiles.size()) {
1148  edm::LogWarning("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::doIO"
1149  << "'vstring mergeTreeFiles' and 'vstring mergeBinaryFiles' "
1150  << "differ in size";
1151  }
1152  this->addHitStatistics(0, outFile, inFiles); // add hit info from tree 0 in 'infiles'
1153  }
1154  MillePedeVariablesIORoot millePedeIO;
1155  millePedeIO.writeMillePedeVariables(theAlignables, outFile.c_str(), loop, false, ioerr);
1156  if (ioerr) {
1157  edm::LogError("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::doIO"
1158  << "Problem " << ioerr << " writing MillePedeVariables";
1159  ++result;
1160  }
1161 
1162  aliIO.writeOrigRigidBodyAlignmentParameters(theAlignables, outFile.c_str(), loop, false, ioerr);
1163  if (ioerr) {
1164  edm::LogError("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::doIO" << "Problem " << ioerr
1165  << " in writeOrigRigidBodyAlignmentParameters, " << loop;
1166  ++result;
1167  }
1168  aliIO.writeAlignableAbsolutePositions(theAlignables, outFile.c_str(), loop, false, ioerr);
1169  if (ioerr) {
1170  edm::LogError("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::doIO" << "Problem " << ioerr
1171  << " in writeAlignableAbsolutePositions, " << loop;
1172  ++result;
1173  }
1174 
1175  return result;
1176 }
1177 
1178 //__________________________________________________________________________________________________
1180 {
1181  for (const auto& iAli: alis) {
1182  AlignmentParameters *params = iAli->alignmentParameters();
1183  if (!params) {
1184  throw cms::Exception("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::buildUserVariables"
1185  << "No parameters for alignable";
1186  }
1187  MillePedeVariables *userVars = dynamic_cast<MillePedeVariables*>(params->userVariables());
1188  if (userVars) { // Just re-use existing, keeping label and numHits:
1189  for (unsigned int iPar = 0; iPar < userVars->size(); ++iPar) {
1190  // if (params->hierarchyLevel() > 0) {
1191  //std::cout << params->hierarchyLevel() << "\nBefore: " << userVars->parameter()[iPar];
1192  // }
1193  userVars->setAllDefault(iPar);
1194  //std::cout << "\nAfter: " << userVars->parameter()[iPar] << std::endl;
1195  }
1196  } else { // Nothing yet or erase wrong type:
1197  userVars = new MillePedeVariables(params->size(), thePedeLabels->alignableLabel(iAli),
1198  thePedeLabels->alignableTracker()->objectIdProvider().typeToName(iAli->alignableObjectId()));
1199  params->setUserVariables(userVars);
1200  }
1201  }
1202 }
1203 
1204 //__________________________________________________________________________________________________
1206 {
1207  if (mode == "full") {
1209  } else if (mode == "mille") {
1210  return myMilleBit; // + myPedeSteerBit; // sic! Including production of steerig file. NO!
1211  } else if (mode == "pede") {
1213  } else if (mode == "pedeSteer") {
1214  return myPedeSteerBit;
1215  } else if (mode == "pedeRun") {
1216  return myPedeSteerBit + myPedeRunBit + myPedeReadBit; // sic! Including steering and reading of result.
1217  } else if (mode == "pedeRead") {
1218  return myPedeReadBit;
1219  }
1220 
1221  throw cms::Exception("BadConfig")
1222  << "Unknown mode '" << mode
1223  << "', use 'full', 'mille', 'pede', 'pedeRun', 'pedeSteer' or 'pedeRead'.";
1224 
1225  return 0;
1226 }
1227 
1228 //__________________________________________________________________________________________________
1230  const std::vector<std::string> &inFiles) const
1231 {
1232  bool allOk = true;
1233  int ierr = 0;
1234  MillePedeVariablesIORoot millePedeIO;
1235  for (std::vector<std::string>::const_iterator iFile = inFiles.begin();
1236  iFile != inFiles.end(); ++iFile) {
1237  const std::string inFile(theDir + *iFile);
1238  const std::vector<AlignmentUserVariables*> mpVars =
1239  millePedeIO.readMillePedeVariables(theAlignables, inFile.c_str(), fromIov, ierr);
1240  if (ierr || !this->addHits(theAlignables, mpVars)) {
1241  edm::LogError("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::addHitStatistics"
1242  << "Error " << ierr << " reading from " << inFile
1243  << ", tree " << fromIov << ", or problems in addHits";
1244  allOk = false;
1245  }
1246  for (std::vector<AlignmentUserVariables*>::const_iterator i = mpVars.begin();
1247  i != mpVars.end(); ++i) {
1248  delete *i; // clean created objects
1249  }
1250  }
1251 
1252  return allOk;
1253 }
1254 
1255 //__________________________________________________________________________________________________
1257  const std::vector<AlignmentUserVariables*> &mpVars) const
1258 {
1259  bool allOk = (mpVars.size() == alis.size());
1260  std::vector<AlignmentUserVariables*>::const_iterator iUser = mpVars.begin();
1261  for (auto iAli = alis.cbegin(); iAli != alis.cend() && iUser != mpVars.end(); ++iAli, ++iUser) {
1262  MillePedeVariables *mpVarNew = dynamic_cast<MillePedeVariables*>(*iUser);
1263  AlignmentParameters *ps = (*iAli)->alignmentParameters();
1264  MillePedeVariables *mpVarOld = (ps ? dynamic_cast<MillePedeVariables*>(ps->userVariables()) : nullptr);
1265  if (!mpVarNew || !mpVarOld || mpVarOld->size() != mpVarNew->size()) {
1266  allOk = false;
1267  continue; // FIXME error etc.?
1268  }
1269 
1270  mpVarOld->increaseHitsX(mpVarNew->hitsX());
1271  mpVarOld->increaseHitsY(mpVarNew->hitsY());
1272  }
1273 
1274  return allOk;
1275 }
1276 
1277 //__________________________________________________________________________________________________
1278 template <typename GlobalDerivativeMatrix>
1279 void MillePedeAlignmentAlgorithm::makeGlobDerivMatrix(const std::vector<float> &globalDerivativesx,
1280  const std::vector<float> &globalDerivativesy,
1281  Eigen::MatrixBase<GlobalDerivativeMatrix>& aGlobalDerivativesM)
1282 {
1283  static_assert(GlobalDerivativeMatrix::RowsAtCompileTime == 2,
1284  "global derivative matrix must have two rows");
1285 
1286  for (size_t i = 0; i < globalDerivativesx.size(); ++i) {
1287  aGlobalDerivativesM(0,i) = globalDerivativesx[i];
1288  aGlobalDerivativesM(1,i) = globalDerivativesy[i];
1289  }
1290 }
1291 
1292 //__________________________________________________________________________________________________
1293 template <typename CovarianceMatrix,
1294  typename LocalDerivativeMatrix,
1295  typename ResidualMatrix,
1296  typename GlobalDerivativeMatrix>
1298 (Eigen::MatrixBase<CovarianceMatrix>& aHitCovarianceM,
1299  Eigen::MatrixBase<LocalDerivativeMatrix>& aLocalDerivativesM,
1300  Eigen::MatrixBase<ResidualMatrix>& aHitResidualsM,
1301  Eigen::MatrixBase<GlobalDerivativeMatrix>& aGlobalDerivativesM) const
1302 {
1303  static_assert(std::is_same<typename LocalDerivativeMatrix::Scalar,
1304  typename ResidualMatrix::Scalar>::value,
1305  "'aLocalDerivativesM' and 'aHitResidualsM' must have the "
1306  "same underlying scalar type");
1307  static_assert(std::is_same<typename LocalDerivativeMatrix::Scalar,
1309  "'aLocalDerivativesM' and 'aGlobalDerivativesM' must have the "
1310  "same underlying scalar type");
1311 
1312  Eigen::SelfAdjointEigenSolver<typename CovarianceMatrix::PlainObject> myDiag{aHitCovarianceM};
1313  // eigenvectors of real symmetric matrices are orthogonal, i.e. invert == transpose
1314  auto aTranfoToDiagonalSystemInv =
1315  myDiag.eigenvectors().transpose().template cast<typename LocalDerivativeMatrix::Scalar>();
1316 
1317  aHitCovarianceM = myDiag.eigenvalues().asDiagonal();
1318  aLocalDerivativesM = aTranfoToDiagonalSystemInv * aLocalDerivativesM;
1319  aHitResidualsM = aTranfoToDiagonalSystemInv * aHitResidualsM;
1320  if (aGlobalDerivativesM.size() > 0) {
1321  // diagonalize only if measurement depends on alignables or calibrations
1322  aGlobalDerivativesM = aTranfoToDiagonalSystemInv * aGlobalDerivativesM;
1323  }
1324 }
1325 
1326 //__________________________________________________________________________________________________
1327 template <typename CovarianceMatrix,
1328  typename ResidualMatrix,
1329  typename LocalDerivativeMatrix>
1332  unsigned int iVirtualMeas,
1333  Eigen::MatrixBase<CovarianceMatrix>& aHitCovarianceM,
1334  Eigen::MatrixBase<ResidualMatrix>& aHitResidualsM,
1335  Eigen::MatrixBase<LocalDerivativeMatrix>& aLocalDerivativesM)
1336 {
1337  // This Method is valid for 1D measurements only
1338 
1339  const unsigned int xIndex = iVirtualMeas + refTrajPtr->numberOfHitMeas();
1340 
1341  aHitCovarianceM(0,0)=refTrajPtr->measurementErrors()[xIndex][xIndex];
1342  aHitResidualsM(0,0)= refTrajPtr->measurements()[xIndex];
1343 
1344  const auto& locDerivMatrix = refTrajPtr->derivatives();
1345  for (int i = 0; i < locDerivMatrix.num_col(); ++i) {
1346  aLocalDerivativesM(0,i) = locDerivMatrix[xIndex][i];
1347  }
1348 }
1349 
1350 //__________________________________________________________________________________________________
1351 template <typename CovarianceMatrix,
1352  typename ResidualMatrix,
1353  typename LocalDerivativeMatrix>
1356  unsigned int iTrajHit,
1357  Eigen::MatrixBase<CovarianceMatrix>& aHitCovarianceM,
1358  Eigen::MatrixBase<ResidualMatrix>& aHitResidualsM,
1359  Eigen::MatrixBase<LocalDerivativeMatrix>& aLocalDerivativesM)
1360 {
1361  // This Method is valid for 2D measurements only
1362 
1363  const unsigned int xIndex = iTrajHit*2;
1364  const unsigned int yIndex = iTrajHit*2+1;
1365 
1366  aHitCovarianceM(0,0)=refTrajPtr->measurementErrors()[xIndex][xIndex];
1367  aHitCovarianceM(0,1)=refTrajPtr->measurementErrors()[xIndex][yIndex];
1368  aHitCovarianceM(1,0)=refTrajPtr->measurementErrors()[yIndex][xIndex];
1369  aHitCovarianceM(1,1)=refTrajPtr->measurementErrors()[yIndex][yIndex];
1370 
1371  aHitResidualsM(0,0)= refTrajPtr->measurements()[xIndex] - refTrajPtr->trajectoryPositions()[xIndex];
1372  aHitResidualsM(1,0)= refTrajPtr->measurements()[yIndex] - refTrajPtr->trajectoryPositions()[yIndex];
1373 
1374  const auto& locDerivMatrix = refTrajPtr->derivatives();
1375  for (int i = 0; i < locDerivMatrix.num_col(); ++i) {
1376  aLocalDerivativesM(0,i) = locDerivMatrix[xIndex][i];
1377  aLocalDerivativesM(1,i) = locDerivMatrix[yIndex][i];
1378  }
1379 }
1380 
1381 //__________________________________________________________________________________________________
1384  unsigned int iTrajHit, const std::vector<int> &globalLabels,
1385  const std::vector<float> &globalDerivativesX,
1386  const std::vector<float> &globalDerivativesY)
1387 {
1388  const ConstRecHitPointer aRecHit(refTrajPtr->recHits()[iTrajHit]);
1389 
1390  if((aRecHit)->dimension() == 1) {
1391  return this->callMille1D(refTrajPtr, iTrajHit, globalLabels, globalDerivativesX);
1392  } else {
1393  return this->callMille2D(refTrajPtr, iTrajHit, globalLabels,
1394  globalDerivativesX, globalDerivativesY);
1395  }
1396 }
1397 
1398 
1399 //__________________________________________________________________________________________________
1402  unsigned int iTrajHit, const std::vector<int> &globalLabels,
1403  const std::vector<float> &globalDerivativesX)
1404 {
1405  const ConstRecHitPointer aRecHit(refTrajPtr->recHits()[iTrajHit]);
1406  const unsigned int xIndex = iTrajHit*2; // the even ones are local x
1407 
1408  // local derivatives
1409  const AlgebraicMatrix &locDerivMatrix = refTrajPtr->derivatives();
1410  const int nLocal = locDerivMatrix.num_col();
1411  std::vector<float> localDerivatives(nLocal);
1412  for (unsigned int i = 0; i < localDerivatives.size(); ++i) {
1413  localDerivatives[i] = locDerivMatrix[xIndex][i];
1414  }
1415 
1416  // residuum and error
1417  float residX = refTrajPtr->measurements()[xIndex] - refTrajPtr->trajectoryPositions()[xIndex];
1418  float hitErrX = TMath::Sqrt(refTrajPtr->measurementErrors()[xIndex][xIndex]);
1419 
1420  // number of global derivatives
1421  const int nGlobal = globalDerivativesX.size();
1422 
1423  // &(localDerivatives[0]) etc. are valid - as long as vector is not empty
1424  // cf. http://www.parashift.com/c++-faq-lite/containers.html#faq-34.3
1425  theMille->mille(nLocal, &(localDerivatives[0]), nGlobal, &(globalDerivativesX[0]),
1426  &(globalLabels[0]), residX, hitErrX);
1427 
1428  if (theMonitor) {
1429  theMonitor->fillDerivatives(aRecHit, &(localDerivatives[0]), nLocal,
1430  &(globalDerivativesX[0]), nGlobal, &(globalLabels[0]));
1431  theMonitor->fillResiduals(aRecHit, refTrajPtr->trajectoryStates()[iTrajHit],
1432  iTrajHit, residX, hitErrX, false);
1433  }
1434 
1435  return 1;
1436 }
1437 
1438 //__________________________________________________________________________________________________
1441  unsigned int iTrajHit, const std::vector<int> &globalLabels,
1442  const std::vector<float> &globalDerivativesx,
1443  const std::vector<float> &globalDerivativesy)
1444 {
1445  const ConstRecHitPointer aRecHit(refTrajPtr->recHits()[iTrajHit]);
1446 
1447  if((aRecHit)->dimension() != 2) {
1448  edm::LogError("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::callMille2D"
1449  << "You try to call method for 2D hits for a "
1450  << (aRecHit)->dimension()
1451  << "D Hit. Hit gets ignored!";
1452  return -1;
1453  }
1454 
1455  Eigen::Matrix<double, 2, 2> aHitCovarianceM;
1456  Eigen::Matrix<float, 2, 1> aHitResidualsM;
1457  Eigen::Matrix<float, 2, Eigen::Dynamic>
1458  aLocalDerivativesM{2, refTrajPtr->derivatives().num_col()};
1459  // below method fills above 3 matrices
1460  this->addRefTrackData2D(refTrajPtr, iTrajHit, aHitCovarianceM,aHitResidualsM,aLocalDerivativesM);
1461  Eigen::Matrix<float, 2, Eigen::Dynamic>
1462  aGlobalDerivativesM{2, globalDerivativesx.size()};
1463  this->makeGlobDerivMatrix(globalDerivativesx, globalDerivativesy, aGlobalDerivativesM);
1464 
1465  // calculates correlation between Hit measurements
1466  // FIXME: Should take correlation (and resulting transformation) from original hit,
1467  // not 2x2 matrix from ReferenceTrajectory: That can come from error propagation etc.!
1468  const double corr = aHitCovarianceM(0,1) / sqrt(aHitCovarianceM(0,0) * aHitCovarianceM(1,1));
1469  if (theMonitor) theMonitor->fillCorrelations2D(corr, aRecHit);
1470  bool diag = false; // diagonalise only tracker TID, TEC
1471  switch(aRecHit->geographicalId().subdetId()) {
1472  case SiStripDetId::TID:
1473  case SiStripDetId::TEC:
1474  if (aRecHit->geographicalId().det() == DetId::Tracker && TMath::Abs(corr) > theMaximalCor2D) {
1475  this->diagonalize(aHitCovarianceM, aLocalDerivativesM, aHitResidualsM, aGlobalDerivativesM);
1476  diag = true;
1477  }
1478  break;
1479  default:;
1480  }
1481 
1482  float newResidX = aHitResidualsM(0,0);
1483  float newResidY = aHitResidualsM(1,0);
1484  float newHitErrX = TMath::Sqrt(aHitCovarianceM(0,0));
1485  float newHitErrY = TMath::Sqrt(aHitCovarianceM(1,1));
1486 
1487  // change from column major (Eigen default) to row major to have row entries
1488  // in continuous memory
1489  std::vector<float> newLocalDerivs(aLocalDerivativesM.size());
1490  Eigen::Map<Eigen::Matrix<float, 2, Eigen::Dynamic, Eigen::RowMajor> >
1491  (newLocalDerivs.data(),
1492  aLocalDerivativesM.rows(),
1493  aLocalDerivativesM.cols()) = aLocalDerivativesM;
1494  float* newLocalDerivsX = &(newLocalDerivs[0]);
1495  float* newLocalDerivsY = &(newLocalDerivs[aLocalDerivativesM.cols()]);
1496 
1497  // change from column major (Eigen default) to row major to have row entries
1498  // in continuous memory
1499  std::vector<float> newGlobDerivs(aGlobalDerivativesM.size());
1500  Eigen::Map<Eigen::Matrix<float, 2, Eigen::Dynamic, Eigen::RowMajor> >
1501  (newGlobDerivs.data(),
1502  aGlobalDerivativesM.rows(),
1503  aGlobalDerivativesM.cols()) = aGlobalDerivativesM;
1504  float* newGlobDerivsX = &(newGlobDerivs[0]);
1505  float* newGlobDerivsY = &(newGlobDerivs[aGlobalDerivativesM.cols()]);
1506 
1507  const int nLocal = aLocalDerivativesM.cols();
1508  const int nGlobal = aGlobalDerivativesM.cols();
1509 
1510  if (diag && (newHitErrX > newHitErrY)) { // also for 2D hits?
1511  // measurement with smaller error is x-measurement (for !is2D do not fill y-measurement):
1512  std::swap(newResidX, newResidY);
1513  std::swap(newHitErrX, newHitErrY);
1514  std::swap(newLocalDerivsX, newLocalDerivsY);
1515  std::swap(newGlobDerivsX, newGlobDerivsY);
1516  }
1517 
1518  // &(globalLabels[0]) is valid - as long as vector is not empty
1519  // cf. http://www.parashift.com/c++-faq-lite/containers.html#faq-34.3
1520  theMille->mille(nLocal, newLocalDerivsX, nGlobal, newGlobDerivsX,
1521  &(globalLabels[0]), newResidX, newHitErrX);
1522 
1523  if (theMonitor) {
1524  theMonitor->fillDerivatives(aRecHit, newLocalDerivsX, nLocal, newGlobDerivsX,
1525  nGlobal, &(globalLabels[0]));
1526  theMonitor->fillResiduals(aRecHit, refTrajPtr->trajectoryStates()[iTrajHit],
1527  iTrajHit, newResidX, newHitErrX, false);
1528  }
1529  const bool isReal2DHit = this->is2D(aRecHit); // strip is 1D (except matched hits)
1530  if (isReal2DHit) {
1531  theMille->mille(nLocal, newLocalDerivsY, nGlobal, newGlobDerivsY,
1532  &(globalLabels[0]), newResidY, newHitErrY);
1533  if (theMonitor) {
1534  theMonitor->fillDerivatives(aRecHit, newLocalDerivsY, nLocal, newGlobDerivsY,
1535  nGlobal, &(globalLabels[0]));
1536  theMonitor->fillResiduals(aRecHit, refTrajPtr->trajectoryStates()[iTrajHit],
1537  iTrajHit, newResidY, newHitErrY, true);// true: y
1538  }
1539  }
1540 
1541  return (isReal2DHit ? 2 : 1);
1542 }
1543 
1544 //__________________________________________________________________________________________________
1546 ::addVirtualMeas(const ReferenceTrajectoryBase::ReferenceTrajectoryPtr &refTrajPtr, unsigned int iVirtualMeas)
1547 {
1548  Eigen::Matrix<double, 1, 1> aHitCovarianceM;
1549  Eigen::Matrix<float, 1, 1> aHitResidualsM;
1550  Eigen::Matrix<float, 1, Eigen::Dynamic>
1551  aLocalDerivativesM{1, refTrajPtr->derivatives().num_col()};
1552  // below method fills above 3 'matrices'
1553  this->addRefTrackVirtualMeas1D(refTrajPtr, iVirtualMeas, aHitCovarianceM, aHitResidualsM, aLocalDerivativesM);
1554 
1555  // no global parameters (use dummy 0)
1556  auto aGlobalDerivativesM = Eigen::Matrix<float, 1, 1>::Zero();
1557 
1558  float newResidX = aHitResidualsM(0,0);
1559  float newHitErrX = TMath::Sqrt(aHitCovarianceM(0,0));
1560  std::vector<float> newLocalDerivsX(aLocalDerivativesM.size());
1561  Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> >
1562  (newLocalDerivsX.data(),
1563  aLocalDerivativesM.rows(),
1564  aLocalDerivativesM.cols()) = aLocalDerivativesM;
1565 
1566  std::vector<float> newGlobDerivsX(aGlobalDerivativesM.size());
1567  Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> >
1568  (newGlobDerivsX.data(),
1569  aGlobalDerivativesM.rows(),
1570  aGlobalDerivativesM.cols()) = aGlobalDerivativesM;
1571 
1572  const int nLocal = aLocalDerivativesM.cols();
1573  const int nGlobal = 0;
1574 
1575  theMille->mille(nLocal, newLocalDerivsX.data(), nGlobal, newGlobDerivsX.data(),
1576  &nGlobal, newResidX, newHitErrX);
1577 }
1578 
1579 //____________________________________________________
1581  const TkFittedLasBeamCollection &lasBeams,
1582  const TsosVectorCollection &lasBeamTsoses)
1583 {
1584  TsosVectorCollection::const_iterator iTsoses = lasBeamTsoses.begin();
1585  for(TkFittedLasBeamCollection::const_iterator iBeam = lasBeams.begin(), iEnd = lasBeams.end();
1586  iBeam != iEnd; ++iBeam, ++iTsoses){ // beam/tsoses parallel!
1587 
1588  edm::LogInfo("Alignment") << "@SUB=MillePedeAlignmentAlgorithm::addLaserData"
1589  << "Beam " << iBeam->getBeamId() << " with "
1590  << iBeam->parameters().size() << " parameters and "
1591  << iBeam->getData().size() << " hits.\n There are "
1592  << iTsoses->size() << " TSOSes.";
1593 
1594  this->addLasBeam(eventInfo, *iBeam, *iTsoses);
1595  }
1596 }
1597 
1598 //____________________________________________________
1600  const TkFittedLasBeam &lasBeam,
1601  const std::vector<TrajectoryStateOnSurface> &tsoses)
1602 {
1603  AlignmentParameters *dummyPtr = nullptr; // for globalDerivativesHierarchy()
1604  std::vector<float> lasLocalDerivsX; // buffer for local derivatives
1605  const unsigned int beamLabel = thePedeLabels->lasBeamLabel(lasBeam.getBeamId());// for global par
1606 
1607  for (unsigned int iHit = 0; iHit < tsoses.size(); ++iHit) {
1608  if (!tsoses[iHit].isValid()) continue;
1609  // clear buffer
1610  theFloatBufferX.clear();
1611  theFloatBufferY.clear();
1612  theIntBuffer.clear();
1613  lasLocalDerivsX.clear();
1614  // get alignables and global parameters
1615  const SiStripLaserRecHit2D &hit = lasBeam.getData()[iHit];
1616  AlignableDetOrUnitPtr lasAli(theAlignableNavigator->alignableFromDetId(hit.getDetId()));
1617  this->globalDerivativesHierarchy(eventInfo,
1618  tsoses[iHit], lasAli, lasAli,
1620  // fill derivatives vector from derivatives matrix
1621  for (unsigned int nFitParams = 0;
1622  nFitParams < static_cast<unsigned int>(lasBeam.parameters().size());
1623  ++nFitParams) {
1624  const float derivative = lasBeam.derivatives()[iHit][nFitParams];
1625  if (nFitParams < lasBeam.firstFixedParameter()) { // first local beam parameters
1626  lasLocalDerivsX.push_back(derivative);
1627  } else { // now global ones
1628  const unsigned int numPar = nFitParams - lasBeam.firstFixedParameter();
1629  theIntBuffer.push_back(thePedeLabels->parameterLabel(beamLabel, numPar));
1630  theFloatBufferX.push_back(derivative);
1631  }
1632  } // end loop over parameters
1633 
1634  const float residual = hit.localPosition().x() - tsoses[iHit].localPosition().x();
1635  // error from file or assume 0.003
1636  const float error = 0.003; // hit.localPositionError().xx(); sqrt???
1637 
1638  theMille->mille(lasLocalDerivsX.size(), &(lasLocalDerivsX[0]), theFloatBufferX.size(),
1639  &(theFloatBufferX[0]), &(theIntBuffer[0]), residual, error);
1640  } // end of loop over hits
1641 
1642  theMille->end();
1643 }
1644 
1646 {
1647  // do some printing, if requested
1648  const bool doOutputOnStdout(pxbSurveyCfg.getParameter<bool>("doOutputOnStdout"));
1649  if (doOutputOnStdout) {
1650  edm::LogInfo("Alignment")
1651  << "@SUB=MillePedeAlignmentAlgorithm::addPxbSurvey"
1652  << "# Output from addPxbSurvey follows below because "
1653  << "doOutputOnStdout is set to True";
1654  }
1655 
1656  // instantiate a dicer object
1657  SurveyPxbDicer dicer(pxbSurveyCfg.getParameter<std::vector<edm::ParameterSet> >("toySurveyParameters"), pxbSurveyCfg.getParameter<unsigned int>("toySurveySeed"));
1658  std::ofstream outfile(pxbSurveyCfg.getUntrackedParameter<std::string>("toySurveyFile").c_str());
1659 
1660  // read data from file
1661  std::vector<SurveyPxbImageLocalFit> measurements;
1662  std::string filename(pxbSurveyCfg.getParameter<edm::FileInPath>("infile").fullPath());
1664 
1665  // loop over photographs (=measurements) and perform the fit
1666  for(std::vector<SurveyPxbImageLocalFit>::size_type i=0; i!=measurements.size(); i++)
1667  {
1668  if (doOutputOnStdout) {
1669  edm::LogInfo("Alignment")
1670  << "@SUB=MillePedeAlignmentAlgorithm::addPxbSurvey"
1671  << "Module " << i << ": ";
1672  }
1673 
1674  // get the Alignables and their surfaces
1675  AlignableDetOrUnitPtr mod1(theAlignableNavigator->alignableFromDetId(measurements[i].getIdFirst()));
1676  AlignableDetOrUnitPtr mod2(theAlignableNavigator->alignableFromDetId(measurements[i].getIdSecond()));
1677  const AlignableSurface& surf1 = mod1->surface();
1678  const AlignableSurface& surf2 = mod2->surface();
1679 
1680  // the position of the fiducial points in local frame of a PXB module
1681  const LocalPoint fidpoint0(-0.91,+3.30);
1682  const LocalPoint fidpoint1(+0.91,+3.30);
1683  const LocalPoint fidpoint2(+0.91,-3.30);
1684  const LocalPoint fidpoint3(-0.91,-3.30);
1685 
1686  // We choose the local frame of the first module as reference,
1687  // so take the fidpoints of the second module and calculate their
1688  // positions in the reference frame
1689  const GlobalPoint surf2point0(surf2.toGlobal(fidpoint0));
1690  const GlobalPoint surf2point1(surf2.toGlobal(fidpoint1));
1691  const LocalPoint fidpoint0inSurf1frame(surf1.toLocal(surf2point0));
1692  const LocalPoint fidpoint1inSurf1frame(surf1.toLocal(surf2point1));
1693 
1694  // Create the vector for the fit
1696  fidpointvec.push_back(fidpoint0inSurf1frame);
1697  fidpointvec.push_back(fidpoint1inSurf1frame);
1698  fidpointvec.push_back(fidpoint2);
1699  fidpointvec.push_back(fidpoint3);
1700 
1701  // if toy survey is requested, dice the values now
1702  if (pxbSurveyCfg.getParameter<bool>("doToySurvey"))
1703  {
1704  dicer.doDice(fidpointvec,measurements[i].getIdPair(), outfile);
1705  }
1706 
1707  // do the fit
1708  measurements[i].doFit(fidpointvec, thePedeLabels->alignableLabel(mod1), thePedeLabels->alignableLabel(mod2));
1709  SurveyPxbImageLocalFit::localpars_t a; // local pars from fit
1710  a = measurements[i].getLocalParameters();
1711  const SurveyPxbImageLocalFit::value_t chi2 = measurements[i].getChi2();
1712 
1713  // do some reporting, if requested
1714  if (doOutputOnStdout)
1715  {
1716  edm::LogInfo("Alignment")
1717  << "@SUB=MillePedeAlignmentAlgorithm::addPxbSurvey"
1718  << "a: " << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3]
1719  << " S= " << sqrt(a[2]*a[2]+a[3]*a[3])
1720  << " phi= " << atan(a[3]/a[2])
1721  << " chi2= " << chi2 << std::endl;
1722  }
1723  if (theMonitor)
1724  {
1725  theMonitor->fillPxbSurveyHistsChi2(chi2);
1726  theMonitor->fillPxbSurveyHistsLocalPars(a[0],a[1],sqrt(a[2]*a[2]+a[3]*a[3]),atan(a[3]/a[2]));
1727  }
1728 
1729  // pass the results from the local fit to mille
1731  {
1732  theMille->mille((int)measurements[i].getLocalDerivsSize(),
1733  measurements[i].getLocalDerivsPtr(j),
1734  (int)measurements[i].getGlobalDerivsSize(),
1735  measurements[i].getGlobalDerivsPtr(j),
1736  measurements[i].getGlobalDerivsLabelPtr(j),
1737  measurements[i].getResiduum(j),
1738  measurements[i].getSigma(j));
1739  }
1740  theMille->end();
1741  }
1742  outfile.close();
1743 }
1744 
1745 
1747  const auto runRangeSelection =
1748  theConfig.getUntrackedParameter<edm::VParameterSet>("RunRangeSelection");
1749 
1750  if (runRangeSelection.empty()) return false;
1751 
1752  const auto runRanges =
1753  align::makeNonOverlappingRunRanges(runRangeSelection,
1754  cond::timeTypeSpecs[cond::runnumber].beginValue);
1755 
1756  return !(runRanges.empty());
1757 }
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
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 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
bool areEmptyParams(const align::Alignables &alignables) const
double Scalar
Definition: Definitions.h:27
void increaseHitsY(unsigned int add=1)
increase hits for y-measurement
Time_t beginValue
Definition: Time.h:45
void endLuminosityBlock(const edm::EventSetup &) override
called at end of luminosity block
void buildUserVariables(const align::Alignables &alignables) const
add MillePedeVariables for each AlignmentParameters (exception if no parameters...)
TrajectoryFactoryBase::ReferenceTrajectoryCollection RefTrajColl
std::vector< ParameterSet > VParameterSet
Definition: ParameterSet.h:33
std::unique_ptr< TrajectoryFactoryBase > theTrajectoryFactory
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
void writeMillePedeVariables(const align::Alignables &alivec, const char *filename, int iter, bool validCheck, int &ierr)
void writeAlignableOriginalPositions(const align::Alignables &alivec, const char *filename, int iter, bool validCheck, int &ierr) override
write Alignable original (before misalignment) absolute positions
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.
bool addHits(const align::Alignables &alis, const std::vector< AlignmentUserVariables * > &mpVars) const
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 writeOrigRigidBodyAlignmentParameters(const align::Alignables &alivec, const char *filename, int iter, bool validCheck, int &ierr) override
write RigidBodyAlignmentParameters as applied on top of original positions
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)
std::vector< AlignmentUserVariables * > readMillePedeVariables(const align::Alignables &alivec, const char *filename, int iter, int &ierr)
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
std::vector< ConstRecHitPointer > ConstRecHitContainer
bool addHitStatistics(int fromLoop, const std::string &outFile, const std::vector< std::string > &inFiles) 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.
std::vector< value_t > localpars_t
void writeAlignableAbsolutePositions(const align::Alignables &alivec, const char *filename, int iter, bool validCheck, int &ierr) override
write Alignable current absolute positions
std::vector< Alignable * > Alignables
Definition: Utilities.h:32
std::map< std::string, AlignPCLThreshold > threshold_map
void run(const edm::EventSetup &setup, const EventInfo &eventInfo) override
Run the algorithm on trajectories and tracks.
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
T get() const
Definition: EventSetup.h:63
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:197
firstRun
Definition: dataset.py:933
static const count_t nMsrmts
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
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.
bool read(align::Alignables &alignables, bool setUserVars)
Definition: PedeReader.cc:54
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:44