CMS 3D CMS Logo

SiStripBackplaneCalibration.cc
Go to the documentation of this file.
1 // reference - but the strip local reco foresees also calibration parameters
8 // for peak data like for the Lorentz angle.
15 
18 // include 'locally':
20 #include "TreeStruct.h"
21 
26 // #include "CalibTracker/Records/interface/SiStripDependentRecords.h"
28 
31 
36 
42 
43 #include "TTree.h"
44 #include "TFile.h"
45 #include "TString.h"
46 
47 // #include <iostream>
48 #include <vector>
49 #include <map>
50 #include <sstream>
51 #include <cstdio>
52 #include <functional>
53 
55 public:
58 
61 
63  unsigned int numParameters() const override;
64 
65  // /// Return all derivatives,
66  // /// default implementation uses other derivatives(..) method,
67  // /// but can be overwritten in derived class for efficiency.
68  // virtual std::vector<double> derivatives(const TransientTrackingRecHit &hit,
69  // const TrajectoryStateOnSurface &tsos,
70  // const edm::EventSetup &setup,
71  // const EventInfo &eventInfo) const;
72 
75  unsigned int derivatives(std::vector<ValuesIndexPair> &outDerivInds,
77  const TrajectoryStateOnSurface &tsos,
78  const edm::EventSetup &setup,
79  const EventInfo &eventInfo) const override;
80 
83  bool setParameter(unsigned int index, double value) override;
84 
87  bool setParameterError(unsigned int index, double error) override;
88 
91  double getParameter(unsigned int index) const override;
92 
95  double getParameterError(unsigned int index) const override;
96 
97  // /// Call at beginning of job:
99 
102  void endOfJob() override;
103 
104 private:
112 
115  double getParameterForDetId(unsigned int detId, edm::RunNumber_t run) const;
116 
117  void writeTree(const SiStripBackPlaneCorrection &backPlaneCorr,
118  const std::map<unsigned int, TreeStruct> &treeInfo,
119  const char *treeName) const;
120  SiStripBackPlaneCorrection *createFromTree(const char *fileName, const char *treeName) const;
121 
123  int16_t readoutMode_;
124  const bool saveToDB_;
127  const std::vector<std::string> mergeFileNames_;
128 
130 
132 
133  std::vector<double> parameters_;
134  std::vector<double> paramUncertainties_;
135 
142 };
143 
144 //======================================================================
145 //======================================================================
146 //======================================================================
147 
150  readoutModeName_(cfg.getParameter<std::string>("readoutMode")),
151  saveToDB_(cfg.getParameter<bool>("saveToDB")),
152  recordNameDBwrite_(cfg.getParameter<std::string>("recordNameDBwrite")),
153  outFileName_(cfg.getParameter<std::string>("treeFile")),
154  mergeFileNames_(cfg.getParameter<std::vector<std::string> >("mergeTreeFiles")),
155  siStripBackPlaneCorrInput_(nullptr),
156  moduleGroupSelector_(nullptr),
157  moduleGroupSelCfg_(cfg.getParameter<edm::ParameterSet>("BackplaneModuleGroups")),
158  latencyToken_(iC.esConsumes()),
159  lorentzAngleToken_(iC.esConsumes<edm::Transition::BeginRun>(edm::ESInputTag("", readoutModeName_))),
160  magFieldToken_(iC.esConsumes()),
161  backPlaneCorrToken_(iC.esConsumes(edm::ESInputTag("", readoutModeName_))) {
162  // SiStripLatency::singleReadOutMode() returns
163  // 1: all in peak, 0: all in deco, -1: mixed state
164  // (in principle one could treat even mixed state APV by APV...)
165  if (readoutModeName_ == "peak") {
167  } else if (readoutModeName_ == "deconvolution") {
169  } else {
170  throw cms::Exception("BadConfig") << "SiStripBackplaneCalibration:\n"
171  << "Unknown mode '" << readoutModeName_
172  << "', should be 'peak' or 'deconvolution' .\n";
173  }
174 }
175 
176 //======================================================================
178  delete moduleGroupSelector_;
179  // std::cout << "Destroy SiStripBackplaneCalibration named " << this->name() << std::endl;
181 }
182 
183 //======================================================================
184 unsigned int SiStripBackplaneCalibration::numParameters() const { return parameters_.size(); }
185 
186 //======================================================================
187 unsigned int SiStripBackplaneCalibration::derivatives(std::vector<ValuesIndexPair> &outDerivInds,
189  const TrajectoryStateOnSurface &tsos,
190  const edm::EventSetup &setup,
191  const EventInfo &eventInfo) const {
192  // ugly const-cast:
193  // But it is either only first initialisation or throwing an exception...
195 
196  outDerivInds.clear();
197 
198  const SiStripLatency *latency = &setup.getData(latencyToken_);
199  const int16_t mode = latency->singleReadOutMode();
200 
201  if (mode == readoutMode_) {
202  if (hit.det()) { // otherwise 'constraint hit' or whatever
203 
204  const int index =
205  moduleGroupSelector_->getParameterIndexFromDetId(hit.det()->geographicalId(), eventInfo.eventId().run());
206  if (index >= 0) { // otherwise not treated
207  const MagneticField *magneticField = &setup.getData(magFieldToken_);
208  const GlobalVector bField(magneticField->inTesla(hit.det()->surface().position()));
209  const LocalVector bFieldLocal(hit.det()->surface().toLocal(bField));
210  //std::cout << "SiStripBackplaneCalibration derivatives " << readoutModeName_ << std::endl;
211  const double dZ = hit.det()->surface().bounds().thickness(); // it's a float only...
212  const double tanPsi = tsos.localParameters().mixedFormatVector()[1]; //float...
213 
214  const SiStripLorentzAngle *lorentzAngleHandle = &setup.getData(lorentzAngleToken_);
215  // Yes, mobility (= LA/By) stored in object called LA...
216  const double mobility = lorentzAngleHandle->getLorentzAngle(hit.det()->geographicalId());
217  // shift due to dead back plane has two parts:
218  // 1) Lorentz Angle correction formula gets reduced thickness dz*(1-bp)
219  // 2) 'Direct' effect is shift of effective module position in local z by bp*dz/2
220  // (see GF's presentation in alignment meeting 25.10.2012,
221  // https://indico.cern.ch/conferenceDisplay.py?confId=174266#2012-10-25)
222  // const double xDerivative = 0.5 * dZ * (mobility * bFieldLocal.y() - tanPsi);
223  //FIXME: +tanPsi? At least that fits the sign of the dr/dw residual
224  // in KarimakiDerivatives...
225  const double xDerivative = 0.5 * dZ * (mobility * bFieldLocal.y() + tanPsi);
226  // std::cout << "derivative is " << xDerivative << " for index " << index
227  // << std::endl;
228  // if (index >= 10) {
229  // std::cout << "mobility * y-field " << mobility * bFieldLocal.y()
230  // << ", \n tanPsi " << tanPsi /*<< ", dZ " << dZ */ << std::endl;
231  // std::cout << "|tanPsi| - |mobility * y-field| "
232  // << fabs(tanPsi) - fabs(mobility * bFieldLocal.y())
233  // << std::endl;
234  // }
235  const Values derivs(xDerivative, 0.); // yDerivative = 0.
236  outDerivInds.push_back(ValuesIndexPair(derivs, index));
237  }
238  } else {
239  edm::LogWarning("Alignment") << "@SUB=SiStripBackplaneCalibration::derivatives1"
240  << "Hit without GeomDet, skip!";
241  }
242  } else if (mode != kDeconvolutionMode && mode != kPeakMode) {
243  // warn only if unknown/mixed mode
244  edm::LogWarning("Alignment") << "@SUB=SiStripBackplaneCalibration::derivatives2"
245  << "Readout mode is " << mode << ", but looking for " << readoutMode_ << " ("
246  << readoutModeName_ << ").";
247  }
248 
249  return outDerivInds.size();
250 }
251 
252 //======================================================================
254  if (index >= parameters_.size()) {
255  return false;
256  } else {
258  return true;
259  }
260 }
261 
262 //======================================================================
264  if (index >= paramUncertainties_.size()) {
265  return false;
266  } else {
268  return true;
269  }
270 }
271 
272 //======================================================================
274  return (index >= parameters_.size() ? 0. : parameters_[index]);
275 }
276 
277 //======================================================================
279  return (index >= paramUncertainties_.size() ? 0. : paramUncertainties_[index]);
280 }
281 
282 //======================================================================
284  AlignableMuon * /*aliMuon*/,
285  AlignableExtras * /*aliExtras*/) {
286  //specify the sub-detectors for which the back plane correction is determined: all strips
287  const std::vector<int> sdets = {SiStripDetId::TIB, SiStripDetId::TID, SiStripDetId::TOB, SiStripDetId::TEC};
288 
290 
293 
294  edm::LogInfo("Alignment") << "@SUB=SiStripBackplaneCalibration"
295  << "Created with name " << this->name() << " for readout mode '" << readoutModeName_
296  << "',\n"
297  << this->numParameters() << " parameters to be determined."
298  << "\nsaveToDB = " << saveToDB_ << "\n outFileName = " << outFileName_
299  << "\n N(merge files) = " << mergeFileNames_.size()
300  << "\n number of IOVs = " << moduleGroupSelector_->numIovs();
301 
302  if (!mergeFileNames_.empty()) {
303  edm::LogInfo("Alignment") << "@SUB=SiStripBackplaneCalibration"
304  << "First file to merge: " << mergeFileNames_[0];
305  }
306 }
307 
308 //======================================================================
310  // loginfo output
311  std::ostringstream out;
312  out << "Parameter results for readout mode '" << readoutModeName_ << "'\n";
313  for (unsigned int iPar = 0; iPar < parameters_.size(); ++iPar) {
314  out << iPar << ": " << parameters_[iPar] << " +- " << paramUncertainties_[iPar] << "\n";
315  }
316  edm::LogInfo("Alignment") << "@SUB=SiStripBackplaneCalibration::endOfJob" << out.str();
317 
318  std::map<unsigned int, TreeStruct> treeInfo; // map of TreeStruct for each detId
319 
320  // now write 'input' tree
321  const SiStripBackPlaneCorrection *input = this->getBackPlaneCorrectionInput(); // never NULL
322  const std::string treeName(this->name() + '_' + readoutModeName_ + '_');
323  this->writeTree(*input, treeInfo, (treeName + "input").c_str()); // empty treeInfo for input...
324 
325  if (input->getBackPlaneCorrections().empty()) {
326  edm::LogError("Alignment") << "@SUB=SiStripBackplaneCalibration::endOfJob"
327  << "Input back plane correction map is empty ('" << readoutModeName_
328  << "' mode), skip writing output!";
329  return;
330  }
331 
332  const unsigned int nonZeroParamsOrErrors = // Any determined value?
333  count_if(parameters_.begin(), parameters_.end(), [](auto c) { return c != 0.; }) +
334  count_if(paramUncertainties_.begin(), paramUncertainties_.end(), [](auto c) { return c != 0.; });
335 
336  for (unsigned int iIOV = 0; iIOV < moduleGroupSelector_->numIovs(); ++iIOV) {
337  cond::Time_t firstRunOfIOV = moduleGroupSelector_->firstRunOfIOV(iIOV);
339  // Loop on map of values from input and add (possible) parameter results
340  for (auto iterIdValue = input->getBackPlaneCorrections().begin();
341  iterIdValue != input->getBackPlaneCorrections().end();
342  ++iterIdValue) {
343  // type of (*iterIdValue) is pair<unsigned int, float>
344  const unsigned int detId = iterIdValue->first; // key of map is DetId
345  // Some code one could use to miscalibrate wrt input:
346  // double param = 0.;
347  // const DetId id(detId);
348  // switch (id.subdetId()) {
349  // case 3:
350  // // delta = 0.025;
351  // {
352  // TIBDetId tibId(detId);
353  // param = tibId.layer() * 0.01;
354  // }
355  // break;
356  // case 5:
357  // //delta = 0.050;
358  // {
359  // TOBDetId tobId(detId);
360  // param = tobId.layer() * 0.015;
361  // }
362  // break;
363  // case 4: // TID
364  // param = 0.03; break;
365  // case 6: // TEC
366  // param = 0.05; break;
367  // break;
368  // default:
369  // std::cout << "unknown subdet " << id.subdetId() << std::endl;
370  // }
371  const double param = this->getParameterForDetId(detId, firstRunOfIOV);
372  // put result in output, i.e. sum of input and determined parameter:
373  output.putBackPlaneCorrection(detId, iterIdValue->second + param);
374  const int paramIndex = moduleGroupSelector_->getParameterIndexFromDetId(detId, firstRunOfIOV);
375  treeInfo[detId] = TreeStruct(param, this->getParameterError(paramIndex), paramIndex);
376  }
377 
378  if (saveToDB_ || nonZeroParamsOrErrors != 0) { // Skip writing mille jobs...
379  this->writeTree(output, treeInfo, (treeName + Form("result_%lld", firstRunOfIOV)).c_str());
380  }
381 
382  if (saveToDB_) { // If requested, write out to DB
384  if (dbService.isAvailable()) {
385  dbService->writeOneIOV(output, firstRunOfIOV, recordNameDBwrite_);
386  // no 'delete output;': writeOne(..) took over ownership
387  } else {
388  edm::LogError("BadConfig") << "@SUB=SiStripBackplaneCalibration::endOfJob"
389  << "No PoolDBOutputService available, but saveToDB true!";
390  }
391  }
392  } // end loop on IOVs
393 }
394 
395 //======================================================================
397  const EventInfo &eventInfo) {
398  const SiStripBackPlaneCorrection *backPlaneCorrHandle = nullptr;
400  backPlaneCorrHandle = &setup.getData(backPlaneCorrToken_);
401  siStripBackPlaneCorrInput_ = new SiStripBackPlaneCorrection(*backPlaneCorrHandle);
402  // FIXME: Should we call 'watchBackPlaneCorrRcd_.check(setup)' as well?
403  // Otherwise could be that next check has to check via following 'else', though
404  // no new IOV has started... (to be checked)
405  } else {
406  if (watchBackPlaneCorrRcd_.check(setup)) { // new IOV of input - but how to check peak vs deco?
407  backPlaneCorrHandle = &setup.getData(backPlaneCorrToken_);
408 
409  if (backPlaneCorrHandle->getBackPlaneCorrections() // but only bad if non-identical values
410  != siStripBackPlaneCorrInput_->getBackPlaneCorrections()) { // (comparing maps)
411  // Maps are containers sorted by key, but comparison problems may arise from
412  // 'floating point comparison' problems (FIXME?)
413  throw cms::Exception("BadInput") << "SiStripBackplaneCalibration::checkBackPlaneCorrectionInput:\n"
414  << "Content of SiStripBackPlaneCorrection changed at run "
415  << eventInfo.eventId().run() << ", but algorithm expects constant input!\n";
416  return false; // not reached...
417  }
418  }
419  }
420 
421  return true;
422 }
423 
424 //======================================================================
426  // For parallel processing in Millepede II, create SiStripBackPlaneCorrection
427  // from info stored in files of parallel jobs and check that they are identical.
428  // If this job has run on events, still check that back plane corrections are
429  // identical to the ones from mergeFileNames_.
430  const std::string treeName(((this->name() + '_') += readoutModeName_) += "_input");
431  for (auto iFile = mergeFileNames_.begin(); iFile != mergeFileNames_.end(); ++iFile) {
432  SiStripBackPlaneCorrection *bpCorr = this->createFromTree(iFile->c_str(), treeName.c_str());
433  // siStripBackPlaneCorrInput_ could be non-null from previous file of this loop
434  // or from checkBackPlaneCorrectionInput(..) when running on data in this job as well
436  delete siStripBackPlaneCorrInput_; // NULL or empty
438  } else {
439  // about comparison of maps see comments in checkBackPlaneCorrectionInput
440  if (bpCorr && !bpCorr->getBackPlaneCorrections().empty() && // single job might not have got events
442  // Throw exception instead of error?
443  edm::LogError("NoInput") << "@SUB=SiStripBackplaneCalibration::getBackPlaneCorrectionInput"
444  << "Different input values from tree " << treeName << " in file " << *iFile << ".";
445  }
446  delete bpCorr;
447  }
448  }
449 
450  if (!siStripBackPlaneCorrInput_) { // no files nor ran on events
452  edm::LogError("NoInput") << "@SUB=SiStripBackplaneCalibration::getBackPlaneCorrectionInput"
453  << "No input, create an empty one ('" << readoutModeName_ << "' mode)!";
454  } else if (siStripBackPlaneCorrInput_->getBackPlaneCorrections().empty()) {
455  edm::LogError("NoInput") << "@SUB=SiStripBackplaneCalibration::getBackPlaneCorrectionInput"
456  << "Empty result ('" << readoutModeName_ << "' mode)!";
457  }
458 
460 }
461 
462 //======================================================================
465 
466  return (index < 0 ? 0. : parameters_[index]);
467 }
468 
469 //======================================================================
471  const std::map<unsigned int, TreeStruct> &treeInfo,
472  const char *treeName) const {
473  TFile *file = TFile::Open(outFileName_.c_str(), "UPDATE");
474  if (!file) {
475  edm::LogError("BadConfig") << "@SUB=SiStripBackplaneCalibration::writeTree"
476  << "Could not open file '" << outFileName_ << "'.";
477  return;
478  }
479 
480  TTree *tree = new TTree(treeName, treeName);
481  unsigned int id = 0;
482  float value = 0.;
483  TreeStruct treeStruct;
484  tree->Branch("detId", &id, "detId/i");
485  tree->Branch("value", &value, "value/F");
486  tree->Branch("treeStruct", &treeStruct, TreeStruct::LeafList());
487 
488  for (auto iterIdValue = backPlaneCorrection.getBackPlaneCorrections().begin();
489  iterIdValue != backPlaneCorrection.getBackPlaneCorrections().end();
490  ++iterIdValue) {
491  // type of (*iterIdValue) is pair<unsigned int, float>
492  id = iterIdValue->first; // key of map is DetId
493  value = iterIdValue->second;
494  // type of (*treeStructIter) is pair<unsigned int, TreeStruct>
495  auto treeStructIter = treeInfo.find(id); // find info for this id
496  if (treeStructIter != treeInfo.end()) {
497  treeStruct = treeStructIter->second; // info from input map
498  } else { // if none found, fill at least parameter index (using 1st IOV...)
499  const cond::Time_t run1of1stIov = moduleGroupSelector_->firstRunOfIOV(0);
500  const int ind = moduleGroupSelector_->getParameterIndexFromDetId(id, run1of1stIov);
501  treeStruct = TreeStruct(ind);
502  }
503  tree->Fill();
504  }
505  tree->Write();
506  delete file; // tree vanishes with the file...
507 }
508 
509 //======================================================================
511  const char *treeName) const {
512  // Check for file existence on your own to work around
513  // https://hypernews.cern.ch/HyperNews/CMS/get/swDevelopment/2715.html:
514  TFile *file = nullptr;
515  FILE *testFile = fopen(fileName, "r");
516  if (testFile) {
517  fclose(testFile);
518  file = TFile::Open(fileName, "READ");
519  } // else not existing, see error below
520 
521  TTree *tree = nullptr;
522  if (file)
523  file->GetObject(treeName, tree);
524 
526  if (tree) {
527  unsigned int id = 0;
528  float value = 0.;
529  tree->SetBranchAddress("detId", &id);
530  tree->SetBranchAddress("value", &value);
531 
533  const Long64_t nEntries = tree->GetEntries();
534  for (Long64_t iEntry = 0; iEntry < nEntries; ++iEntry) {
535  tree->GetEntry(iEntry);
536  result->putBackPlaneCorrection(id, value);
537  }
538  } else { // Warning only since could be parallel job on no events.
539  edm::LogWarning("Alignment") << "@SUB=SiStripBackplaneCalibration::createFromTree"
540  << "Could not get TTree '" << treeName << "' from file '" << fileName
541  << (file ? "'." : "' (file does not exist).");
542  }
543 
544  delete file; // tree will vanish with file
545  return result;
546 }
547 
548 //======================================================================
549 //======================================================================
550 // Plugin definition
551 
553 
int getParameterIndexFromDetId(unsigned int detId, edm::RunNumber_t run) const
unsigned int numIovs() const
Total number of IOVs.
TkModuleGroupSelector * moduleGroupSelector_
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
const edm::ESGetToken< SiStripLatency, SiStripLatencyRcd > latencyToken_
static constexpr auto TID
Definition: SiStripDetId.h:38
unsigned int derivatives(std::vector< ValuesIndexPair > &outDerivInds, const TransientTrackingRecHit &hit, const TrajectoryStateOnSurface &tsos, const edm::EventSetup &setup, const EventInfo &eventInfo) const override
const LocalTrajectoryParameters & localParameters() const
~SiStripBackplaneCalibration() override
Destructor.
SiStripBackPlaneCorrection * siStripBackPlaneCorrInput_
unsigned int getNumberOfParameters() const
Log< level::Error, false > LogError
const edm::ParameterSet moduleGroupSelCfg_
double getParameterForDetId(unsigned int detId, edm::RunNumber_t run) const
unsigned int numParameters() const override
How many parameters does this calibration define?
define event information passed to algorithms
static std::string const input
Definition: EdmProvDump.cc:47
bool checkBackPlaneCorrectionInput(const edm::EventSetup &setup, const EventInfo &eventInfo)
const SiStripBackPlaneCorrection * getBackPlaneCorrectionInput()
structure to store algorithm results in a TTree
Definition: TreeStruct.h:6
const edm::ESGetToken< SiStripLorentzAngle, SiStripLorentzAngleRcd > lorentzAngleToken_
unsigned long long Time_t
Definition: Time.h:14
const std::vector< std::string > mergeFileNames_
void beginOfJob(AlignableTracker *tracker, AlignableMuon *muon, AlignableExtras *extras) override
SiStripBackPlaneCorrection * createFromTree(const char *fileName, const char *treeName) const
std::pair< Values, unsigned int > ValuesIndexPair
x- and y-values
edm::ESWatcher< SiStripBackPlaneCorrectionRcd > watchBackPlaneCorrRcd_
Hash writeOneIOV(const T &payload, Time_t time, const std::string &recordName)
Transition
Definition: Transition.h:12
bool setParameterError(unsigned int index, double error) override
const edm::ESGetToken< SiStripBackPlaneCorrection, SiStripBackPlaneCorrectionRcd > backPlaneCorrToken_
Definition: value.py:1
static constexpr auto TOB
Definition: SiStripDetId.h:39
std::pair< double, double > Values
Log< level::Info, false > LogInfo
float getLorentzAngle(const uint32_t &) const
AlgebraicVector5 mixedFormatVector() const
const std::map< unsigned int, float > & getBackPlaneCorrections() const
static const char * LeafList()
Definition: TreeStruct.h:16
double getParameter(unsigned int index) const override
SiStripBackplaneCalibration(const edm::ParameterSet &cfg, edm::ConsumesCollector &iC)
Constructor.
const edm::ESGetToken< MagneticField, IdealMagneticFieldRecord > magFieldToken_
void writeTree(const SiStripBackPlaneCorrection &backPlaneCorr, const std::map< unsigned int, TreeStruct > &treeInfo, const char *treeName) const
bool check(const edm::EventSetup &iSetup)
Definition: ESWatcher.h:57
static constexpr auto TIB
Definition: SiStripDetId.h:37
HLT enums.
#define DEFINE_EDM_PLUGIN(factory, type, name)
bool isAvailable() const
Definition: Service.h:40
unsigned int RunNumber_t
eventInfo
add run, event number and lumi section
Definition: tree.py:1
Log< level::Warning, false > LogWarning
double getParameterError(unsigned int index) const override
Constructor of the full muon geometry.
Definition: AlignableMuon.h:38
bool setParameter(unsigned int index, double value) override
const std::string & name() const
name of this calibration
edm::RunNumber_t firstRunOfIOV(unsigned int iovNum) const
First run of iov (0 if iovNum not treated).
static constexpr auto TEC
Definition: SiStripDetId.h:40