CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
HcalNoiseMonitor.cc
Go to the documentation of this file.
1 #include <cmath>
2 #include <fstream>
3 #include <algorithm>
4 
6 
11 
14 
19 
22 
24 
26 {
27  Online_ = ps.getUntrackedParameter<bool>("online",false);
28  mergeRuns_ = ps.getUntrackedParameter<bool>("mergeRuns",false);
29  enableCleanup_ = ps.getUntrackedParameter<bool>("enableCleanup",false);
30  debug_ = ps.getUntrackedParameter<int>("debug",0);
31  prefixME_ = ps.getUntrackedParameter<std::string>("subSystemFolder","Hcal/");
32  if(prefixME_.substr(prefixME_.size()-1,prefixME_.size())!="/")
33  prefixME_.append("/");
34  subdir_ = ps.getUntrackedParameter<std::string>("TaskFolder","NoiseMonitor_Hcal");
35  if(subdir_.size()>0 && subdir_.substr(subdir_.size()-1,subdir_.size())!="/")
36  subdir_.append("/");
37  subdir_=prefixME_+subdir_;
38  AllowedCalibTypes_ = ps.getUntrackedParameter<std::vector<int> > ("AllowedCalibTypes");
39  skipOutOfOrderLS_ = ps.getUntrackedParameter<bool>("skipOutOfOrderLS",false);
40  NLumiBlocks_ = ps.getUntrackedParameter<int>("NLumiBlocks",4000);
41  makeDiagnostics_ = ps.getUntrackedParameter<bool>("makeDiagnostics",false);
42 
43  triggers_=ps.getUntrackedParameter<std::vector<std::string> >("nzsHLTnames");
44  //["HLT_HcalPhiSym","HLT_HcalNoise_8E29]
45  period_=ps.getUntrackedParameter<int>("NoiseeventPeriod",4096); //4096
47  hltresultsLabel_ = ps.getUntrackedParameter<edm::InputTag>("HLTResultsLabel");
48  tok_hbhe_ = consumes<HBHEDigiCollection>(ps.getUntrackedParameter<edm::InputTag>("hbheDigiLabel"));
49  tok_hbherec_ = consumes<HBHERecHitCollection>(ps.getUntrackedParameter<edm::InputTag>("hbheRechitLabel"));
50  tok_noise_ = consumes<reco::HcalNoiseRBXCollection>(ps.getUntrackedParameter<edm::InputTag>("noiseLabel"));
51 
52  mTrianglePeakTS = 4; // for now...
53 
54  mE2E10MinEnergy = ps.getUntrackedParameter<double>("E2E10MinEnergy");
55  mMinE2E10 = ps.getUntrackedParameter<double>("MinE2E10");
56  mMaxE2E10 = ps.getUntrackedParameter<double>("MaxE2E10");
57  mMaxHPDHitCount = ps.getUntrackedParameter<int>("MaxHPDHitCount");
58  mMaxHPDNoOtherHitCount = ps.getUntrackedParameter<int>("MaxHPDNoOtherHitCount");
59  mMaxADCZeros = ps.getUntrackedParameter<int>("MaxADCZeros");
60  mTotalZeroMinEnergy = ps.getUntrackedParameter<double>("TotalZeroMinEnergy");
61  setupDone_ = false;
62 }
63 
65 
67 {
68 }
69 
71 {
72  if(debug_ > 1)
73  std::cout <<"HcalNoiseMonitor::bookHistograms"<< std::endl;
74 
76 
77  if(tevt_ == 0)
78  setup(ib);
79 
80  if(mergeRuns_ == false)
81  reset();
82 
83  return;
84 }
85 
87 {
88  if (setupDone_)
89  return;
90  setupDone_ = true;
92 
93  if(debug_ > 1)
94  std::cout << "<HcalNoiseMonitor::setup> Creating histograms" << std::endl;
95 
97 
98  // Fit-based
99  ib.setCurrentFolder(subdir_ + "DoubleChi2/");
100 
101  hNominalChi2 = ib.book1D("Nominal_fit_chi2", "Nominal fit chi2, total charge > 20 fC", 100, 0, 200);
102  hNominalChi2->setAxisTitle("Nominal fit #chi^{2}", 1);
103 
104  hLinearChi2 = ib.book1D("Linear_fit_chi2", "Linear fit chi2, total charge > 20 fC", 100, 0, 200);
105  hLinearChi2->setAxisTitle("Linear fit #chi^{2}", 1);
106 
107  hLinearTestStatistics = ib.book1D("Lambda_linear", "#Lambda_{linear}, total charge > 20 fC", 100, -10, 10);
108  hLinearTestStatistics->setAxisTitle("#Lambda_{linear}", 1);
109 
110  hRMS8OverMax = ib.book1D("RMS8_over_Max", "RMS8/max, total charge > 20 fC", 100, 0, 2);
111  hRMS8OverMax->setAxisTitle("RMS8/max", 1);
112 
113  hRMS8OverMaxTestStatistics = ib.book1D("Lambda_RMS8_over_max", "#Lambda_{RMS8/Max}, total charge > 20 fC",
114  100, -30, 10);
115  hRMS8OverMaxTestStatistics->setAxisTitle("#Lambda_{RMS8/Max}", 1);
116 
117  hLambdaLinearVsTotalCharge = ib.book2D("Lambda_linear_vs_total_charge", "#Lambda_{Linear}",
118  50, -5, 5, 25, 0, 500);
119  hLambdaLinearVsTotalCharge->setAxisTitle("#Lambda_{linear}", 1);
120  hLambdaLinearVsTotalCharge->setAxisTitle("Total charge", 2);
121 
122  hLambdaRMS8MaxVsTotalCharge = ib.book2D("Lambda_RMS8Max_vs_total_charge", "#Lambda_{RMS8/Max}",
123  50, -15, 5, 25, 0, 500);
124  hLambdaRMS8MaxVsTotalCharge->setAxisTitle("#Lambda_{RMS8/Max}", 1);
125  hLambdaRMS8MaxVsTotalCharge->setAxisTitle("Total charge", 2);
126 
127  hTriangleLeftSlopeVsTS4 = ib.book2D("Triangle_fit_left_slope",
128  "Triangle fit left distance vs. TS4", 50, 0, 10, 25, 0, 500);
129  hTriangleLeftSlopeVsTS4->setAxisTitle("Left slope", 1);
130  hTriangleLeftSlopeVsTS4->setAxisTitle("Peak time slice", 2);
131 
132  hTriangleRightSlopeVsTS4 = ib.book2D("Triangle_fit_right_slope",
133  "Triangle fit right distance vs. peak time slice", 50, 0, 10, 25, 0, 500);
134  hTriangleRightSlopeVsTS4->setAxisTitle("Left slope", 1);
135  hTriangleRightSlopeVsTS4->setAxisTitle("Peak time slice", 2);
136 
137  SetupEtaPhiHists(ib,hFailLinearEtaPhi, "Fail_linear_Eta_Phi_Map", "");
138  SetupEtaPhiHists(ib,hFailRMSMaxEtaPhi, "Fail_RMS8Max_Eta_Phi_Map", "");
139  SetupEtaPhiHists(ib,hFailTriangleEtaPhi, "Fail_triangle_Eta_Phi_Map", "");
140 
141  // High-level isolation filter
142  ib.setCurrentFolder(subdir_ + "IsolationVariable/");
143 
144  SetupEtaPhiHists(ib,hFailIsolationEtaPhi, "Fail_isolation_Eta_Phi_Map", "");
145 
146  // TS4 vs. TS5 variable
147  ib.setCurrentFolder(subdir_ + "TS4TS5Variable/");
148 
149  hTS4TS5RelativeDifference = ib.book1D("TS4_TS5_relative_difference",
150  "(TS4-TS5)/(TS4+TS5), total charge > 20 fC", 100, -1, 1);
151  hTS4TS5RelativeDifference->setAxisTitle("(TS4 - TS5) / (TS4 + TS5)", 1);
152 
153  hTS4TS5RelativeDifferenceVsCharge = ib.book2D("TS4_TS5_relative_difference_charge",
154  "(TS4-TS5)/(TS4+TS5) vs. Charge", 25, 0, 400, 75, -1, 1);
156  hTS4TS5RelativeDifferenceVsCharge->setAxisTitle("(TS4 - TS5) / (TS4 + TS5)", 2);
157 
158  // Noise summary object
159  ib.setCurrentFolder(subdir_ + "NoiseMonitoring/");
160 
161  hMaxZeros = ib.book1D("Max_Zeros", "Max zeros", 15, -0.5, 14.5);
162 
163  hTotalZeros = ib.book1D("Total_Zeros", "Total zeros", 15, -0.5, 14.5);
164 
165  hE2OverE10Digi = ib.book1D("E2OverE10Digi", "E2/E10 of the highest digi in an HPD", 100, 0, 2);
166 
167  hE2OverE10Digi5 = ib.book1D("E2OverE10Digi5", "E2/E10 of the highest 5 digi in an HPD", 100, 0, 2);
168 
169  hE2OverE10RBX = ib.book1D("E2OverE10RBX", "E2/E10 of RBX", 100, 0, 2);
170 
171  hHPDHitCount = ib.book1D("HPDHitCount", "HPD hit count (1.5 GeV)", 19, -0.5, 18.5);
172 
173  hRBXHitCount = ib.book1D("RBXHitCount", "Number of hits in RBX", 74, -0.5, 73.5);
174 
175  hHcalNoiseCategory = ib.book1D("Hcal_noise_category", "Hcal noise category", 10, 0.5, 10.5);
176  hHcalNoiseCategory->setBinLabel(1, "RBX noise", 1);
177  hHcalNoiseCategory->setBinLabel(2, "RBX pedestal flatter", 1);
178  hHcalNoiseCategory->setBinLabel(3, "RBX pedestal sharper", 1);
179  hHcalNoiseCategory->setBinLabel(4, "RBX flash large hit count", 1);
180  hHcalNoiseCategory->setBinLabel(5, "RBX flash small hit count", 1);
181  hHcalNoiseCategory->setBinLabel(7, "HPD discharge", 1);
182  hHcalNoiseCategory->setBinLabel(8, "HPD ion feedback", 1);
183 
184  hBadZeroRBX = ib.book1D("BadZeroRBX", "RBX with bad ADC zero counts", 72, 0.5, 72.5);
185  hBadCountHPD = ib.book1D("BadCountHPD", "HPD with bad hit counts", 72 * 4, 0.5, 72 * 4 + 0.5);
186  hBadNoOtherCountHPD = ib.book1D("BadNoOtherCountHPD", "HPD with bad \"no other\" hit counts", 72 * 4, 0.5, 72 * 4 + 0.5);
187  hBadE2E10RBX = ib.book1D("BadE2E10RBX", "RBX with bad E2/E10 value", 72, 0.5, 72.5);
188 
189  ReadHcalPulse();
190 
191  return;
192 }
193 
194 
196 {
198  iEvent.getByToken(tok_hbhe_,hHBHEDigis);
199 
200  edm::ESHandle<HcalDbService> hConditions;
201  iSetup.get<HcalDbRecord>().get(hConditions);
202 
204  iEvent.getByToken(tok_hbherec_, hRecHits);
205 
207  iEvent.getByToken(tok_noise_,hRBXCollection);
208 
209  HcalBaseDQMonitor::analyze(iEvent, iSetup);
210 
211 
212  // loop over digis
213  for(HBHEDigiCollection::const_iterator iter = hHBHEDigis->begin(); iter != hHBHEDigis->end(); iter++)
214  {
215  HcalDetId id = iter->id();
216  const HcalCalibrations &Calibrations = hConditions->getHcalCalibrations(id);
217  const HcalQIECoder *ChannelCoder = hConditions->getHcalCoder(id);
218  const HcalQIEShape *Shape = hConditions->getHcalShape(ChannelCoder);
219  HcalCoderDb Coder(*ChannelCoder, *Shape);
220  CaloSamples Tool;
221  Coder.adc2fC(*iter, Tool);
222 
223  // int ieta = id.ieta();
224  // int iphi = id.iphi();
225  // int depth = id.depth();
226 
227  double Charge[10] = {0};
228  for(int i = 0; i < iter->size(); i++)
229  Charge[i] = Tool[i] - Calibrations.pedestal(iter->sample(i).capid());
230 
231  double TotalCharge = 0;
232  for(int i = 0; i < 10; i++)
233  TotalCharge = TotalCharge + Charge[i];
234 
235  if(TotalCharge > 20)
236  {
237  double NominalChi2 = 10000000;
238  NominalChi2 = PerformNominalFit(Charge);
239 
240  double LinearChi2 = PerformLinearFit(Charge);
241  double RMS8Max = CalculateRMS8Max(Charge);
242  TriangleFitResult TriangleResult = PerformTriangleFit(Charge);
243 
244  double TS4LeftSlope = 100000;
245  double TS4RightSlope = 100000;
246 
247  if(TriangleResult.LeftSlope > 1e-5)
248  TS4LeftSlope = Charge[4] / fabs(TriangleResult.LeftSlope);
249  if(TriangleResult.RightSlope < -1e-5)
250  TS4RightSlope = Charge[4] / fabs(TriangleResult.RightSlope);
251 
252  if(TS4LeftSlope < -1000 || TS4LeftSlope > 1000)
253  TS4LeftSlope = 1000;
254  if(TS4RightSlope < -1000 || TS4RightSlope > 1000)
255  TS4RightSlope = 1000;
256 
257  hNominalChi2->Fill(NominalChi2);
258  hLinearChi2->Fill(LinearChi2);
259  hLinearTestStatistics->Fill(log(LinearChi2) - log(NominalChi2));
260  hRMS8OverMax->Fill(RMS8Max);
261  hRMS8OverMaxTestStatistics->Fill(log(RMS8Max) - log(NominalChi2));
262 
263  hLambdaLinearVsTotalCharge->Fill(log(LinearChi2) - log(NominalChi2), TotalCharge);
264  hLambdaRMS8MaxVsTotalCharge->Fill(log(RMS8Max) - log(NominalChi2), TotalCharge);
265  hTriangleLeftSlopeVsTS4->Fill(TS4LeftSlope, Charge[4]);
266  hTriangleRightSlopeVsTS4->Fill(TS4RightSlope, Charge[4]);
267  }
268 
269  if(Charge[4] + Charge[5] > 1e-5)
270  {
271  hTS4TS5RelativeDifference->Fill((Charge[4] - Charge[5]) / (Charge[4] + Charge[5]));
272  hTS4TS5RelativeDifferenceVsCharge->Fill(TotalCharge, (Charge[4] - Charge[5]) / (Charge[4] + Charge[5]));
273  }
274  }
275 
276  // loop over rechits - noise bits (fit-based, isolation)
277  for(HBHERecHitCollection::const_iterator iter = hRecHits->begin(); iter != hRecHits->end(); iter++)
278  {
279  HcalDetId id = iter->id();
280 
281  int ieta = id.ieta();
282  int iphi = id.iphi();
283  int depth = id.depth();
284 
285  if(iter->flagField(HcalCaloFlagLabels::HBHEFlatNoise) == 1)
286  hFailLinearEtaPhi.depth[depth-1]->Fill(ieta, iphi);
287 
288  if(iter->flagField(HcalCaloFlagLabels::HBHESpikeNoise) == 1)
289  hFailRMSMaxEtaPhi.depth[depth-1]->Fill(ieta, iphi);
290 
291  if(iter->flagField(HcalCaloFlagLabels::HBHETriangleNoise) == 1)
292  hFailTriangleEtaPhi.depth[depth-1]->Fill(ieta, iphi);
293 
294  if(iter->flagField(HcalCaloFlagLabels::HBHEIsolatedNoise) == 1)
295  hFailIsolationEtaPhi.depth[depth-1]->Fill(ieta, iphi);
296  }
297 
298  // Code analagous to Yifei's
299  for(reco::HcalNoiseRBXCollection::const_iterator rbx = hRBXCollection->begin();
300  rbx != hRBXCollection->end(); rbx++)
301  {
302  const reco::HcalNoiseRBX RBX = *rbx;
303 
304  int NumberRBXHits = RBX.numRecHits(1.5);
305  double RBXEnergy = RBX.recHitEnergy(1.5);
306  double RBXE2 = RBX.allChargeHighest2TS();
307  double RBXE10 = RBX.allChargeTotal();
308 
309  std::vector<reco::HcalNoiseHPD> HPDs = RBX.HPDs();
310 
311  int RBXID = RBX.idnumber();
312 
313  if(RBXEnergy > mTotalZeroMinEnergy && RBX.totalZeros() >= mMaxADCZeros)
314  hBadZeroRBX->Fill(RBXID);
315  if(RBXEnergy > mE2E10MinEnergy && RBXE10 > 1e-5 && (RBXE2 / RBXE10 > mMaxE2E10 || RBXE2 / RBXE10 < mMinE2E10))
316  hBadE2E10RBX->Fill(RBXID);
317  for(std::vector<reco::HcalNoiseHPD>::const_iterator hpd = HPDs.begin(); hpd != HPDs.end(); hpd++)
318  {
319  reco::HcalNoiseHPD HPD = *hpd;
320  int HPDHitCount = HPD.numRecHits(1.5);
321  if(HPDHitCount >= mMaxHPDHitCount)
322  hBadCountHPD->Fill(HPD.idnumber());
323  if(HPDHitCount == NumberRBXHits && HPDHitCount >= mMaxHPDNoOtherHitCount)
325  }
326 
327  if(NumberRBXHits == 0 || RBXEnergy <= 10)
328  continue;
329 
330  hRBXHitCount->Fill(NumberRBXHits);
331 
332  hMaxZeros->Fill(RBX.maxZeros());
333  hTotalZeros->Fill(RBX.totalZeros());
334 
335  double HighestHPDEnergy = 0;
336  int HighestHPDHits = 0;
337 
338  for(std::vector<reco::HcalNoiseHPD>::const_iterator hpd = HPDs.begin(); hpd != HPDs.end(); hpd++)
339  {
340  reco::HcalNoiseHPD HPD = *hpd;
341 
342  if(HPD.recHitEnergy(1.5) > HighestHPDEnergy)
343  {
344  HighestHPDEnergy = HPD.recHitEnergy(1.5);
345  HighestHPDHits = HPD.numRecHits(1.5);
346  }
347 
348  if(HPD.numRecHits(5) < 1)
349  continue;
350 
351  if(HPD.bigChargeTotal() > 1e-5)
353  if(HPD.big5ChargeTotal() > 1e-5)
355 
356  hHPDHitCount->Fill(HPD.numRecHits(1.5));
357  }
358 
359  int NoiseCategory = 0;
360  bool IsRBXNoise = false;
361  // bool IsHPDNoise = false;
362  // bool IsHPDIonFeedback = false;
363  // bool IsHPDDischarge = false;
364 
365  if(RBXEnergy > 1e-5 && HighestHPDEnergy / RBXEnergy > 0.98)
366  {
367  // IsHPDNoise = true;
368 
369  if(HighestHPDHits >= 9)
370  {
371  // IsHPDDischarge = true;
372  NoiseCategory = 7;
373  }
374  else
375  {
376  // IsHPDIonFeedback = true;
377  NoiseCategory = 8;
378  }
379  }
380  else
381  {
382  IsRBXNoise = true;
383  NoiseCategory = 1;
384 
385  if(RBXE10 > 1e-5)
386  {
387  if(RBXE2 / RBXE10 < 0.33)
388  NoiseCategory = 2;
389  else if(RBXE2 / RBXE10 < 0.8)
390  NoiseCategory = 3;
391  else if(RBXE2 / RBXE10 > 0.8 && NumberRBXHits > 10)
392  NoiseCategory = 4;
393  else if(RBXE2 / RBXE10 > 0.8 && NumberRBXHits < 10) // [hic]
394  NoiseCategory = 5;
395  }
396  }
397 
398  hHcalNoiseCategory->Fill(NoiseCategory);
399 
400  if(IsRBXNoise == true && RBXE10 > 1e-5)
401  hE2OverE10RBX->Fill(RBXE2 / RBXE10);
402  }
403 
404  return;
405 }
406 
407 double HcalNoiseMonitor::PerformNominalFit(double Charge[10])
408 {
409  //
410  // Performs a fit to the ideal pulse shape. Returns best chi2
411  //
412  // A scan over different timing offset (for the ideal pulse) is carried out,
413  // and for each offset setting a one-parameter fit is performed
414  //
415 
416  int DigiSize = 10;
417 
418  double MinimumChi2 = 100000;
419 
420  double F = 0;
421 
422  double SumF2 = 0;
423  double SumTF = 0;
424  double SumT2 = 0;
425 
426  for(int i = 0; i + 250 < (int)CumulativeIdealPulse.size(); i++)
427  {
429  continue;
430 
431  SumF2 = 0;
432  SumTF = 0;
433  SumT2 = 0;
434 
435  for(int j = 0; j < DigiSize; j++)
436  {
437  // get ideal pulse component for this time slice....
438  F = CumulativeIdealPulse[i+j*25+25] - CumulativeIdealPulse[i+j*25];
439 
440  double Error2 = Charge[j];
441  if(Error2 < 1)
442  Error2 = 1;
443 
444  // ...and increment various summations
445  SumF2 += F * F / Error2;
446  SumTF += F * Charge[j] / Error2;
447  SumT2 += Charge[j] * Charge[j] / Error2;
448  }
449 
450  /* chi2= sum((Charge[j]-aF)^2/|Charge[j]|
451  ( |Charge[j]| = assumed sigma^2 for Charge[j]; a bit wonky for Charge[j]<1 )
452  chi2 = sum(|Charge[j]|) - 2*sum(aF*Charge[j]/|Charge[j]|) +sum( a^2*F^2/|Charge[j]|)
453  chi2 minimimized when d(chi2)/da = 0:
454  a = sum(F*Charge[j])/sum(F^2)
455  ...
456  chi2= sum(|Q[j]|) - sum(Q[j]/|Q[j]|*F)*sum(Q[j]/|Q[j]|*F)/sum(F^2/|Q[j]|), where Q = Charge
457  chi2 = SumT2 - SumTF*SumTF/SumF2
458  */
459 
460  double Chi2 = SumT2 - SumTF * SumTF / SumF2;
461 
462  if(Chi2 < MinimumChi2)
463  MinimumChi2 = Chi2;
464  }
465 
466  // safety protection in case of perfect fit - don't want the log(...) to explode
467  if(MinimumChi2 < 1e-5)
468  MinimumChi2 = 1e-5;
469 
470  return MinimumChi2;
471 }
472 
474 {
475  //
476  // Perform dual nominal fit and returns the chi2
477  //
478  // In this function we do a scan over possible "distance" (number of time slices between two components)
479  // and overall offset for the two components; first coarse, then finer
480  // All the fitting is done in the DualNominalFitSingleTry function
481  //
482 
483  double OverallMinimumChi2 = 1000000;
484 
485  int AvailableDistance[] = {-100, -75, -50, 50, 75, 100};
486 
487  // loop over possible pulse distances between two components
488  for(int k = 0; k < 6; k++)
489  {
490  double SingleMinimumChi2 = 1000000;
491  int MinOffset = 0;
492 
493  // scan coarsely through different offsets and find the minimum
494  for(int i = 0; i + 250 < (int)CumulativeIdealPulse.size(); i += 10)
495  {
496  double Chi2 = DualNominalFitSingleTry(Charge, i, AvailableDistance[k]);
497 
498  if(Chi2 < SingleMinimumChi2)
499  {
500  SingleMinimumChi2 = Chi2;
501  MinOffset = i;
502  }
503  }
504 
505  // around the minimum, scan finer for better a better minimum
506  for(int i = MinOffset - 15; i + 250 < (int)CumulativeIdealPulse.size() && i < MinOffset + 15; i++)
507  {
508  double Chi2 = DualNominalFitSingleTry(Charge, i, AvailableDistance[k]);
509  if(Chi2 < SingleMinimumChi2)
510  SingleMinimumChi2 = Chi2;
511  }
512 
513  // update overall minimum chi2
514  if(SingleMinimumChi2 < OverallMinimumChi2)
515  OverallMinimumChi2 = SingleMinimumChi2;
516  }
517 
518  return OverallMinimumChi2;
519 }
520 
521 double HcalNoiseMonitor::DualNominalFitSingleTry(double Charge[10], int Offset, int Distance)
522 {
523  //
524  // Does a fit to dual signal pulse hypothesis given offset and distance of the two target pulses
525  //
526  // The only parameters to fit here are the two pulse heights of in-time and out-of-time components
527  // since offset is given
528  // The calculation here is based from writing down the Chi2 formula and minimize against the two parameters,
529  // ie., Chi2 = Sum{((T[i] - a1 * F1[i] - a2 * F2[i]) / (Sigma[i]))^2}, where T[i] is the input pulse shape,
530  // and F1[i], F2[i] are the two ideal pulse components
531  //
532 
533  int DigiSize = 10;
534 
535  if(Offset < 0 || Offset + 250 >= (int)CumulativeIdealPulse.size())
536  return 1000000;
537  if(CumulativeIdealPulse[Offset+250] - CumulativeIdealPulse[Offset] < 1e-5)
538  return 1000000;
539 
540  static std::vector<double> F1;
541  static std::vector<double> F2;
542 
543  F1.resize(DigiSize);
544  F2.resize(DigiSize);
545 
546  double SumF1F1 = 0;
547  double SumF1F2 = 0;
548  double SumF2F2 = 0;
549  double SumTF1 = 0;
550  double SumTF2 = 0;
551 
552  double Error = 0;
553 
554  for(int j = 0; j < DigiSize; j++)
555  {
556  // this is the TS value for in-time component - no problem we can do a subtraction directly
557  F1[j] = CumulativeIdealPulse[Offset+j*25+25] - CumulativeIdealPulse[Offset+j*25];
558 
559  // However for the out-of-time component the index might go out-of-bound.
560  // Let's protect against this.
561 
562  int OffsetTemp = Offset + j * 25 + Distance;
563 
564  double C1 = 0; // lower-indexed value in the cumulative pulse shape
565  double C2 = 0; // higher-indexed value in the cumulative pulse shape
566 
567  if(OffsetTemp + 25 < (int)CumulativeIdealPulse.size() && OffsetTemp + 25 >= 0)
568  C1 = CumulativeIdealPulse[OffsetTemp+25];
569  if(OffsetTemp + 25 >= (int)CumulativeIdealPulse.size())
570  C1 = CumulativeIdealPulse[CumulativeIdealPulse.size()-1];
571  if(OffsetTemp < (int)CumulativeIdealPulse.size() && OffsetTemp >= 0)
572  C2 = CumulativeIdealPulse[OffsetTemp];
573  if(OffsetTemp >= (int)CumulativeIdealPulse.size())
574  C2 = CumulativeIdealPulse[CumulativeIdealPulse.size()-1];
575  F2[j] = C1 - C2;
576 
577  Error = Charge[j];
578  if(Error < 1)
579  Error = 1;
580 
581  SumF1F1 += F1[j] * F1[j] / Error;
582  SumF1F2 += F1[j] * F2[j] / Error;
583  SumF2F2 += F2[j] * F2[j] / Error;
584  SumTF1 += F1[j] * Charge[j] / Error;
585  SumTF2 += F2[j] * Charge[j] / Error;
586  }
587 
588  double Height = (SumF1F2 * SumTF2 - SumF2F2 * SumTF1) / (SumF1F2 * SumF1F2 - SumF1F1 * SumF2F2);
589  double Height2 = (SumF1F2 * SumTF1 - SumF1F1 * SumTF2) / (SumF1F2 * SumF1F2 - SumF1F1 * SumF2F2);
590 
591  double Chi2 = 0;
592  for(int j = 0; j < DigiSize; j++)
593  {
594  double Error = Charge[j];
595  if(Error < 1)
596  Error = 1;
597 
598  double Residual = Height * F1[j] + Height2 * F2[j] - Charge[j];
599  Chi2 += Residual * Residual / Error;
600  }
601 
602  // Safety protection in case of zero
603  if(Chi2 < 1e-5)
604  Chi2 = 1e-5;
605 
606  return Chi2;
607 }
608 
609 double HcalNoiseMonitor::PerformLinearFit(double Charge[10])
610 {
611  //
612  // Performs a straight-line fit over all time slices, and returns the chi2 value
613  //
614  // The calculation here is based from writing down the formula for chi2 and minimize
615  // with respect to the parameters in the fit, ie., slope and intercept of the straight line
616  // By doing two differentiation, we will get two equations, and the best parameters are determined by these
617  //
618 
619  int DigiSize = 10;
620 
621  double SumTS2OverTi = 0;
622  double SumTSOverTi = 0;
623  double SumOverTi = 0;
624  double SumTiTS = 0;
625  double SumTi = 0;
626 
627  double Error2 = 0;
628  for(int i = 0; i < DigiSize; i++)
629  {
630  Error2 = Charge[i];
631  if(Charge[i] < 1)
632  Error2 = 1;
633 
634  SumTS2OverTi += 1.* i * i / Error2;
635  SumTSOverTi += 1.* i / Error2;
636  SumOverTi += 1. / Error2;
637  SumTiTS += Charge[i] * i / Error2;
638  SumTi += Charge[i] / Error2;
639  }
640 
641  double CM1 = SumTS2OverTi; // Coefficient in front of slope in equation 1
642  double CM2 = SumTSOverTi; // Coefficient in front of slope in equation 2
643  double CD1 = SumTSOverTi; // Coefficient in front of intercept in equation 1
644  double CD2 = SumOverTi; // Coefficient in front of intercept in equation 2
645  double C1 = SumTiTS; // Constant coefficient in equation 1
646  double C2 = SumTi; // Constant coefficient in equation 2
647 
648  double Slope = (C1 * CD2 - C2 * CD1) / (CM1 * CD2 - CM2 * CD1);
649  double Intercept = (C1 * CM2 - C2 * CM1) / (CD1 * CM2 - CD2 * CM1);
650 
651  // now that the best parameters are found, calculate chi2 from those
652  double Chi2 = 0;
653  for(int i = 0; i < DigiSize; i++)
654  {
655  double Deviation = Slope * i + Intercept - Charge[i];
656  double Error2 = Charge[i];
657  if(Charge[i] < 1)
658  Error2 = 1;
659  Chi2 += Deviation * Deviation / Error2;
660  }
661 
662  // safety protection in case of perfect fit
663  if(Chi2 < 1e-5)
664  Chi2 = 1e-5;
665 
666  return Chi2;
667 }
668 
669 double HcalNoiseMonitor::CalculateRMS8Max(double Charge[10])
670 {
671  //
672  // CalculateRMS8Max
673  //
674  // returns "RMS" divided by the largest charge in the time slices
675  // "RMS" is calculated using all but the two largest time slices.
676  // The "RMS" is not quite the actual RMS (see note below), but the value is only
677  // used for determining max values, and is not quoted as the actual RMS anywhere.
678  //
679 
680  int DigiSize = 10;
681 
682  // Copy Charge vector again, since we are passing references around
683  std::vector<double> TempCharge(Charge, Charge + 10);
684 
685  // Sort TempCharge vector from smallest to largest charge
686  sort(TempCharge.begin(), TempCharge.end());
687 
688  double Total = 0;
689  double Total2 = 0;
690  for(int i = 0; i < DigiSize - 2; i++)
691  {
692  Total = Total + TempCharge[i];
693  Total2 = Total2 + TempCharge[i] * TempCharge[i];
694  }
695 
696  // This isn't quite the RMS (both Total2 and Total*Total need to be
697  // divided by an extra (DigiSize-2) within the sqrt to get the RMS.)
698  // We're only using this value for relative comparisons, though; we
699  // aren't explicitly interpreting it as the RMS. It might be nice
700  // to either change the calculation or rename the variable in the future, though.
701 
702  double RMS = sqrt(Total2 - Total * Total / (DigiSize - 2));
703 
704  double RMS8Max = 99999;
705  if(TempCharge[DigiSize-1] > 1e-5)
706  RMS8Max = RMS / TempCharge[DigiSize-1];
707  if(RMS8Max < 1e-5) // protection against zero
708  RMS8Max = 1e-5;
709 
710  return RMS8Max;
711 }
712 
714 {
715  //
716  // Perform a "triangle fit", and extract the slopes
717  //
718  // Left-hand side and right-hand side are not correlated to each other - do them separately
719  //
720 
722  result.Chi2 = 0;
723  result.LeftSlope = 0;
724  result.RightSlope = 0;
725 
726  int DigiSize = 10;
727 
728  // right side, starting from TS4
729  double MinimumRightChi2 = 1000000;
730  double Numerator = 0;
731  double Denominator = 0;
732 
733  for(int iTS = mTrianglePeakTS + 2; iTS <= DigiSize; iTS++) // the place where first TS center in flat line
734  {
735  // fit a straight line to the triangle part
736  Numerator = 0;
737  Denominator = 0;
738 
739  for(int i = mTrianglePeakTS + 1; i < iTS; i++)
740  {
741  Numerator += (i - mTrianglePeakTS) * (Charge[i] - Charge[mTrianglePeakTS]);
742  Denominator += (i - mTrianglePeakTS) * (i - mTrianglePeakTS);
743  }
744 
745  double BestSlope = Numerator / Denominator;
746  if(BestSlope > 0)
747  BestSlope = 0;
748 
749  // check if the slope is reasonable
750  if(iTS != DigiSize)
751  {
752  if(BestSlope > -1 * Charge[mTrianglePeakTS] / (iTS - mTrianglePeakTS))
753  BestSlope = -1 * Charge[mTrianglePeakTS] / (iTS - mTrianglePeakTS);
754  if(BestSlope < -1 * Charge[mTrianglePeakTS] / (iTS - 1 - mTrianglePeakTS))
755  BestSlope = -1 * Charge[mTrianglePeakTS] / (iTS - 1 - mTrianglePeakTS);
756  }
757  else
758  {
759  if(BestSlope < -1 * Charge[mTrianglePeakTS] / (iTS - 1 - mTrianglePeakTS))
760  BestSlope = -1 * Charge[mTrianglePeakTS] / (iTS - 1 - mTrianglePeakTS);
761  }
762 
763  // calculate partial chi2
764 
765  // The shape I'm fitting is more like a tent than a triangle.
766  // After the end of triangle edge assume a flat line
767 
768  double Chi2 = 0;
769  for(int i = mTrianglePeakTS + 1; i < iTS; i++)
770  Chi2 += (Charge[mTrianglePeakTS] - Charge[i] + (i - mTrianglePeakTS) * BestSlope)
771  * (Charge[mTrianglePeakTS] - Charge[i] + (i - mTrianglePeakTS) * BestSlope);
772  for(int i = iTS; i < DigiSize; i++) // Assumes fit line = 0 for iTS > fit
773  Chi2 += Charge[i] * Charge[i];
774 
775  if(Chi2 < MinimumRightChi2)
776  {
777  MinimumRightChi2 = Chi2;
778  result.RightSlope = BestSlope;
779  }
780  } // end of right-hand side loop
781 
782  // left side
783  double MinimumLeftChi2 = 1000000;
784 
785  for(int iTS = 0; iTS < (int)mTrianglePeakTS; iTS++) // the first time after linear fit ends
786  {
787  // fit a straight line to the triangle part
788  Numerator = 0;
789  Denominator = 0;
790  for(int i = iTS; i < (int)mTrianglePeakTS; i++)
791  {
792  Numerator = Numerator + (i - mTrianglePeakTS) * (Charge[i] - Charge[mTrianglePeakTS]);
793  Denominator = Denominator + (i - mTrianglePeakTS) * (i - mTrianglePeakTS);
794  }
795 
796  double BestSlope = Numerator / Denominator;
797  if(BestSlope < 0)
798  BestSlope = 0;
799 
800  // check slope
801  if(iTS != 0)
802  {
803  if(BestSlope > Charge[mTrianglePeakTS] / (mTrianglePeakTS - iTS))
804  BestSlope = Charge[mTrianglePeakTS] / (mTrianglePeakTS - iTS);
805  if(BestSlope < Charge[mTrianglePeakTS] / (mTrianglePeakTS + 1 - iTS))
806  BestSlope = Charge[mTrianglePeakTS] / (mTrianglePeakTS + 1 - iTS);
807  }
808  else
809  {
810  if(BestSlope > Charge[mTrianglePeakTS] / (mTrianglePeakTS - iTS))
811  BestSlope = Charge[mTrianglePeakTS] / (mTrianglePeakTS - iTS);
812  }
813 
814  // calculate minimum chi2
815  double Chi2 = 0;
816  for(int i = 0; i < iTS; i++)
817  Chi2 += Charge[i] * Charge[i];
818  for(int i = iTS; i < (int)mTrianglePeakTS; i++)
819  Chi2 += (Charge[mTrianglePeakTS] - Charge[i] + (i - mTrianglePeakTS) * BestSlope)
820  * (Charge[mTrianglePeakTS] - Charge[i] + (i - mTrianglePeakTS) * BestSlope);
821 
822  if(MinimumLeftChi2 > Chi2)
823  {
824  MinimumLeftChi2 = Chi2;
825  result.LeftSlope = BestSlope;
826  }
827  } // end of left-hand side loop
828 
829  result.Chi2 = MinimumLeftChi2 + MinimumRightChi2;
830 
831  return result;
832 }
833 
835 {
836  std::vector<double> PulseShape;
837 
838  HcalPulseShapes Shapes;
839  HcalPulseShapes::Shape HPDShape = Shapes.hbShape();
840 
841  PulseShape.reserve(350);
842  for(int i = 0; i < 200; i++)
843  PulseShape.push_back(HPDShape.at(i));
844  PulseShape.insert(PulseShape.begin(), 150, 0); // Safety margin of a lot of zeros in the beginning
845 
846  CumulativeIdealPulse.reserve(350);
847  CumulativeIdealPulse.clear();
848  CumulativeIdealPulse.push_back(0);
849  for(unsigned int i = 1; i < PulseShape.size(); i++)
850  CumulativeIdealPulse.push_back(CumulativeIdealPulse[i-1] + PulseShape[i]);
851 }
852 
854 
MonitorElement * hBadCountHPD
MonitorElement * hE2OverE10Digi
T getUntrackedParameter(std::string const &, T const &) const
MonitorElement * hBadNoOtherCountHPD
MonitorElement * hTS4TS5RelativeDifferenceVsCharge
int i
Definition: DBlmapReader.cc:9
double PerformNominalFit(double Charge[10])
MonitorElement * hE2OverE10RBX
int ib
Definition: cuy.py:660
float allChargeHighest2TS(unsigned int firstts=4) const
Definition: HcalNoiseRBX.cc:65
int idnumber(void) const
Definition: HcalNoiseHPD.cc:32
MonitorElement * hMaxZeros
virtual void analyze(const edm::Event &e, const edm::EventSetup &c)
int maxZeros(void) const
Definition: HcalNoiseRBX.cc:90
float at(double time) const
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:449
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
edm::EDGetTokenT< reco::HcalNoiseRBXCollection > tok_noise_
std::vector< int > AllowedCalibTypes_
TriangleFitResult PerformTriangleFit(double Charge[10])
void setup(DQMStore::IBooker &)
MonitorElement * hLambdaRMS8MaxVsTotalCharge
virtual void bookHistograms(DQMStore::IBooker &, edm::Run const &, edm::EventSetup const &)
std::vector< HBHEDataFrame >::const_iterator const_iterator
double CalculateRMS8Max(double Charge[10])
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)
int numRecHits(double threshold=1.5) const
MonitorElement * hHcalNoiseCategory
double pedestal(int fCapId) const
get pedestal for capid=0..3
MonitorElement * hNominalChi2
edm::EDGetTokenT< HBHEDigiCollection > tok_hbhe_
EtaPhiHists hFailRMSMaxEtaPhi
void Fill(long long x)
MonitorElement * hTotalZeros
MonitorElement * hLinearChi2
void SetupEtaPhiHists(DQMStore::IBooker &ib, EtaPhiHists &hh, std::string Name, std::string Units)
MonitorElement * hLinearTestStatistics
edm::InputTag hltresultsLabel_
int iEvent
Definition: GenABIO.cc:230
std::vector< MonitorElement * > depth
MonitorElement * hBadE2E10RBX
double recHitEnergy(double theshold=1.5) const
Definition: HcalNoiseRBX.cc:99
float allChargeTotal(void) const
Definition: HcalNoiseRBX.cc:57
EtaPhiHists hFailTriangleEtaPhi
float big5ChargeHighest2TS(unsigned int firstts=4) const
Definition: HcalNoiseHPD.cc:82
virtual void adc2fC(const HBHEDataFrame &df, CaloSamples &lf) const
Definition: HcalCoderDb.cc:44
T sqrt(T t)
Definition: SSEVec.h:48
int numRecHits(float threshold=1.5) const
MonitorElement * hBadZeroRBX
tuple result
Definition: query.py:137
MonitorElement * hTriangleRightSlopeVsTS4
float bigChargeHighest2TS(unsigned int firstts=4) const
Definition: HcalNoiseHPD.cc:51
MonitorElement * book1D(Args &&...args)
Definition: DQMStore.h:115
MonitorElement * hRMS8OverMaxTestStatistics
int j
Definition: DBlmapReader.cc:9
MonitorElement * hTS4TS5RelativeDifference
double PerformDualNominalFit(double Charge[10])
float big5ChargeTotal(void) const
Definition: HcalNoiseHPD.cc:73
double DualNominalFitSingleTry(double Charge[10], int Offset, int Distance)
MonitorElement * hRBXHitCount
void bookHistograms(DQMStore::IBooker &ib, const edm::Run &run, const edm::EventSetup &c)
MonitorElement * hE2OverE10Digi5
int totalZeros(void) const
Definition: HcalNoiseRBX.cc:82
void setCurrentFolder(const std::string &fullpath)
Definition: DQMStore.cc:274
MonitorElement * book2D(Args &&...args)
Definition: DQMStore.h:133
const T & get() const
Definition: EventSetup.h:55
MonitorElement * hRMS8OverMax
MonitorElement * hTriangleLeftSlopeVsTS4
const std::vector< HcalNoiseHPD > HPDs(void) const
Definition: HcalNoiseRBX.cc:33
std::vector< double > CumulativeIdealPulse
const Shape & hbShape() const
float recHitEnergy(float threshold=1.5) const
void analyze(edm::Event const &e, edm::EventSetup const &s)
int idnumber(void) const
Definition: HcalNoiseRBX.cc:28
tuple cout
Definition: gather_cfg.py:121
MonitorElement * hHPDHitCount
EtaPhiHists hFailIsolationEtaPhi
std::vector< std::string > triggers_
edm::EDGetTokenT< HBHERecHitCollection > tok_hbherec_
edm::InputTag rawdataLabel_
static uInt32 F(BLOWFISH_CTX *ctx, uInt32 x)
Definition: blowfish.cc:281
Definition: Chi2.h:17
HcalNoiseMonitor(const edm::ParameterSet &ps)
MonitorElement * hLambdaLinearVsTotalCharge
void setAxisTitle(const std::string &title, int axis=1)
set x-, y- or z-axis title (axis=1, 2, 3 respectively)
virtual void setup(DQMStore::IBooker &)
float bigChargeTotal(void) const
Definition: HcalNoiseHPD.cc:42
Definition: Run.h:41
double PerformLinearFit(double Charge[10])
EtaPhiHists hFailLinearEtaPhi
tuple log
Definition: cmsBatch.py:347
Abstract Class of shape.
Definition: Shape.h:14