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 
36 
41 
42 #include "TTree.h"
43 #include "TFile.h"
44 #include "TString.h"
45 
46 #include <vector>
47 #include <map>
48 #include <sstream>
49 #include <cstdio>
50 #include <memory>
51 #include <functional>
52 
54 public:
57 
59  ~SiStripLorentzAngleCalibration() override = default;
60 
62  unsigned int numParameters() const override;
63 
66  unsigned int derivatives(std::vector<ValuesIndexPair> &outDerivInds,
68  const TrajectoryStateOnSurface &tsos,
69  const edm::EventSetup &setup,
70  const EventInfo &eventInfo) const override;
71 
74  bool setParameter(unsigned int index, double value) override;
75 
78  bool setParameterError(unsigned int index, double error) override;
79 
82  double getParameter(unsigned int index) const override;
83 
86  double getParameterError(unsigned int index) const override;
87 
88  // /// Call at beginning of job:
90 
92  void beginRun(const edm::Run &, const edm::EventSetup &) override;
93 
96  void endOfJob() override;
97 
98 private:
104  double effectiveThickness(const GeomDet *det, int16_t mode, const edm::EventSetup &setup) const;
105 
108  double getParameterForDetId(unsigned int detId, edm::RunNumber_t run) const;
109 
110  void writeTree(const SiStripLorentzAngle *lorentzAngle,
111  const std::map<unsigned int, TreeStruct> &treeInfo,
112  const char *treeName) const;
113  SiStripLorentzAngle createFromTree(const char *fileName, const char *treeName) const;
114 
116  int16_t readoutMode_;
117  const bool saveToDB_;
120  const std::vector<std::string> mergeFileNames_;
121 
123 
124  std::map<align::RunNumber, SiStripLorentzAngle> cachedLorentzAngleInputs_;
127 
128  std::vector<double> parameters_;
129  std::vector<double> paramUncertainties_;
130 
131  std::unique_ptr<TkModuleGroupSelector> moduleGroupSelector_;
133 
138 };
139 
140 //======================================================================
141 //======================================================================
142 //======================================================================
143 
146  readoutModeName_(cfg.getParameter<std::string>("readoutMode")),
147  saveToDB_(cfg.getParameter<bool>("saveToDB")),
148  recordNameDBwrite_(cfg.getParameter<std::string>("recordNameDBwrite")),
149  outFileName_(cfg.getParameter<std::string>("treeFile")),
150  mergeFileNames_(cfg.getParameter<std::vector<std::string> >("mergeTreeFiles")),
151  moduleGroupSelCfg_(cfg.getParameter<edm::ParameterSet>("LorentzAngleModuleGroups")),
152  latencyToken_(iC.esConsumes()),
153  lorentzAngleToken_(iC.esConsumes<edm::Transition::BeginRun>(edm::ESInputTag("", readoutModeName_))),
154  magFieldToken_(iC.esConsumes()),
155  backPlaneCorrToken_(iC.esConsumes(edm::ESInputTag("", readoutModeName_))) {
156  // SiStripLatency::singleReadOutMode() returns
157  // 1: all in peak, 0: all in deco, -1: mixed state
158  // (in principle one could treat even mixed state APV by APV...)
159  if (readoutModeName_ == "peak") {
161  } else if (readoutModeName_ == "deconvolution") {
163  } else {
164  throw cms::Exception("BadConfig") << "SiStripLorentzAngleCalibration:\n"
165  << "Unknown mode '" << readoutModeName_
166  << "', should be 'peak' or 'deconvolution' .\n";
167  }
168 }
169 
170 //======================================================================
171 unsigned int SiStripLorentzAngleCalibration::numParameters() const { return parameters_.size(); }
172 
173 //======================================================================
175  // no action needed if the LA record didn't change
177  return;
178 
179  const auto runNumber = run.run();
181 
182  // avoid infinite loop due to wrap-around of unsigned variable 'i' including
183  // arrow from i to zero and a nice smiley ;)
184  for (unsigned int i = moduleGroupSelector_->numIovs(); i-- > 0;) {
185  const auto firstRunOfIOV = moduleGroupSelector_->firstRunOfIOV(i);
186  if (runNumber >= firstRunOfIOV) {
187  firstRun = firstRunOfIOV;
188  break;
189  }
190  }
191 
192  const SiStripLorentzAngle *lorentzAngleHandle = &setup.getData(lorentzAngleToken_);
193  const auto &lorentzAngleRcd = setup.get<SiStripLorentzAngleRcd>();
195  cachedLorentzAngleInputs_.emplace(firstRun, SiStripLorentzAngle(*lorentzAngleHandle));
196  } else {
197  if (lorentzAngleRcd.validityInterval().first().eventID().run() > firstRun &&
198  lorentzAngleHandle->getLorentzAngles() // only bad if non-identical values
199  != cachedLorentzAngleInputs_[firstRun].getLorentzAngles()) { // (comparing maps)
200  // Maps are containers sorted by key, but comparison problems may arise from
201  // 'floating point comparison' problems (FIXME?)
202  throw cms::Exception("BadInput") << "Trying to cache SiStripLorentzAngle payload for a run (" << runNumber
203  << ") in an IOV (" << firstRun << ") that was already cached.\n"
204  << "The following record in your input database tag has an IOV "
205  << "boundary that does not match your IOV definition:\n"
206  << " - SiStripLorentzAngleRcd '" << lorentzAngleRcd.key().name() << "' (since "
207  << lorentzAngleRcd.validityInterval().first().eventID().run() << ")\n";
208  }
209  }
210 
213 }
214 
215 //======================================================================
216 unsigned int SiStripLorentzAngleCalibration::derivatives(std::vector<ValuesIndexPair> &outDerivInds,
218  const TrajectoryStateOnSurface &tsos,
219  const edm::EventSetup &setup,
220  const EventInfo &eventInfo) const {
221  outDerivInds.clear();
222 
223  const SiStripLatency *latency = &setup.getData(latencyToken_);
224  const int16_t mode = latency->singleReadOutMode();
225  if (mode == readoutMode_) {
226  if (hit.det()) { // otherwise 'constraint hit' or whatever
227 
228  const int index =
229  moduleGroupSelector_->getParameterIndexFromDetId(hit.det()->geographicalId(), eventInfo.eventId().run());
230  if (index >= 0) { // otherwise not treated
231  const MagneticField *magneticField = &setup.getData(magFieldToken_);
232  const GlobalVector bField(magneticField->inTesla(hit.det()->surface().position()));
233  const LocalVector bFieldLocal(hit.det()->surface().toLocal(bField));
234  const double dZ = this->effectiveThickness(hit.det(), mode, setup);
235  // shift due to LA: dx = tan(LA) * dz/2 = mobility * B_y * dz/2,
236  // '-' since we have derivative of the residual r = hit - trk and mu is part of trk model
237  // (see GF's presentation in alignment meeting 25.10.2012,
238  // https://indico.cern.ch/conferenceDisplay.py?confId=174266#2012-10-25)
239  // Hmm! StripCPE::fillParams() defines, together with
240  // StripCPE::driftDirection(...):
241  // drift.x = -mobility * by * thickness (full drift from backside)
242  // So '-' already comes from that, not from mobility being part of
243  // track model...
244  // GM: sign convention is the same as for pixel LA, i.e. adopt it here, too
245  const double xDerivative = bFieldLocal.y() * dZ * -0.5; // parameter is mobility!
246  const double yDerivative = bFieldLocal.x() * dZ * 0.5; // parameter is mobility!
247  if (xDerivative || yDerivative) { // If field is zero, this is zero: do not return it
248  const Values derivs{xDerivative, yDerivative};
249  outDerivInds.push_back(ValuesIndexPair(derivs, index));
250  }
251  }
252  } else {
253  edm::LogWarning("Alignment") << "@SUB=SiStripLorentzAngleCalibration::derivatives1"
254  << "Hit without GeomDet, skip!";
255  }
256  } else if (mode != kDeconvolutionMode && mode != kPeakMode) {
257  // warn only if unknown/mixed mode
258  edm::LogWarning("Alignment") << "@SUB=SiStripLorentzAngleCalibration::derivatives2"
259  << "Readout mode is " << mode << ", but looking for " << readoutMode_ << " ("
260  << readoutModeName_ << ").";
261  }
262 
263  return outDerivInds.size();
264 }
265 
266 //======================================================================
268  if (index >= parameters_.size()) {
269  return false;
270  } else {
272  return true;
273  }
274 }
275 
276 //======================================================================
278  if (index >= paramUncertainties_.size()) {
279  return false;
280  } else {
282  return true;
283  }
284 }
285 
286 //======================================================================
288  return (index >= parameters_.size() ? 0. : parameters_[index]);
289 }
290 
291 //======================================================================
293  return (index >= paramUncertainties_.size() ? 0. : paramUncertainties_[index]);
294 }
295 
296 //======================================================================
298  AlignableMuon * /*aliMuon*/,
299  AlignableExtras * /*aliExtras*/) {
300  //specify the sub-detectors for which the LA is determined
301  const std::vector<int> sdets = {SiStripDetId::TIB, SiStripDetId::TOB, SiStripDetId::TID, SiStripDetId::TEC};
302  moduleGroupSelector_ = std::make_unique<TkModuleGroupSelector>(aliTracker, moduleGroupSelCfg_, sdets);
303 
304  parameters_.resize(moduleGroupSelector_->getNumberOfParameters(), 0.);
305  paramUncertainties_.resize(moduleGroupSelector_->getNumberOfParameters(), 0.);
306 
307  edm::LogInfo("Alignment") << "@SUB=SiStripLorentzAngleCalibration"
308  << "Created with name " << this->name() << " for readout mode '" << readoutModeName_
309  << "',\n"
310  << this->numParameters() << " parameters to be determined."
311  << "\nsaveToDB = " << saveToDB_ << "\n outFileName = " << outFileName_
312  << "\n N(merge files) = " << mergeFileNames_.size()
313  << "\n number of IOVs = " << moduleGroupSelector_->numIovs();
314 
315  if (!mergeFileNames_.empty()) {
316  edm::LogInfo("Alignment") << "@SUB=SiStripLorentzAngleCalibration"
317  << "First file to merge: " << mergeFileNames_[0];
318  }
319 }
320 
321 //======================================================================
323  // loginfo output
324  std::ostringstream out;
325  out << "Parameter results for readout mode '" << readoutModeName_ << "'\n";
326  for (unsigned int iPar = 0; iPar < parameters_.size(); ++iPar) {
327  out << iPar << ": " << parameters_[iPar] << " +- " << paramUncertainties_[iPar] << "\n";
328  }
329  edm::LogInfo("Alignment") << "@SUB=SiStripLorentzAngleCalibration::endOfJob" << out.str();
330 
331  std::map<unsigned int, TreeStruct> treeInfo; // map of TreeStruct for each detId
332 
333  // now write 'input' tree
334  const std::string treeName{this->name() + '_' + readoutModeName_ + '_'};
335  std::vector<const SiStripLorentzAngle *> inputs{};
336  inputs.reserve(moduleGroupSelector_->numIovs());
337  for (unsigned int iIOV = 0; iIOV < moduleGroupSelector_->numIovs(); ++iIOV) {
338  const auto firstRunOfIOV = moduleGroupSelector_->firstRunOfIOV(iIOV);
339  inputs.push_back(this->getLorentzAnglesInput(firstRunOfIOV)); // never NULL
340  this->writeTree(inputs.back(),
341  treeInfo,
342  (treeName + "input_" + std::to_string(firstRunOfIOV)).c_str()); // empty treeInfo for input...
343 
344  if (inputs.back()->getLorentzAngles().empty()) {
345  edm::LogError("Alignment") << "@SUB=SiStripLorentzAngleCalibration::endOfJob"
346  << "Input Lorentz angle map is empty ('" << readoutModeName_
347  << "' mode), skip writing output!";
348  return;
349  }
350  }
351 
352  const unsigned int nonZeroParamsOrErrors = // Any determined value?
353  count_if(parameters_.begin(), parameters_.end(), [](auto c) { return c != 0.; }) +
354  count_if(paramUncertainties_.begin(), paramUncertainties_.end(), [](auto c) { return c != 0.; });
355 
356  for (unsigned int iIOV = 0; iIOV < moduleGroupSelector_->numIovs(); ++iIOV) {
357  auto firstRunOfIOV = static_cast<cond::Time_t>(moduleGroupSelector_->firstRunOfIOV(iIOV));
359  // Loop on map of values from input and add (possible) parameter results
360  for (const auto &iterIdValue : inputs[iIOV]->getLorentzAngles()) {
361  // type of 'iterIdValue' is pair<unsigned int, float>
362  const auto detId = iterIdValue.first; // key of map is DetId
363  // Some code one could use to miscalibrate wrt input:
364  // double param = 0.;
365  // const DetId id(detId);
366  // if (id.subdetId() == 3) { // TIB
367  // param = (readoutMode_ == kPeakMode ? -0.003 : -0.002);
368  // } else if (id.subdetId() == 5) { // TOB
369  // param = (readoutMode_ == kPeakMode ? 0.005 : 0.004);
370  // }
371  const double param = this->getParameterForDetId(detId, firstRunOfIOV);
372  // put result in output, i.e. sum of input and determined parameter:
373  auto value = iterIdValue.second + static_cast<float>(param);
374  output.putLorentzAngle(detId, value);
375  const int paramIndex = moduleGroupSelector_->getParameterIndexFromDetId(detId, firstRunOfIOV);
376  treeInfo[detId] = TreeStruct(param, this->getParameterError(paramIndex), paramIndex);
377  }
378 
379  if (saveToDB_ || nonZeroParamsOrErrors != 0) { // Skip writing mille jobs...
380  this->writeTree(&output, treeInfo, (treeName + Form("result_%lld", firstRunOfIOV)).c_str());
381  }
382 
383  if (saveToDB_) { // If requested, write out to DB
385  if (dbService.isAvailable()) {
386  dbService->writeOneIOV(output, firstRunOfIOV, recordNameDBwrite_);
387  } else {
388  edm::LogError("BadConfig") << "@SUB=SiStripLorentzAngleCalibration::endOfJob"
389  << "No PoolDBOutputService available, but saveToDB true!";
390  }
391  }
392  } // end loop on IOVs
393 }
394 
395 //======================================================================
397  int16_t mode,
398  const edm::EventSetup &setup) const {
399  if (!det)
400  return 0.;
401  double dZ = det->surface().bounds().thickness(); // it is a float only...
402  const SiStripDetId id(det->geographicalId());
403  const SiStripBackPlaneCorrection *backPlaneHandle = &setup.getData(backPlaneCorrToken_);
404  // FIXME: which one? DepRcd->get(handle) or Rcd->get(readoutModeName_, handle)??
405  // setup.get<SiStripBackPlaneCorrectionDepRcd>().get(backPlaneHandle); // get correct mode
406  const double bpCor = backPlaneHandle->getBackPlaneCorrection(id); // it's a float...
407  // std::cout << "bpCor " << bpCor << " in subdet " << id.subdetId() << std::endl;
408  dZ *= (1. - bpCor);
409 
410  return dZ;
411 }
412 
413 //======================================================================
415  const auto &resolvedRun = run > 0 ? run : currentIOV_;
416  // For parallel processing in Millepede II, create SiStripLorentzAngle
417  // from info stored in files of parallel jobs and check that they are identical.
418  // If this job has run on events, still check that LA is identical to the ones
419  // from mergeFileNames_.
420  const std::string treeName{this->name() + "_" + readoutModeName_ + "_input_" + std::to_string(resolvedRun)};
421  for (const auto &iFile : mergeFileNames_) {
422  auto la = this->createFromTree(iFile.c_str(), treeName.c_str());
423  // siStripLorentzAngleInput_ could be non-null from previous file of this loop
424  // or from checkLorentzAngleInput(..) when running on data in this job as well
426  cachedLorentzAngleInputs_[resolvedRun] = la;
428  currentIOV_ = resolvedRun;
429  } else {
430  // FIXME: about comparison of maps see comments in checkLorentzAngleInput
431  if (!la.getLorentzAngles().empty() && // single job might not have got events
432  la.getLorentzAngles() != siStripLorentzAngleInput_->getLorentzAngles()) {
433  // Throw exception instead of error?
434  edm::LogError("NoInput") << "@SUB=SiStripLorentzAngleCalibration::getLorentzAnglesInput"
435  << "Different input values from tree " << treeName << " in file " << iFile << ".";
436  }
437  }
438  }
439 
440  if (!siStripLorentzAngleInput_) { // no files nor ran on events
441  // [] operator default-constructs an empty SiStripLorentzAngle object in place:
443  currentIOV_ = resolvedRun;
444  edm::LogError("NoInput") << "@SUB=SiStripLorentzAngleCalibration::getLorentzAnglesInput"
445  << "No input, create an empty one ('" << readoutModeName_ << "' mode)!";
446  } else if (siStripLorentzAngleInput_->getLorentzAngles().empty()) {
447  edm::LogError("NoInput") << "@SUB=SiStripLorentzAngleCalibration::getLorentzAnglesInput"
448  << "Empty result ('" << readoutModeName_ << "' mode)!";
449  }
450 
452 }
453 
454 //======================================================================
456  const int index = moduleGroupSelector_->getParameterIndexFromDetId(detId, run);
457 
458  return (index < 0 ? 0. : parameters_[index]);
459 }
460 
461 //======================================================================
463  const std::map<unsigned int, TreeStruct> &treeInfo,
464  const char *treeName) const {
465  if (!lorentzAngle)
466  return;
467 
468  TFile *file = TFile::Open(outFileName_.c_str(), "UPDATE");
469  if (!file) {
470  edm::LogError("BadConfig") << "@SUB=SiStripLorentzAngleCalibration::writeTree"
471  << "Could not open file '" << outFileName_ << "'.";
472  return;
473  }
474 
475  TTree *tree = new TTree(treeName, treeName);
476  unsigned int id = 0;
477  float value = 0.;
478  TreeStruct treeStruct;
479  tree->Branch("detId", &id, "detId/i");
480  tree->Branch("value", &value, "value/F");
481  tree->Branch("treeStruct", &treeStruct, TreeStruct::LeafList());
482 
483  for (auto iterIdValue = lorentzAngle->getLorentzAngles().begin();
484  iterIdValue != lorentzAngle->getLorentzAngles().end();
485  ++iterIdValue) {
486  // type of (*iterIdValue) is pair<unsigned int, float>
487  id = iterIdValue->first; // key of map is DetId
488  value = iterIdValue->second;
489  // type of (*treeStructIter) is pair<unsigned int, TreeStruct>
490  auto treeStructIter = treeInfo.find(id); // find info for this id
491  if (treeStructIter != treeInfo.end()) {
492  treeStruct = treeStructIter->second; // info from input map
493  } else { // if none found, fill at least parameter index (using 1st IOV...)
494  const cond::Time_t run1of1stIov = moduleGroupSelector_->firstRunOfIOV(0);
495  const int ind = moduleGroupSelector_->getParameterIndexFromDetId(id, run1of1stIov);
496  treeStruct = TreeStruct(ind);
497  }
498  tree->Fill();
499  }
500  tree->Write();
501  delete file; // tree vanishes with the file...
502 }
503 
504 //======================================================================
506  // Check for file existence on your own to work around
507  // https://hypernews.cern.ch/HyperNews/CMS/get/swDevelopment/2715.html:
508  TFile *file = nullptr;
509  FILE *testFile = fopen(fileName, "r");
510  if (testFile) {
511  fclose(testFile);
512  file = TFile::Open(fileName, "READ");
513  } // else not existing, see error below
514 
515  TTree *tree = nullptr;
516  if (file)
517  file->GetObject(treeName, tree);
518 
520  if (tree) {
521  unsigned int id = 0;
522  float value = 0.;
523  tree->SetBranchAddress("detId", &id);
524  tree->SetBranchAddress("value", &value);
525 
526  const Long64_t nEntries = tree->GetEntries();
527  for (Long64_t iEntry = 0; iEntry < nEntries; ++iEntry) {
528  tree->GetEntry(iEntry);
529  result.putLorentzAngle(id, value);
530  }
531  } else { // Warning only since could be parallel job on no events.
532  edm::LogWarning("Alignment") << "@SUB=SiStripLorentzAngleCalibration::createFromTree"
533  << "Could not get TTree '" << treeName << "' from file '" << fileName
534  << (file ? "'." : "' (file does not exist).");
535  }
536 
537  delete file; // tree will vanish with file
538  return result;
539 }
540 
541 //======================================================================
542 //======================================================================
543 // Plugin definition
544 
546 
const TimeTypeSpecs timeTypeSpecs[]
Definition: Time.cc:16
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
void writeTree(const SiStripLorentzAngle *lorentzAngle, const std::map< unsigned int, TreeStruct > &treeInfo, const char *treeName) const
Time_t beginValue
Definition: Time.h:41
const edm::ESGetToken< MagneticField, IdealMagneticFieldRecord > magFieldToken_
static constexpr auto TID
Definition: SiStripDetId.h:38
const std::vector< std::string > mergeFileNames_
std::string to_string(const V &value)
Definition: OMSAccess.h:71
double getParameterError(unsigned int index) const override
const edm::ESGetToken< SiStripLorentzAngle, SiStripLorentzAngleRcd > lorentzAngleToken_
std::map< align::RunNumber, SiStripLorentzAngle > cachedLorentzAngleInputs_
Log< level::Error, false > LogError
bool setParameter(unsigned int index, double value) override
const GeomDet * det() const
define event information passed to algorithms
edm::ESWatcher< SiStripLorentzAngleRcd > watchLorentzAngleRcd_
double getParameter(unsigned int index) const override
const edm::ESGetToken< SiStripLatency, SiStripLatencyRcd > latencyToken_
virtual float thickness() const =0
structure to store algorithm results in a TTree
Definition: TreeStruct.h:6
unsigned long long Time_t
Definition: Time.h:14
~SiStripLorentzAngleCalibration() override=default
Destructor.
double effectiveThickness(const GeomDet *det, int16_t mode, const edm::EventSetup &setup) const
in non-peak mode the effective thickness is reduced...
std::pair< Values, unsigned int > ValuesIndexPair
x- and y-values
const edm::ESGetToken< SiStripBackPlaneCorrection, SiStripBackPlaneCorrectionRcd > backPlaneCorrToken_
Hash writeOneIOV(const T &payload, Time_t time, const std::string &recordName)
Transition
Definition: Transition.h:12
Definition: value.py:1
DetId geographicalId() const
The label of this GeomDet.
Definition: GeomDet.h:64
static constexpr auto TOB
Definition: SiStripDetId.h:39
SiStripLorentzAngle createFromTree(const char *fileName, const char *treeName) const
unsigned int derivatives(std::vector< ValuesIndexPair > &outDerivInds, const TransientTrackingRecHit &hit, const TrajectoryStateOnSurface &tsos, const edm::EventSetup &setup, const EventInfo &eventInfo) const override
std::pair< double, double > Values
Log< level::Info, false > LogInfo
Detector identifier class for the strip tracker.
Definition: SiStripDetId.h:18
const Plane & surface() const
The nominal surface of the GeomDet.
Definition: GeomDet.h:37
std::unique_ptr< TkModuleGroupSelector > moduleGroupSelector_
static const char * LeafList()
Definition: TreeStruct.h:16
void beginRun(const edm::Run &, const edm::EventSetup &) override
Call at beginning of run:
bool check(const edm::EventSetup &iSetup)
Definition: ESWatcher.h:57
static constexpr auto TIB
Definition: SiStripDetId.h:37
SiStripLorentzAngleCalibration(const edm::ParameterSet &cfg, edm::ConsumesCollector &iC)
Constructor.
const SiStripLorentzAngle * getLorentzAnglesInput(const align::RunNumber &=0)
HLT enums.
unsigned int numParameters() const override
How many parameters does this calibration define?
bool setParameterError(unsigned int index, double error) override
void beginOfJob(AlignableTracker *tracker, AlignableMuon *muon, AlignableExtras *extras) override
firstRun
Definition: dataset.py:940
#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
const std::map< unsigned int, float > & getLorentzAngles() const
Constructor of the full muon geometry.
Definition: AlignableMuon.h:38
const std::string & name() const
name of this calibration
static constexpr auto TEC
Definition: SiStripDetId.h:40
double getParameterForDetId(unsigned int detId, edm::RunNumber_t run) const
Definition: Run.h:45
cond::RealTimeType< cond::runnumber >::type RunNumber
Definition: Utilities.h:37
const Bounds & bounds() const
Definition: Surface.h:87