CMS 3D CMS Logo

SiPixelLorentzAnglePCLHarvester.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: CalibTracker/SiPixelLorentzAnglePCLHarvester
4 // Class: SiPixelLorentzAnglePCLHarvester
5 //
12 //
13 // Original Author: mmusich
14 // Created: Sat, 29 May 2021 14:46:19 GMT
15 //
16 //
17 
18 // system includes
19 #include <fmt/format.h>
20 #include <fmt/printf.h>
21 #include <fstream>
22 
23 // user includes
41 
42 /*
43  * Auxilliary struct to store fit results
44  */
45 namespace SiPixelLAHarvest {
46  struct fitResults {
47  public:
49  // set all parameters to default
50  p0 = p1 = p2 = p3 = p4 = p5 = 0.;
51  e0 = e1 = e2 = e3 = e4 = e5 = 0.;
52  chi2 = prob = redChi2 = tan_LA = error_LA = -9999.;
53  ndf = -999;
54  };
55 
56  double p0;
57  double e0;
58  double p1;
59  double e1;
60  double p2;
61  double e2;
62  double p3;
63  double e3;
64  double p4;
65  double e4;
66  double p5;
67  double e5;
68  double chi2;
69  int ndf;
70  double prob;
71  double redChi2;
72  double tan_LA;
73  double error_LA;
74  };
75 } // namespace SiPixelLAHarvest
76 
77 //------------------------------------------------------------------------------
79 public:
81  ~SiPixelLorentzAnglePCLHarvester() override = default;
82  void beginRun(const edm::Run&, const edm::EventSetup&) override;
83 
85 
86 private:
88  void endRun(const edm::Run&, const edm::EventSetup&) override;
89  void findMean(MonitorElement* h_drift_depth_adc_slice_, int i, int i_ring);
90  SiPixelLAHarvest::fitResults fitAndStore(std::shared_ptr<SiPixelLorentzAngle> theLA, int i_idx, int i_lay, int i_mod);
91 
92  // es tokens
97 
98  std::vector<std::string> newmodulelist_;
100  const double fitChi2Cut_;
101  const int minHitsCut_;
103  std::unique_ptr<TF1> f1;
104  float width_;
105 
109  std::unique_ptr<TrackerTopology> theTrackerTopology;
110 };
111 
112 //------------------------------------------------------------------------------
114  : geomEsToken_(esConsumes<edm::Transition::BeginRun>()),
115  topoEsTokenBR_(esConsumes<edm::Transition::BeginRun>()),
116  topoEsTokenER_(esConsumes<edm::Transition::EndRun>()),
117  siPixelLAEsToken_(esConsumes<edm::Transition::BeginRun>()),
118  magneticFieldToken_(esConsumes<edm::Transition::BeginRun>()),
119  newmodulelist_(iConfig.getParameter<std::vector<std::string>>("newmodulelist")),
120  dqmDir_(iConfig.getParameter<std::string>("dqmDir")),
121  fitChi2Cut_(iConfig.getParameter<double>("fitChi2Cut")),
122  minHitsCut_(iConfig.getParameter<int>("minHitsCut")),
123  recordName_(iConfig.getParameter<std::string>("record")) {
124  // first ensure DB output service is available
126  if (!poolDbService.isAvailable())
127  throw cms::Exception("SiPixelLorentzAnglePCLHarvester") << "PoolDBService required";
128 }
129 
130 //------------------------------------------------------------------------------
132  // geometry
133  const TrackerGeometry* geom = &iSetup.getData(geomEsToken_);
134  const TrackerTopology* tTopo = &iSetup.getData(topoEsTokenBR_);
135 
138 
140  hists.nlay = geom->numberOfLayers(PixelSubdetector::PixelBarrel);
141  hists.nModules_.resize(hists.nlay);
142  hists.nLadders_.resize(hists.nlay);
143  for (int i = 0; i < hists.nlay; i++) {
144  hists.nModules_[i] = map.getPXBModules(i + 1);
145  hists.nLadders_[i] = map.getPXBLadders(i + 1);
146  }
147 
148  // list of modules already filled, then return (we already entered here)
149  if (!hists.BPixnewDetIds_.empty() || !hists.FPixnewDetIds_.empty())
150  return;
151 
152  if (!newmodulelist_.empty()) {
153  for (auto const& modulename : newmodulelist_) {
154  if (modulename.find("BPix_") != std::string::npos) {
155  PixelBarrelName bn(modulename, true);
156  const auto& detId = bn.getDetId(tTopo);
157  hists.BPixnewmodulename_.push_back(modulename);
158  hists.BPixnewDetIds_.push_back(detId.rawId());
159  hists.BPixnewModule_.push_back(bn.moduleName());
160  hists.BPixnewLayer_.push_back(bn.layerName());
161  } else if (modulename.find("FPix_") != std::string::npos) {
162  PixelEndcapName en(modulename, true);
163  const auto& detId = en.getDetId(tTopo);
164  hists.FPixnewmodulename_.push_back(modulename);
165  hists.FPixnewDetIds_.push_back(detId.rawId());
166  hists.FPixnewDisk_.push_back(en.diskName());
167  hists.FPixnewBlade_.push_back(en.bladeName());
168  }
169  }
170  }
171 
172  uint count = 0;
173  for (const auto& id : hists.BPixnewDetIds_) {
174  LogDebug("SiPixelLorentzAnglePCLHarvester") << id;
175  count++;
176  }
177  LogDebug("SiPixelLorentzAnglePCLHarvester") << "Stored a total of " << count << " new detIds.";
178 
179  // list of modules already filled, return (we already entered here)
180  if (!hists.detIdsList.empty())
181  return;
182 
183  std::vector<uint32_t> treatedIndices;
184 
185  for (auto det : geom->detsPXB()) {
186  const PixelGeomDetUnit* pixelDet = dynamic_cast<const PixelGeomDetUnit*>(det);
187  width_ = pixelDet->surface().bounds().thickness();
188  const auto& layer = tTopo->pxbLayer(pixelDet->geographicalId());
189  const auto& module = tTopo->pxbModule(pixelDet->geographicalId());
190  int i_index = module + (layer - 1) * hists.nModules_[layer - 1];
191 
192  uint32_t rawId = pixelDet->geographicalId().rawId();
193 
194  // if the detId is already accounted for in the special class, do not attach it
195  if (std::find(hists.BPixnewDetIds_.begin(), hists.BPixnewDetIds_.end(), rawId) != hists.BPixnewDetIds_.end())
196  continue;
197 
198  if (std::find(treatedIndices.begin(), treatedIndices.end(), i_index) != treatedIndices.end()) {
199  hists.detIdsList[i_index].push_back(rawId);
200  } else {
201  hists.detIdsList.insert(std::pair<uint32_t, std::vector<uint32_t>>(i_index, {rawId}));
202  treatedIndices.push_back(i_index);
203  }
204  }
205 
206  count = 0;
207  for (const auto& i : treatedIndices) {
208  for (const auto& id : hists.detIdsList[i]) {
209  LogDebug("SiPixelLorentzAnglePCLHarvester") << id;
210  count++;
211  };
212  }
213  LogDebug("SiPixelLorentzAnglePCLHarvester") << "Stored a total of " << count << " detIds.";
214 }
215 
216 //------------------------------------------------------------------------------
218  if (!theTrackerTopology) {
219  theTrackerTopology = std::make_unique<TrackerTopology>(isetup.getData(topoEsTokenER_));
220  }
221 }
222 
223 //------------------------------------------------------------------------------
225  // go in the right directory
226  iGetter.cd();
227  iGetter.setCurrentFolder(dqmDir_);
228 
229  // fetch the 2D histograms
230  for (int i_layer = 1; i_layer <= hists.nlay; i_layer++) {
231  const auto& prefix_ = fmt::sprintf("%s/BPix/BPixLayer%i", dqmDir_, i_layer);
232  for (int i_module = 1; i_module <= hists.nModules_[i_layer - 1]; i_module++) {
233  int i_index = i_module + (i_layer - 1) * hists.nModules_[i_layer - 1];
234 
235  hists.h_drift_depth_[i_index] =
236  iGetter.get(fmt::format("{}/h_drift_depth_layer{}_module{}", prefix_, i_layer, i_module));
237 
238  if (hists.h_drift_depth_[i_index] == nullptr) {
239  edm::LogError("SiPixelLorentzAnglePCLHarvester::dqmEndJob")
240  << "Failed to retrieve electron drift over depth for layer " << i_layer << ", module " << i_module << ".";
241  continue;
242  }
243 
244  hists.h_drift_depth_adc_[i_index] =
245  iGetter.get(fmt::format("{}/h_drift_depth_adc_layer{}_module{}", prefix_, i_layer, i_module));
246 
247  hists.h_drift_depth_adc2_[i_index] =
248  iGetter.get(fmt::format("{}/h_drift_depth_adc2_layer{}_module{}", prefix_, i_layer, i_module));
249 
250  hists.h_drift_depth_noadc_[i_index] =
251  iGetter.get(fmt::format("{}/h_drift_depth_noadc_layer{}_module{}", prefix_, i_layer, i_module));
252 
253  hists.h_mean_[i_index] = iGetter.get(fmt::format("{}/h_mean_layer{}_module{}", dqmDir_, i_layer, i_module));
254 
255  hists.h_drift_depth_[i_index]->divide(
256  hists.h_drift_depth_adc_[i_index], hists.h_drift_depth_noadc_[i_index], 1., 1., "");
257  }
258  }
259 
260  // fetch the new modules 2D histograms
261  for (int i = 0; i < (int)hists.BPixnewDetIds_.size(); i++) {
262  int new_index = i + 1 + hists.nModules_[hists.nlay - 1] + (hists.nlay - 1) * hists.nModules_[hists.nlay - 1];
263 
264  hists.h_drift_depth_[new_index] = iGetter.get(
265  fmt::format("{}/h_BPixnew_drift_depth_{}", dqmDir_ + "/BPix/NewModules", hists.BPixnewmodulename_[i]));
266 
267  if (hists.h_drift_depth_[new_index] == nullptr) {
268  edm::LogError("SiPixelLorentzAnglePCLHarvester")
269  << "Failed to retrieve electron drift over depth for new module " << hists.BPixnewmodulename_[i] << ".";
270  continue;
271  }
272 
273  hists.h_drift_depth_adc_[new_index] = iGetter.get(
274  fmt::format("{}/h_BPixnew_drift_depth_adc_{}", dqmDir_ + "/BPix/NewModules", hists.BPixnewmodulename_[i]));
275 
276  hists.h_drift_depth_adc2_[new_index] = iGetter.get(
277  fmt::format("{}/h_BPixnew_drift_depth_adc2_{}", dqmDir_ + "/BPix/NewModules", hists.BPixnewmodulename_[i]));
278 
279  hists.h_drift_depth_noadc_[new_index] = iGetter.get(
280  fmt::format("{}/h_BPixnew_drift_depth_noadc_{}", dqmDir_ + "/BPix/NewModules", hists.BPixnewmodulename_[i]));
281 
282  hists.h_mean_[new_index] = iGetter.get(fmt::format("{}/h_BPixnew_mean_{}", dqmDir_, hists.BPixnewmodulename_[i]));
283 
284  hists.h_drift_depth_[new_index]->divide(
285  hists.h_drift_depth_adc_[new_index], hists.h_drift_depth_noadc_[new_index], 1., 1., "");
286  }
287 
288  hists.h_bySectOccupancy_ = iGetter.get(fmt::format("{}/h_bySectorOccupancy", dqmDir_ + "/SectorMonitoring"));
289  if (hists.h_bySectOccupancy_ == nullptr) {
290  edm::LogError("SiPixelLorentzAnglePCLHarvester") << "Failed to retrieve the hit on track occupancy.";
291  return;
292  }
293 
294  int hist_drift_;
295  int hist_depth_;
296  double min_drift_;
297  double max_drift_;
298 
299  if (hists.h_drift_depth_adc_[1] != nullptr) {
300  hist_drift_ = hists.h_drift_depth_adc_[1]->getNbinsX();
301  hist_depth_ = hists.h_drift_depth_adc_[1]->getNbinsY();
302  min_drift_ = hists.h_drift_depth_adc_[1]->getAxisMin(1);
303  max_drift_ = hists.h_drift_depth_adc_[1]->getAxisMax(1);
304  } else {
305  hist_drift_ = 100;
306  hist_depth_ = 50;
307  min_drift_ = -500.;
308  max_drift_ = 500.;
309  }
310 
311  iBooker.setCurrentFolder(fmt::format("{}Harvesting", dqmDir_));
312  MonitorElement* h_drift_depth_adc_slice_ =
313  iBooker.book1D("h_drift_depth_adc_slice", "slice of adc histogram", hist_drift_, min_drift_, max_drift_);
314 
315  // book histogram of differences
316  MonitorElement* h_diffLA = iBooker.book1D(
317  "h_diffLA", "difference in #mu_{H}; #Delta #mu_{H}/#mu_{H} (old-new)/old [%];n. modules", 100, -150, 150);
318 
319  // retrieve the number of bins from the other monitoring histogram
320  const auto& maxSect = hists.h_bySectOccupancy_->getNbinsX();
321  const double lo = -0.5;
322  const double hi = maxSect - 0.5;
323 
324  // this will be booked in the Harvesting folder
325  iBooker.setCurrentFolder(fmt::format("{}Harvesting/SectorMonitoring", dqmDir_));
326  std::string repText = "%s tan#theta_{LA}/B by sector;pixel sector;%s tan(#theta_{LA})/B [1/T]";
328  iBooker.book1D("h_LAbySector_Measured", fmt::sprintf(repText, "measured", "measured"), maxSect, lo, hi);
330  iBooker.book1D("h_LAbySector_Accepted", fmt::sprintf(repText, "accepted", "accepted"), maxSect, lo, hi);
332  iBooker.book1D("h_LAbySector_Rejected", fmt::sprintf(repText, "rejected", "rejected"), maxSect, lo, hi);
333  hists.h_bySectLA_ = iBooker.book1D("h_LAbySector", fmt::sprintf(repText, "payload", "payload"), maxSect, lo, hi);
335  iBooker.book1D("h_deltaLAbySector", fmt::sprintf(repText, "#Delta", "#Delta"), maxSect, lo, hi);
337  iBooker.book1D("h_bySectorChi2", "Fit #chi^{2}/ndf by sector;pixel sector; fit #chi^{2}/ndf", maxSect, lo, hi);
338 
339  // copy the bin labels from the occupancy histogram
340  for (int bin = 1; bin <= maxSect; bin++) {
341  const auto& binName = hists.h_bySectOccupancy_->getTH1()->GetXaxis()->GetBinLabel(bin);
343  hists.h_bySectSetLA_->setBinLabel(bin, binName);
345  hists.h_bySectLA_->setBinLabel(bin, binName);
347  hists.h_bySectChi2_->setBinLabel(bin, binName);
348  }
349 
350  // this will be booked in the Harvesting folder
351  iBooker.setCurrentFolder(fmt::format("{}Harvesting/LorentzAngleMaps", dqmDir_));
352  for (int i = 0; i < hists.nlay; i++) {
353  std::string repName = "h2_byLayerLA_%i";
354  std::string repText = "BPix Layer %i tan#theta_{LA}/B;module number;ladder number;tan#theta_{LA}/B [1/T]";
355 
356  hists.h2_byLayerLA_.emplace_back(iBooker.book2D(fmt::sprintf(repName, i + 1),
357  fmt::sprintf(repText, i + 1),
358  hists.nModules_[i],
359  0.5,
360  hists.nModules_[i] + 0.5,
361  hists.nLadders_[i],
362  0.5,
363  hists.nLadders_[i] + 0.5));
364 
365  repName = "h2_byLayerDiff_%i";
366  repText = "BPix Layer %i #Delta#mu_{H}/#mu_{H};module number;ladder number;#Delta#mu_{H}/#mu_{H} [%%]";
367  hists.h2_byLayerDiff_.emplace_back(iBooker.book2D(fmt::sprintf(repName, i + 1),
368  fmt::sprintf(repText, i + 1),
369  hists.nModules_[i],
370  0.5,
371  hists.nModules_[i] + 0.5,
372  hists.nLadders_[i],
373  0.5,
374  hists.nLadders_[i] + 0.5));
375  }
376 
377  // clang-format off
378  edm::LogPrint("LorentzAngle") << "module" << "\t" << "layer" << "\t"
379  << "offset" << "\t" << "e0" << "\t"
380  << "slope" << "\t" << "e1" << "\t"
381  << "rel.err" << "\t" << "pull" << "\t"
382  << "p2" << "\t" << "e2" << "\t"
383  << "p3" << "\t" << "e3" << "\t"
384  << "p4" << "\t" << "e4" << "\t"
385  << "p5" << "\t" << "e5" << "\t"
386  << "chi2" << "\t" << "prob" << "\t"
387  << "newDetId" << "\t" << "tan(LA)" << "\t"
388  << "Error(LA)" ;
389  // clang-format on
390 
391  // payload to be written out
392  std::shared_ptr<SiPixelLorentzAngle> LorentzAngle = std::make_shared<SiPixelLorentzAngle>();
393 
394  // fill the map of simulation values
395  double p1_simul_newmodule = 0.294044;
396  double p1_simul[hists.nlay + 1][hists.nModules_[hists.nlay - 1]];
397  for (int i_layer = 1; i_layer <= hists.nlay; i_layer++) {
398  for (int i_module = 1; i_module <= hists.nModules_[i_layer - 1]; i_module++) {
399  if (i_layer == 1)
400  p1_simul[i_layer - 1][i_module - 1] = 0.436848;
401  else if (i_layer == 2)
402  p1_simul[i_layer - 1][i_module - 1] = 0.25802;
403  else if (i_layer == 3 && i_module <= 4)
404  p1_simul[i_layer - 1][i_module - 1] = 0.29374;
405  else if (i_layer == 3 && i_module >= 5)
406  p1_simul[i_layer - 1][i_module - 1] = 0.31084;
407  else if (i_layer == 4 && i_module <= 4)
408  p1_simul[i_layer - 1][i_module - 1] = 0.29944;
409  else
410  p1_simul[i_layer - 1][i_module - 1] = 0.31426;
411  }
412  }
413  // fictitious n-th layer to store the values of new modules
414  for (int i_module = 1; i_module <= hists.nModules_[hists.nlay - 1]; i_module++) {
415  p1_simul[hists.nlay][i_module - 1] = p1_simul_newmodule;
416  }
417 
418  // loop over "new" BPix modules
419  for (int j = 0; j < (int)hists.BPixnewDetIds_.size(); j++) {
420  //uint32_t rawId = hists.BPixnewDetIds_[j];
421  int new_index = j + 1 + hists.nModules_[hists.nlay - 1] + (hists.nlay - 1) * hists.nModules_[hists.nlay - 1];
422  if (hists.h_drift_depth_adc_[new_index] == nullptr)
423  continue;
424  for (int i = 1; i <= hist_depth_; i++) {
425  findMean(h_drift_depth_adc_slice_, i, new_index);
426  }
427 
428  // fit the distributions and store the LA in the payload
429  const auto& res = fitAndStore(LorentzAngle, new_index, hists.BPixnewLayer_[j], hists.BPixnewModule_[j]);
430 
431  edm::LogPrint("SiPixelLorentzAngle") << std::setprecision(4) << hists.BPixnewModule_[j] << "\t"
432  << hists.BPixnewLayer_[j] << "\t" << res.p0 << "\t" << res.e0 << "\t" << res.p1
433  << std::setprecision(3) << "\t" << res.e1 << "\t" << res.e1 / res.p1 * 100.
434  << "\t" << (res.p1 - p1_simul[hists.nlay][0]) / res.e1 << "\t" << res.p2
435  << "\t" << res.e2 << "\t" << res.p3 << "\t" << res.e3 << "\t" << res.p4 << "\t"
436  << res.e4 << "\t" << res.p5 << "\t" << res.e5 << "\t" << res.chi2 << "\t"
437  << res.prob << "\t" << hists.BPixnewDetIds_[j] << "\t" << res.tan_LA << "\t"
438  << res.error_LA;
439  } // loop on BPix new modules
440 
441  //loop over modules and layers to fit the lorentz angle
442  for (int i_layer = 1; i_layer <= hists.nlay; i_layer++) {
443  for (int i_module = 1; i_module <= hists.nModules_[i_layer - 1]; i_module++) {
444  int i_index = i_module + (i_layer - 1) * hists.nModules_[i_layer - 1];
445  if (hists.h_drift_depth_adc_[i_index] == nullptr)
446  continue;
447  //loop over bins in depth (z-local-coordinate) (in order to fit slices)
448  for (int i = 1; i <= hist_depth_; i++) {
449  findMean(h_drift_depth_adc_slice_, i, i_index);
450  } // end loop over bins in depth
451 
452  // fit the distributions and store the LA in the payload
453  const auto& res = fitAndStore(LorentzAngle, i_index, i_layer, i_module);
454 
455  edm::LogPrint("SiPixelLorentzAngle")
456  << std::setprecision(4) << i_module << "\t" << i_layer << "\t" << res.p0 << "\t" << res.e0 << "\t" << res.p1
457  << std::setprecision(3) << "\t" << res.e1 << "\t" << res.e1 / res.p1 * 100. << "\t"
458  << (res.p1 - p1_simul[i_layer - 1][i_module - 1]) / res.e1 << "\t" << res.p2 << "\t" << res.e2 << "\t"
459  << res.p3 << "\t" << res.e3 << "\t" << res.p4 << "\t" << res.e4 << "\t" << res.p5 << "\t" << res.e5 << "\t"
460  << res.chi2 << "\t" << res.prob << "\t"
461  << "null"
462  << "\t" << res.tan_LA << "\t" << res.error_LA;
463  }
464  } // end loop over modules and layers
465 
466  // fill the rest of DetIds not filled above (for the moment FPix)
467  const auto& currentLAMap = currentLorentzAngle->getLorentzAngles();
468  const auto& newLAMap = LorentzAngle->getLorentzAngles();
469  std::vector<unsigned int> currentLADets;
470  std::vector<unsigned int> newLADets;
471 
472  std::transform(currentLAMap.begin(),
473  currentLAMap.end(),
474  std::back_inserter(currentLADets),
475  [](const std::map<unsigned int, float>::value_type& pair) { return pair.first; });
476 
477  std::transform(newLAMap.begin(),
478  newLAMap.end(),
479  std::back_inserter(newLADets),
480  [](const std::map<unsigned int, float>::value_type& pair) { return pair.first; });
481 
482  std::vector<unsigned int> notCommon;
483  std::set_symmetric_difference(
484  currentLADets.begin(), currentLADets.end(), newLADets.begin(), newLADets.end(), std::back_inserter(notCommon));
485 
486  for (const auto& id : notCommon) {
487  float fPixLorentzAnglePerTesla_ = currentLorentzAngle->getLorentzAngle(id);
488  if (!LorentzAngle->putLorentzAngle(id, fPixLorentzAnglePerTesla_)) {
489  edm::LogError("SiPixelLorentzAnglePCLHarvester")
490  << "[SiPixelLorentzAnglePCLHarvester::dqmEndJob] filling rest of payload: detid already exists";
491  }
492  }
493 
494  for (const auto& id : newLADets) {
495  float deltaMuHoverMuH = (currentLorentzAngle->getLorentzAngle(id) - LorentzAngle->getLorentzAngle(id)) /
497  h_diffLA->Fill(deltaMuHoverMuH * 100.f);
498  }
499 
500  // fill the 2D output Lorentz Angle maps
501  for (const auto& [id, value] : LorentzAngle->getLorentzAngles()) {
502  DetId ID = DetId(id);
503  if (ID.subdetId() == PixelSubdetector::PixelBarrel) {
504  const auto& layer = theTrackerTopology->pxbLayer(id);
505  const auto& ladder = theTrackerTopology->pxbLadder(id);
506  const auto& module = theTrackerTopology->pxbModule(id);
507  hists.h2_byLayerLA_[layer - 1]->setBinContent(module, ladder, value);
508 
509  float deltaMuHoverMuH =
511  hists.h2_byLayerDiff_[layer - 1]->setBinContent(module, ladder, deltaMuHoverMuH * 100.f);
512  }
513  }
514 
515  // fill the DB object record
517  if (mydbservice.isAvailable()) {
518  try {
519  mydbservice->writeOneIOV(*LorentzAngle, mydbservice->currentTime(), recordName_);
520  } catch (const cond::Exception& er) {
521  edm::LogError("SiPixelLorentzAngleDB") << er.what();
522  } catch (const std::exception& er) {
523  edm::LogError("SiPixelLorentzAngleDB") << "caught std::exception " << er.what();
524  }
525  } else {
526  edm::LogError("SiPixelLorentzAngleDB") << "Service is unavailable";
527  }
528 }
529 
530 //------------------------------------------------------------------------------
531 void SiPixelLorentzAnglePCLHarvester::findMean(MonitorElement* h_drift_depth_adc_slice_, int i, int i_ring) {
532  double nentries = 0;
533  h_drift_depth_adc_slice_->Reset();
534  int hist_drift_ = h_drift_depth_adc_slice_->getNbinsX();
535 
536  // determine sigma and sigma^2 of the adc counts and average adc counts
537  //loop over bins in drift width
538  for (int j = 1; j <= hist_drift_; j++) {
539  if (hists.h_drift_depth_noadc_[i_ring]->getBinContent(j, i) >= 1) {
540  double adc_error2 = (hists.h_drift_depth_adc2_[i_ring]->getBinContent(j, i) -
541  hists.h_drift_depth_adc_[i_ring]->getBinContent(j, i) *
542  hists.h_drift_depth_adc_[i_ring]->getBinContent(j, i) /
543  hists.h_drift_depth_noadc_[i_ring]->getBinContent(j, i)) /
544  hists.h_drift_depth_noadc_[i_ring]->getBinContent(j, i);
545 
546  hists.h_drift_depth_adc_[i_ring]->setBinError(j, i, sqrt(adc_error2));
547  double error2 = adc_error2 / (hists.h_drift_depth_noadc_[i_ring]->getBinContent(j, i) - 1.);
548  hists.h_drift_depth_[i_ring]->setBinError(j, i, sqrt(error2));
549  } else {
550  hists.h_drift_depth_[i_ring]->setBinError(j, i, 0);
551  hists.h_drift_depth_adc_[i_ring]->setBinError(j, i, 0);
552  }
553  h_drift_depth_adc_slice_->setBinContent(j, hists.h_drift_depth_adc_[i_ring]->getBinContent(j, i));
554  h_drift_depth_adc_slice_->setBinError(j, hists.h_drift_depth_adc_[i_ring]->getBinError(j, i));
555  nentries += hists.h_drift_depth_noadc_[i_ring]->getBinContent(j, i);
556  } // end loop over bins in drift width
557 
558  double mean = h_drift_depth_adc_slice_->getMean(1);
559  double error = 0;
560  if (nentries != 0) {
561  error = h_drift_depth_adc_slice_->getRMS(1) / std::sqrt(nentries);
562  }
563  hists.h_mean_[i_ring]->setBinContent(i, mean);
564  hists.h_mean_[i_ring]->setBinError(i, error);
565 
566  h_drift_depth_adc_slice_->Reset(); // clear again after extracting the parameters
567 }
568 
569 //------------------------------------------------------------------------------
571  std::shared_ptr<SiPixelLorentzAngle> theLAPayload, int i_index, int i_layer, int i_module) {
572  // output results
574 
575  // B-field value
576  // nominalValue returns the magnetic field value in kgauss (1T = 10 kgauss)
577  float theMagField = magField->nominalValue() / 10.;
578 
579  double half_width = width_ * 10000 / 2; // pixel half thickness in units of micro meter
580 
581  f1 = std::make_unique<TF1>("f1", "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + [5]*x*x*x*x*x", 5., 280.);
582  f1->SetParName(0, "offset");
583  f1->SetParName(1, "tan#theta_{LA}");
584  f1->SetParName(2, "quad term");
585  f1->SetParName(3, "cubic term");
586  f1->SetParName(4, "quartic term");
587  f1->SetParName(5, "quintic term");
588 
589  f1->SetParameter(0, 0);
590  f1->SetParError(0, 0);
591  f1->SetParameter(1, 0.4);
592  f1->SetParError(1, 0);
593  f1->SetParameter(2, 0.0);
594  f1->SetParError(2, 0);
595  f1->SetParameter(3, 0.0);
596  f1->SetParError(3, 0);
597  f1->SetParameter(4, 0.0);
598  f1->SetParError(4, 0);
599  f1->SetParameter(5, 0.0);
600  f1->SetParError(5, 0);
601  f1->SetChisquare(0);
602 
603  hists.h_mean_[i_index]->getTH1()->Fit(f1.get(), "ERQ");
604 
605  res.p0 = f1->GetParameter(0);
606  res.e0 = f1->GetParError(0);
607  res.p1 = f1->GetParameter(1);
608  res.e1 = f1->GetParError(1);
609  res.p2 = f1->GetParameter(2);
610  res.e2 = f1->GetParError(2);
611  res.p3 = f1->GetParameter(3);
612  res.e3 = f1->GetParError(3);
613  res.p4 = f1->GetParameter(4);
614  res.e4 = f1->GetParError(4);
615  res.p5 = f1->GetParameter(5);
616  res.e5 = f1->GetParError(5);
617  res.chi2 = f1->GetChisquare();
618  res.ndf = f1->GetNDF();
619  res.prob = f1->GetProb();
620  res.redChi2 = res.ndf > 0. ? res.chi2 / res.ndf : 0.;
621 
622  double f1_halfwidth = res.p0 + res.p1 * half_width + res.p2 * pow(half_width, 2) + res.p3 * pow(half_width, 3) +
623  res.p4 * pow(half_width, 4) + res.p5 * pow(half_width, 5);
624 
625  double f1_zerowidth = res.p0;
626 
627  // tan_LA = (f1(x = half_width) - f1(x = 0)) / (half_width - 0)
628  res.tan_LA = (f1_halfwidth - f1_zerowidth) / half_width;
629  double errsq_LA =
630  (pow(res.e1, 2) + pow((half_width * res.e2), 2) + pow((half_width * half_width * res.e3), 2) +
631  pow((half_width * half_width * half_width * res.e4), 2) +
632  pow((half_width * half_width * half_width * half_width * res.e5), 2)); // Propagation of uncertainty
633  res.error_LA = sqrt(errsq_LA);
634 
635  hists.h_bySectMeasLA_->setBinContent(i_index, (res.tan_LA / theMagField));
636  hists.h_bySectMeasLA_->setBinError(i_index, (res.error_LA / theMagField));
637  hists.h_bySectChi2_->setBinContent(i_index, res.redChi2);
638  hists.h_bySectChi2_->setBinError(i_index, 0.); // no errors
639 
640  int nentries = hists.h_bySectOccupancy_->getBinContent(i_index); // number of on track hits in that sector
641 
642  bool isNew = (i_index > hists.nlay * hists.nModules_[hists.nlay - 1]);
643  int shiftIdx = i_index - hists.nlay * hists.nModules_[hists.nlay - 1] - 1;
644 
645  LogDebug("SiPixelLorentzAnglePCLHarvester")
646  << " isNew: " << isNew << " i_index: " << i_index << " shift index: " << shiftIdx;
647 
648  const auto& detIdsToFill =
649  isNew ? std::vector<unsigned int>({hists.BPixnewDetIds_[shiftIdx]}) : hists.detIdsList[i_index];
650 
651  LogDebug("SiPixelLorentzAnglePCLHarvester")
652  << "index: " << i_index << " i_module: " << i_module << " i_layer: " << i_layer;
653  for (const auto& id : detIdsToFill) {
654  LogDebug("SiPixelLorentzAnglePCLHarvester") << id << ",";
655  }
656 
657  // no errors on the following MEs
658  hists.h_bySectSetLA_->setBinError(i_index, 0.);
659  hists.h_bySectRejectLA_->setBinError(i_index, 0.);
660  hists.h_bySectLA_->setBinError(i_index, 0.);
661  hists.h_bySectDeltaLA_->setBinError(i_index, 0.);
662 
663  float LorentzAnglePerTesla_;
664  float currentLA = currentLorentzAngle->getLorentzAngle(detIdsToFill.front());
665  // if the fit quality is OK
666  if ((res.redChi2 != 0.) && (res.redChi2 < fitChi2Cut_) && (nentries > minHitsCut_)) {
667  LorentzAnglePerTesla_ = res.tan_LA / theMagField;
668  // fill the LA actually written to payload
669  hists.h_bySectSetLA_->setBinContent(i_index, LorentzAnglePerTesla_);
670  hists.h_bySectRejectLA_->setBinContent(i_index, 0.);
671  hists.h_bySectLA_->setBinContent(i_index, LorentzAnglePerTesla_);
672 
673  const auto& deltaLA = (LorentzAnglePerTesla_ - currentLA);
674  hists.h_bySectDeltaLA_->setBinContent(i_index, deltaLA);
675 
676  for (const auto& id : detIdsToFill) {
677  if (!theLAPayload->putLorentzAngle(id, LorentzAnglePerTesla_)) {
678  edm::LogError("SiPixelLorentzAnglePCLHarvester") << "[SiPixelLorentzAnglePCLHarvester::fitAndStore]: detid ("
679  << i_layer << "," << i_module << ") already exists";
680  }
681  }
682  } else {
683  // just copy the values from the existing payload
684  hists.h_bySectSetLA_->setBinContent(i_index, 0.);
685  hists.h_bySectRejectLA_->setBinContent(i_index, (res.tan_LA / theMagField));
686  hists.h_bySectLA_->setBinContent(i_index, currentLA);
687  hists.h_bySectDeltaLA_->setBinContent(i_index, 0.);
688 
689  for (const auto& id : detIdsToFill) {
690  LorentzAnglePerTesla_ = currentLorentzAngle->getLorentzAngle(id);
691  if (!theLAPayload->putLorentzAngle(id, LorentzAnglePerTesla_)) {
692  edm::LogError("SiPixelLorentzAnglePCLHarvester") << "[SiPixelLorentzAnglePCLHarvester::fitAndStore]: detid ("
693  << i_layer << "," << i_module << ") already exists";
694  }
695  }
696  }
697  // return the struct of fit details
698  return res;
699 }
700 
701 //------------------------------------------------------------------------------
704  desc.setComment("Harvester module of the SiPixel Lorentz Angle PCL monitoring workflow");
705  desc.add<std::vector<std::string>>("newmodulelist", {})->setComment("the list of DetIds for new sensors");
706  desc.add<std::string>("dqmDir", "AlCaReco/SiPixelLorentzAngle")->setComment("the directory of PCL Worker output");
707  desc.add<double>("fitChi2Cut", 20.)->setComment("cut on fit chi2/ndof to accept measurement");
708  desc.add<int>("minHitsCut", 10000)->setComment("cut on minimum number of on-track hits to accept measurement");
709  desc.add<std::string>("record", "SiPixelLorentzAngleRcd")->setComment("target DB record");
710  descriptions.addWithDefaultLabel(desc);
711 }
712 
std::vector< dqm::reco::MonitorElement * > h2_byLayerLA_
void addWithDefaultLabel(ParameterSetDescription const &psetDescription)
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
unsigned int pxbLayer(const DetId &id) const
Base exception class for the object to relational access.
Definition: Exception.h:11
virtual void setCurrentFolder(std::string const &fullpath)
Definition: DQMStore.cc:32
void beginRun(const edm::Run &, const edm::EventSetup &) override
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
int bladeName() const
blade id
edm::ESGetToken< TrackerTopology, TrackerTopologyRcd > topoEsTokenBR_
int moduleName() const
module id (index in z)
uint32_t ID
Definition: Definitions.h:24
void findMean(MonitorElement *h_drift_depth_adc_slice_, int i, int i_ring)
SiPixelLorentzAnglePCLHarvester(const edm::ParameterSet &)
SiPixelLAHarvest::fitResults fitAndStore(std::shared_ptr< SiPixelLorentzAngle > theLA, int i_idx, int i_lay, int i_mod)
edm::ESGetToken< TrackerTopology, TrackerTopologyRcd > topoEsTokenER_
const std::map< unsigned int, float > & getLorentzAngles() const
SiPixelLorentzAngleCalibrationHistograms hists
Log< level::Error, false > LogError
static void fillDescriptions(edm::ConfigurationDescriptions &)
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
Definition: Electron.h:6
constexpr std::array< uint8_t, layerIndexSize > layer
void Fill(long long x)
virtual float thickness() const =0
~SiPixelLorentzAnglePCLHarvester() override=default
virtual void Reset()
Remove all data from the ME, keept the empty histogram with all its settings.
edm::ESGetToken< SiPixelLorentzAngle, SiPixelLorentzAngleRcd > siPixelLAEsToken_
virtual double getRMS(int axis=1) const
get RMS of histogram along x, y or z axis (axis=1, 2, 3 respectively)
Definition: EPCuts.h:4
int diskName() const
disk id
T sqrt(T t)
Definition: SSEVec.h:19
std::unordered_map< uint32_t, std::vector< uint32_t > > detIdsList
edm::ESGetToken< TrackerGeometry, TrackerDigiGeometryRecord > geomEsToken_
Hash writeOneIOV(const T &payload, Time_t time, const std::string &recordName)
Transition
Definition: Transition.h:12
double f[11][100]
bool getData(T &iHolder) const
Definition: EventSetup.h:122
std::unique_ptr< TrackerTopology > theTrackerTopology
Definition: value.py:1
virtual void setBinLabel(int bin, const std::string &label, int axis=1)
set bin label for x, y or z axis (axis=1, 2, 3 respectively)
DetId geographicalId() const
The label of this GeomDet.
Definition: GeomDet.h:64
Log< level::Warning, true > LogPrint
PXFDetId getDetId()
return DetId
Definition: DetId.h:17
const Plane & surface() const
The nominal surface of the GeomDet.
Definition: GeomDet.h:37
virtual void setBinContent(int binx, double content)
set content of bin (1-D)
constexpr uint32_t rawId() const
get the raw id
Definition: DetId.h:57
int layerName() const
layer id
MonitorElement * book2D(TString const &name, TString const &title, int nchX, double lowX, double highX, int nchY, double lowY, double highY, FUNC onbooking=NOOP())
Definition: DQMStore.h:212
virtual MonitorElement * get(std::string const &fullpath) const
Definition: DQMStore.cc:673
virtual double getMean(int axis=1) const
get mean value of histogram along x, y or z axis (axis=1, 2, 3 respectively)
HLT enums.
virtual int getNbinsX() const
get # of bins in X-axis
int nominalValue() const
The nominal field value for this map in kGauss.
Definition: MagneticField.h:49
bool isAvailable() const
Definition: Service.h:40
virtual void setBinError(int binx, double error)
set uncertainty on content of bin (1-D)
unsigned int pxbModule(const DetId &id) const
MonitorElement * book1D(TString const &name, TString const &title, int const nchX, double const lowX, double const highX, FUNC onbooking=NOOP())
Definition: DQMStore.h:98
char const * what() const noexcept override
Definition: Exception.cc:103
float getLorentzAngle(const uint32_t &) const
edm::ESGetToken< MagneticField, IdealMagneticFieldRecord > magneticFieldToken_
PXBDetId getDetId()
return the DetId
std::vector< dqm::reco::MonitorElement * > h2_byLayerDiff_
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29
void endRun(const edm::Run &, const edm::EventSetup &) override
Definition: Run.h:45
void dqmEndJob(DQMStore::IBooker &, DQMStore::IGetter &) override
#define LogDebug(id)
virtual double getBinContent(int binx) const
get content of bin (1-D)
const Bounds & bounds() const
Definition: Surface.h:87
unsigned transform(const HcalDetId &id, unsigned transformCode)