CMS 3D CMS Logo

SiStripLorentzAngleCalibration.cc
Go to the documentation of this file.
1 
16 // include 'locally':
18 #include "TreeStruct.h"
19 
24 //#include "CalibTracker/Records/interface/SiStripDependentRecords.h"
26 
29 
35 
40 
41 #include "TTree.h"
42 #include "TFile.h"
43 #include "TString.h"
44 
45 // #include <iostream>
46 #include <boost/assign/list_of.hpp>
47 #include <vector>
48 #include <map>
49 #include <sstream>
50 #include <cstdio>
51 #include <functional>
52 
54 {
55 public:
58 
61 
63  virtual 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  virtual unsigned int derivatives(std::vector<ValuesIndexPair> &outDerivInds,
77  const TrajectoryStateOnSurface &tsos,
78  const edm::EventSetup &setup,
79  const EventInfo &eventInfo) const override;
80 
83  virtual bool setParameter(unsigned int index, double value) override;
84 
87  virtual bool setParameterError(unsigned int index, double error) override;
88 
91  virtual double getParameter(unsigned int index) const override;
92 
95  virtual double getParameterError(unsigned int index) const override;
96 
97  // /// Call at beginning of job:
98  virtual void beginOfJob(AlignableTracker *tracker,
100  AlignableExtras *extras) override;
101 
102 
105  virtual void endOfJob() override;
106 
107 private:
110  bool checkLorentzAngleInput(const edm::EventSetup &setup, const EventInfo &eventInfo);
116  double effectiveThickness(const GeomDet *det, int16_t mode, const edm::EventSetup &setup) const;
117 
120  double getParameterForDetId(unsigned int detId, edm::RunNumber_t run) const;
121 
122  void writeTree(const SiStripLorentzAngle *lorentzAngle,
123  const std::map<unsigned int,TreeStruct> &treeInfo, const char *treeName) const;
124  SiStripLorentzAngle* createFromTree(const char *fileName, const char *treeName) const;
125 
127  int16_t readoutMode_;
128  const bool saveToDB_;
131  const std::vector<std::string> mergeFileNames_;
132 
134 
136 
137  std::vector<double> parameters_;
138  std::vector<double> paramUncertainties_;
139 
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")),
157  moduleGroupSelCfg_(cfg.getParameter<edm::ParameterSet>("LorentzAngleModuleGroups"))
158 {
159 
160  // SiStripLatency::singleReadOutMode() returns
161  // 1: all in peak, 0: all in deco, -1: mixed state
162  // (in principle one could treat even mixed state APV by APV...)
163  if (readoutModeName_ == "peak") {
165  } else if (readoutModeName_ == "deconvolution") {
167  } else {
168  throw cms::Exception("BadConfig")
169  << "SiStripLorentzAngleCalibration:\n" << "Unknown mode '"
170  << readoutModeName_ << "', should be 'peak' or 'deconvolution' .\n";
171  }
172 
173 }
174 
175 //======================================================================
177 {
178  delete moduleGroupSelector_;
179  // std::cout << "Destroy SiStripLorentzAngleCalibration named " << this->name() << std::endl;
181 }
182 
183 //======================================================================
185 {
186  return parameters_.size();
187 }
188 
189 //======================================================================
190 unsigned int
191 SiStripLorentzAngleCalibration::derivatives(std::vector<ValuesIndexPair> &outDerivInds,
193  const TrajectoryStateOnSurface &tsos,
194  const edm::EventSetup &setup,
195  const EventInfo &eventInfo) const
196 {
197  // ugly const-cast:
198  // But it is either only first initialisation or throwing an exception...
199  const_cast<SiStripLorentzAngleCalibration*>(this)->checkLorentzAngleInput(setup, eventInfo);
200 
201  outDerivInds.clear();
202 
204  setup.get<SiStripLatencyRcd>().get(latency);
205  const int16_t mode = latency->singleReadOutMode();
206  if (mode == readoutMode_) {
207  if (hit.det()) { // otherwise 'constraint hit' or whatever
208 
210  eventInfo.eventId().run());
211  if (index >= 0) { // otherwise not treated
213  setup.get<IdealMagneticFieldRecord>().get(magneticField);
214  const GlobalVector bField(magneticField->inTesla(hit.det()->surface().position()));
215  const LocalVector bFieldLocal(hit.det()->surface().toLocal(bField));
216  //std::cout << "SiStripLorentzAngleCalibration derivatives " << readoutModeName_ << std::endl;
217  const double dZ = this->effectiveThickness(hit.det(), mode, setup);
218  // shift due to LA: dx = tan(LA) * dz/2 = mobility * B_y * dz/2,
219  // '-' since we have derivative of the residual r = hit - trk and mu is part of trk model
220  // (see GF's presentation in alignment meeting 25.10.2012,
221  // https://indico.cern.ch/conferenceDisplay.py?confId=174266#2012-10-25)
222  // Hmm! StripCPE::fillParams() defines, together with
223  // StripCPE::driftDirection(...):
224  // drift.x = -mobility * by * thickness (full drift from backside)
225  // So '-' already comes from that, not from mobility being part of
226  // track model...
227  const double xDerivative = bFieldLocal.y() * dZ * -0.5; // parameter is mobility!
228  if (xDerivative) { // If field is zero, this is zero: do not return it
229  const Values derivs(xDerivative, 0.); // yDerivative = 0.
230  outDerivInds.push_back(ValuesIndexPair(derivs, index));
231  }
232  }
233  } else {
234  edm::LogWarning("Alignment") << "@SUB=SiStripLorentzAngleCalibration::derivatives1"
235  << "Hit without GeomDet, skip!";
236  }
237  } else if (mode != kDeconvolutionMode && mode != kPeakMode) {
238  // warn only if unknown/mixed mode
239  edm::LogWarning("Alignment") << "@SUB=SiStripLorentzAngleCalibration::derivatives2"
240  << "Readout mode is " << mode << ", but looking for "
241  << readoutMode_ << " (" << readoutModeName_ << ").";
242  }
243 
244  return outDerivInds.size();
245 }
246 
247 //======================================================================
249 {
250  if (index >= parameters_.size()) {
251  return false;
252  } else {
254  return true;
255  }
256 }
257 
258 //======================================================================
260 {
261  if (index >= paramUncertainties_.size()) {
262  return false;
263  } else {
265  return true;
266  }
267 }
268 
269 //======================================================================
271 {
272  return (index >= parameters_.size() ? 0. : parameters_[index]);
273 }
274 
275 //======================================================================
277 {
278  return (index >= paramUncertainties_.size() ? 0. : paramUncertainties_[index]);
279 }
280 
281 //======================================================================
283  AlignableMuon * /*aliMuon*/,
284  AlignableExtras * /*aliExtras*/)
285 {
286  //specify the sub-detectors for which the LA is determined
287  const std::vector<int> sdets = boost::assign::list_of(SiStripDetId::TIB)(SiStripDetId::TOB); //no TEC,TID
289 
292 
293  edm::LogInfo("Alignment") << "@SUB=SiStripLorentzAngleCalibration" << "Created with name "
294  << this->name() << " for readout mode '" << readoutModeName_
295  << "',\n" << this->numParameters() << " parameters to be determined."
296  << "\nsaveToDB = " << saveToDB_
297  << "\n outFileName = " << outFileName_
298  << "\n N(merge files) = " << mergeFileNames_.size()
299  << "\n number of IOVs = " << moduleGroupSelector_->numIovs();
300 
301  if (mergeFileNames_.size()) {
302  edm::LogInfo("Alignment") << "@SUB=SiStripLorentzAngleCalibration"
303  << "First file to merge: " << mergeFileNames_[0];
304  }
305 }
306 
307 
308 //======================================================================
310 {
311  // loginfo output
312  std::ostringstream out;
313  out << "Parameter results for readout mode '" << readoutModeName_ << "'\n";
314  for (unsigned int iPar = 0; iPar < parameters_.size(); ++iPar) {
315  out << iPar << ": " << parameters_[iPar] << " +- " << paramUncertainties_[iPar] << "\n";
316  }
317  edm::LogInfo("Alignment") << "@SUB=SiStripLorentzAngleCalibration::endOfJob" << out.str();
318 
319  std::map<unsigned int, TreeStruct> treeInfo; // map of TreeStruct for each detId
320 
321  // now write 'input' tree
322  const SiStripLorentzAngle *input = this->getLorentzAnglesInput(); // never NULL
323  const std::string treeName(this->name() + '_' + readoutModeName_ + '_');
324  this->writeTree(input, treeInfo, (treeName + "input").c_str()); // empty treeInfo for input...
325 
326  if (input->getLorentzAngles().empty()) {
327  edm::LogError("Alignment") << "@SUB=SiStripLorentzAngleCalibration::endOfJob"
328  << "Input Lorentz angle map is empty ('"
329  << readoutModeName_ << "' mode), skip writing output!";
330  return;
331  }
332 
333  const unsigned int nonZeroParamsOrErrors = // Any determined value?
334  count_if (parameters_.begin(), parameters_.end(), std::bind2nd(std::not_equal_to<double>(),0.))
335  + count_if(paramUncertainties_.begin(), paramUncertainties_.end(),
336  std::bind2nd(std::not_equal_to<double>(), 0.));
337 
338  for (unsigned int iIOV = 0; iIOV < moduleGroupSelector_->numIovs(); ++iIOV) {
339  cond::Time_t firstRunOfIOV = moduleGroupSelector_->firstRunOfIOV(iIOV);
341  // Loop on map of values from input and add (possible) parameter results
342  for (auto iterIdValue = input->getLorentzAngles().begin();
343  iterIdValue != input->getLorentzAngles().end(); ++iterIdValue) {
344  // type of (*iterIdValue) is pair<unsigned int, float>
345  const unsigned int detId = iterIdValue->first; // key of map is DetId
346  // Some code one could use to miscalibrate wrt input:
347  // double param = 0.;
348  // const DetId id(detId);
349  // if (id.subdetId() == 3) { // TIB
350  // param = (readoutMode_ == kPeakMode ? -0.003 : -0.002);
351  // } else if (id.subdetId() == 5) { // TOB
352  // param = (readoutMode_ == kPeakMode ? 0.005 : 0.004);
353  // }
354  const double param = this->getParameterForDetId(detId, firstRunOfIOV);
355  // put result in output, i.e. sum of input and determined parameter:
356  output->putLorentzAngle(detId, iterIdValue->second + param);
357  const int paramIndex = moduleGroupSelector_->getParameterIndexFromDetId(detId,firstRunOfIOV);
358  treeInfo[detId] = TreeStruct(param, this->getParameterError(paramIndex), paramIndex);
359  }
360 
361  if (saveToDB_ || nonZeroParamsOrErrors != 0) { // Skip writing mille jobs...
362  this->writeTree(output, treeInfo, (treeName + Form("result_%lld", firstRunOfIOV)).c_str());
363  }
364 
365  if (saveToDB_) { // If requested, write out to DB
367  if (dbService.isAvailable()) {
368  dbService->writeOne(output, firstRunOfIOV, recordNameDBwrite_.c_str());
369  // no 'delete output;': writeOne(..) took over ownership
370  } else {
371  delete output;
372  edm::LogError("BadConfig") << "@SUB=SiStripLorentzAngleCalibration::endOfJob"
373  << "No PoolDBOutputService available, but saveToDB true!";
374  }
375  } else {
376  delete output;
377  }
378  } // end loop on IOVs
379 }
380 
381 //======================================================================
383  const EventInfo &eventInfo)
384 {
385  edm::ESHandle<SiStripLorentzAngle> lorentzAngleHandle;
387  setup.get<SiStripLorentzAngleRcd>().get(readoutModeName_, lorentzAngleHandle);
388  siStripLorentzAngleInput_ = new SiStripLorentzAngle(*lorentzAngleHandle);
389  // FIXME: Should we call 'watchLorentzAngleRcd_.check(setup)' as well?
390  // Otherwise could be that next check has to check via following 'else', though
391  // no new IOV has started... (to be checked)
392  } else {
393  if (watchLorentzAngleRcd_.check(setup)) { // new IOV of input - but how to check peak vs deco?
394  setup.get<SiStripLorentzAngleRcd>().get(readoutModeName_, lorentzAngleHandle);
395  if (lorentzAngleHandle->getLorentzAngles() // but only bad if non-identical values
396  != siStripLorentzAngleInput_->getLorentzAngles()) { // (comparing maps)
397  // Maps are containers sorted by key, but comparison problems may arise from
398  // 'floating point comparison' problems (FIXME?)
399  throw cms::Exception("BadInput")
400  << "SiStripLorentzAngleCalibration::checkLorentzAngleInput:\n"
401  << "Content of SiStripLorentzAngle changed at run " << eventInfo.eventId().run()
402  << ", but algorithm expects constant input!\n";
403  return false; // not reached...
404  }
405  }
406  }
407 
408  return true;
409 }
410 
411 //======================================================================
413  int16_t mode,
414  const edm::EventSetup &setup) const
415 {
416  if (!det) return 0.;
417  double dZ = det->surface().bounds().thickness(); // it is a float only...
418  const SiStripDetId id(det->geographicalId());
420  // FIXME: which one? DepRcd->get(handle) or Rcd->get(readoutModeName_, handle)??
421  // setup.get<SiStripBackPlaneCorrectionDepRcd>().get(backPlaneHandle); // get correct mode
422  setup.get<SiStripBackPlaneCorrectionRcd>().get(readoutModeName_, backPlaneHandle);
423  const double bpCor = backPlaneHandle->getBackPlaneCorrection(id); // it's a float...
424  // std::cout << "bpCor " << bpCor << " in subdet " << id.subdetId() << std::endl;
425  dZ *= (1. - bpCor);
426 
427  return dZ;
428 }
429 
430 //======================================================================
432 {
433  // For parallel processing in Millepede II, create SiStripLorentzAngle
434  // from info stored in files of parallel jobs and check that they are identical.
435  // If this job has run on events, still check that LA is identical to the ones
436  // from mergeFileNames_.
437  const std::string treeName(((this->name() + '_') += readoutModeName_) += "_input");
438  for (auto iFile = mergeFileNames_.begin(); iFile != mergeFileNames_.end(); ++iFile) {
439  SiStripLorentzAngle* la = this->createFromTree(iFile->c_str(), treeName.c_str());
440  // siStripLorentzAngleInput_ could be non-null from previous file of this loop
441  // or from checkLorentzAngleInput(..) when running on data in this job as well
443  delete siStripLorentzAngleInput_; // NULL or empty
445  } else {
446  // FIXME: about comparison of maps see comments in checkLorentzAngleInput
447  if (la && !la->getLorentzAngles().empty() && // single job might not have got events
449  // Throw exception instead of error?
450  edm::LogError("NoInput") << "@SUB=SiStripLorentzAngleCalibration::getLorentzAnglesInput"
451  << "Different input values from tree " << treeName
452  << " in file " << *iFile << ".";
453 
454  }
455  delete la;
456  }
457  }
458 
459  if (!siStripLorentzAngleInput_) { // no files nor ran on events
461  edm::LogError("NoInput") << "@SUB=SiStripLorentzAngleCalibration::getLorentzAnglesInput"
462  << "No input, create an empty one ('" << readoutModeName_ << "' mode)!";
463  } else if (siStripLorentzAngleInput_->getLorentzAngles().empty()) {
464  edm::LogError("NoInput") << "@SUB=SiStripLorentzAngleCalibration::getLorentzAnglesInput"
465  << "Empty result ('" << readoutModeName_ << "' mode)!";
466  }
467 
469 }
470 
471 //======================================================================
473  edm::RunNumber_t run) const
474 {
475  const int index = moduleGroupSelector_->getParameterIndexFromDetId(detId, run);
476 
477  return (index < 0 ? 0. : parameters_[index]);
478 }
479 
480 //======================================================================
482  const std::map<unsigned int, TreeStruct> &treeInfo,
483  const char *treeName) const
484 {
485  if (!lorentzAngle) return;
486 
487  TFile* file = TFile::Open(outFileName_.c_str(), "UPDATE");
488  if (!file) {
489  edm::LogError("BadConfig") << "@SUB=SiStripLorentzAngleCalibration::writeTree"
490  << "Could not open file '" << outFileName_ << "'.";
491  return;
492  }
493 
494  TTree *tree = new TTree(treeName, treeName);
495  unsigned int id = 0;
496  float value = 0.;
497  TreeStruct treeStruct;
498  tree->Branch("detId", &id, "detId/i");
499  tree->Branch("value", &value, "value/F");
500  tree->Branch("treeStruct", &treeStruct, TreeStruct::LeafList());
501 
502  for (auto iterIdValue = lorentzAngle->getLorentzAngles().begin();
503  iterIdValue != lorentzAngle->getLorentzAngles().end(); ++iterIdValue) {
504  // type of (*iterIdValue) is pair<unsigned int, float>
505  id = iterIdValue->first; // key of map is DetId
506  value = iterIdValue->second;
507  // type of (*treeStructIter) is pair<unsigned int, TreeStruct>
508  auto treeStructIter = treeInfo.find(id); // find info for this id
509  if (treeStructIter != treeInfo.end()) {
510  treeStruct = treeStructIter->second; // info from input map
511  } else { // if none found, fill at least parameter index (using 1st IOV...)
512  const cond::Time_t run1of1stIov = moduleGroupSelector_->firstRunOfIOV(0);
513  const int ind = moduleGroupSelector_->getParameterIndexFromDetId(id, run1of1stIov);
514  treeStruct = TreeStruct(ind);
515  }
516  tree->Fill();
517  }
518  tree->Write();
519  delete file; // tree vanishes with the file...
520 }
521 
522 //======================================================================
524 SiStripLorentzAngleCalibration::createFromTree(const char *fileName, const char *treeName) const
525 {
526  // Check for file existence on your own to work around
527  // https://hypernews.cern.ch/HyperNews/CMS/get/swDevelopment/2715.html:
528  TFile* file = 0;
529  FILE* testFile = fopen(fileName,"r");
530  if (testFile) {
531  fclose(testFile);
532  file = TFile::Open(fileName, "READ");
533  } // else not existing, see error below
534 
535  TTree *tree = 0;
536  if (file) file->GetObject(treeName, tree);
537 
539  if (tree) {
540  unsigned int id = 0;
541  float value = 0.;
542  tree->SetBranchAddress("detId", &id);
543  tree->SetBranchAddress("value", &value);
544 
545  result = new SiStripLorentzAngle;
546  const Long64_t nEntries = tree->GetEntries();
547  for (Long64_t iEntry = 0; iEntry < nEntries; ++iEntry) {
548  tree->GetEntry(iEntry);
549  result->putLorentzAngle(id, value);
550  }
551  } else { // Warning only since could be parallel job on no events.
552  edm::LogWarning("Alignment") << "@SUB=SiStripLorentzAngleCalibration::createFromTree"
553  << "Could not get TTree '" << treeName << "' from file '"
554  << fileName << (file ? "'." : "' (file does not exist).");
555  }
556 
557  delete file; // tree will vanish with file
558  return result;
559 }
560 
561 
562 //======================================================================
563 //======================================================================
564 // Plugin definition
565 
567 
569  SiStripLorentzAngleCalibration, "SiStripLorentzAngleCalibration");
RunNumber_t run() const
Definition: EventID.h:39
edm::RunNumber_t firstRunOfIOV(unsigned int iovNum) const
First run of iov (0 if iovNum not treated).
int16_t singleReadOutMode() const
const std::vector< std::string > mergeFileNames_
SiStripLorentzAngleCalibration(const edm::ParameterSet &cfg)
Constructor.
const std::string & name() const
name of this calibration
def setup(process, global_tag, zero_tesla=False)
Definition: GeneralSetup.py:1
const Bounds & bounds() const
Definition: Surface.h:120
int getParameterIndexFromDetId(unsigned int detId, edm::RunNumber_t run) const
void writeTree(const SiStripLorentzAngle *lorentzAngle, const std::map< unsigned int, TreeStruct > &treeInfo, const char *treeName) const
const edm::EventID eventId() const
const Plane & surface() const
The nominal surface of the GeomDet.
Definition: GeomDet.h:42
virtual bool setParameter(unsigned int index, double value) override
double getParameterForDetId(unsigned int detId, edm::RunNumber_t run) const
define event information passed to algorithms
bool putLorentzAngle(const uint32_t &, float)
edm::ESWatcher< SiStripLorentzAngleRcd > watchLorentzAngleRcd_
static std::string const input
Definition: EdmProvDump.cc:44
structure to store algorithm results in a TTree
Definition: TreeStruct.h:6
const std::map< unsigned int, float > & getLorentzAngles() const
unsigned long long Time_t
Definition: Time.h:16
const GeomDet * det() const
LocalPoint toLocal(const GlobalPoint &gp) const
std::pair< Values, unsigned int > ValuesIndexPair
x- and y-values
bool isAvailable() const
Definition: Service.h:46
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)
Definition: value.py:1
virtual GlobalVector inTesla(const GlobalPoint &gp) const =0
Field value ad specified global point, in Tesla.
virtual double getParameterError(unsigned int index) const override
Detector identifier class for the strip tracker.
Definition: SiStripDetId.h:17
virtual double getParameter(unsigned int index) const override
virtual float thickness() const =0
std::pair< double, double > Values
const T & get() const
Definition: EventSetup.h:55
static const char * LeafList()
Definition: TreeStruct.h:17
double effectiveThickness(const GeomDet *det, int16_t mode, const edm::EventSetup &setup) const
in non-peak mode the effective thickness is reduced...
bool check(const edm::EventSetup &iSetup)
Definition: ESWatcher.h:57
bool checkLorentzAngleInput(const edm::EventSetup &setup, const EventInfo &eventInfo)
HLT enums.
virtual unsigned int numParameters() const override
How many parameters does this calibration define?
unsigned int getNumberOfParameters() const
virtual bool setParameterError(unsigned int index, double error) override
unsigned int numIovs() const
Total number of IOVs.
virtual void beginOfJob(AlignableTracker *tracker, AlignableMuon *muon, AlignableExtras *extras) override
#define DEFINE_EDM_PLUGIN(factory, type, name)
unsigned int RunNumber_t
eventInfo
add run, event number and lumi section
Definition: tree.py:1
virtual unsigned int derivatives(std::vector< ValuesIndexPair > &outDerivInds, const TransientTrackingRecHit &hit, const TrajectoryStateOnSurface &tsos, const edm::EventSetup &setup, const EventInfo &eventInfo) const override
Constructor of the full muon geometry.
Definition: AlignableMuon.h:37
const SiStripLorentzAngle * getLorentzAnglesInput()
latency
hardware algo
SiStripLorentzAngle * createFromTree(const char *fileName, const char *treeName) const
const PositionType & position() const