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