00001
00002 #include <string>
00003 #include <vector>
00004 #include <iostream>
00005 #include <algorithm>
00006 #include <fstream>
00007 #include <cmath>
00008
00009
00010 #include "RecoLocalCalo/HcalRecAlgos/interface/HBHEPulseShapeFlag.h"
00011 #include "RecoLocalCalo/HcalRecAlgos/interface/HcalCaloFlagLabels.h"
00012
00013 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00014
00015 #include "DataFormats/HcalDigi/interface/HBHEDataFrame.h"
00016 #include "DataFormats/HcalRecHit/interface/HcalRecHitCollections.h"
00017 #include "DataFormats/HcalRecHit/interface/HBHERecHit.h"
00018
00019 #include "CalibFormats/HcalObjects/interface/HcalCalibrations.h"
00020 #include "CalibFormats/HcalObjects/interface/HcalCoderDb.h"
00021 #include "CalibCalorimetry/HcalAlgos/interface/HcalPulseShapes.h"
00022
00023 HBHEPulseShapeFlagSetter::HBHEPulseShapeFlagSetter()
00024 {
00025
00026
00027
00028
00029
00030
00031
00032
00033 mMinimumChargeThreshold = 99999999;
00034 mTS4TS5ChargeThreshold = 99999999;
00035 }
00036
00037 HBHEPulseShapeFlagSetter::HBHEPulseShapeFlagSetter(double MinimumChargeThreshold,
00038 double TS4TS5ChargeThreshold,
00039 unsigned int TrianglePeakTS,
00040 std::vector<double> LinearThreshold,
00041 std::vector<double> LinearCut,
00042 std::vector<double> RMS8MaxThreshold,
00043 std::vector<double> RMS8MaxCut,
00044 std::vector<double> LeftSlopeThreshold,
00045 std::vector<double> LeftSlopeCut,
00046 std::vector<double> RightSlopeThreshold,
00047 std::vector<double> RightSlopeCut,
00048 std::vector<double> RightSlopeSmallThreshold,
00049 std::vector<double> RightSlopeSmallCut,
00050 std::vector<double> TS4TS5LowerThreshold,
00051 std::vector<double> TS4TS5LowerCut,
00052 std::vector<double> TS4TS5UpperThreshold,
00053 std::vector<double> TS4TS5UpperCut,
00054 bool UseDualFit,
00055 bool TriangleIgnoreSlow)
00056 {
00057
00058
00059
00060
00061
00062
00063
00064 mMinimumChargeThreshold = MinimumChargeThreshold;
00065 mTS4TS5ChargeThreshold = TS4TS5ChargeThreshold;
00066 mTrianglePeakTS = TrianglePeakTS;
00067 mTriangleIgnoreSlow = TriangleIgnoreSlow;
00068
00069 for(std::vector<double>::size_type i = 0; i < LinearThreshold.size() && i < LinearCut.size(); i++)
00070 mLambdaLinearCut.push_back(std::pair<double, double>(LinearThreshold[i], LinearCut[i]));
00071 sort(mLambdaLinearCut.begin(), mLambdaLinearCut.end());
00072
00073 for(std::vector<double>::size_type i = 0; i < RMS8MaxThreshold.size() && i < RMS8MaxCut.size(); i++)
00074 mLambdaRMS8MaxCut.push_back(std::pair<double, double>(RMS8MaxThreshold[i], RMS8MaxCut[i]));
00075 sort(mLambdaRMS8MaxCut.begin(), mLambdaRMS8MaxCut.end());
00076
00077 for(std::vector<double>::size_type i = 0; i < LeftSlopeThreshold.size() && i < LeftSlopeCut.size(); i++)
00078 mLeftSlopeCut.push_back(std::pair<double, double>(LeftSlopeThreshold[i], LeftSlopeCut[i]));
00079 sort(mLeftSlopeCut.begin(), mLeftSlopeCut.end());
00080
00081 for(std::vector<double>::size_type i = 0; i < RightSlopeThreshold.size() && i < RightSlopeCut.size(); i++)
00082 mRightSlopeCut.push_back(std::pair<double, double>(RightSlopeThreshold[i], RightSlopeCut[i]));
00083 sort(mRightSlopeCut.begin(), mRightSlopeCut.end());
00084
00085 for(std::vector<double>::size_type i = 0; i < RightSlopeSmallThreshold.size() && i < RightSlopeSmallCut.size(); i++)
00086 mRightSlopeSmallCut.push_back(std::pair<double, double>(RightSlopeSmallThreshold[i], RightSlopeSmallCut[i]));
00087 sort(mRightSlopeSmallCut.begin(), mRightSlopeSmallCut.end());
00088
00089 for(std::vector<double>::size_type i = 0; i < TS4TS5UpperThreshold.size() && i < TS4TS5UpperCut.size(); i++)
00090 mTS4TS5UpperCut.push_back(std::pair<double, double>(TS4TS5UpperThreshold[i], TS4TS5UpperCut[i]));
00091 sort(mTS4TS5UpperCut.begin(), mTS4TS5UpperCut.end());
00092
00093 for(std::vector<double>::size_type i = 0; i < TS4TS5LowerThreshold.size() && i < TS4TS5LowerCut.size(); i++)
00094 mTS4TS5LowerCut.push_back(std::pair<double, double>(TS4TS5LowerThreshold[i], TS4TS5LowerCut[i]));
00095 sort(mTS4TS5LowerCut.begin(), mTS4TS5LowerCut.end());
00096
00097 mUseDualFit = UseDualFit;
00098
00099 Initialize();
00100 }
00101
00102 HBHEPulseShapeFlagSetter::~HBHEPulseShapeFlagSetter()
00103 {
00104
00105 }
00106
00107 void HBHEPulseShapeFlagSetter::Clear()
00108 {
00109
00110 }
00111
00112 void HBHEPulseShapeFlagSetter::SetPulseShapeFlags(HBHERecHit &hbhe,
00113 const HBHEDataFrame &digi,
00114 const HcalCoder &coder,
00115 const HcalCalibrations &calib)
00116 {
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 int abseta = hbhe.id().ietaAbs();
00128 if(abseta == 28 || abseta == 29) return;
00129
00130 CaloSamples Tool;
00131 coder.adc2fC(digi, Tool);
00132
00133 mCharge.clear();
00134 mCharge.resize(digi.size());
00135
00136 double TotalCharge = 0;
00137
00138 for(int i = 0; i < digi.size(); ++i)
00139 {
00140 mCharge[i] = Tool[i] - calib.pedestal(digi.sample(i).capid());
00141 TotalCharge += mCharge[i];
00142 }
00143
00144
00145 if(TotalCharge < mMinimumChargeThreshold)
00146 return;
00147
00148 double NominalChi2 = 0;
00149 if (mUseDualFit == true)
00150 NominalChi2=PerformDualNominalFit(mCharge);
00151 else
00152 NominalChi2=PerformNominalFit(mCharge);
00153
00154 double LinearChi2 = PerformLinearFit(mCharge);
00155
00156 double RMS8Max = CalculateRMS8Max(mCharge);
00157 TriangleFitResult TriangleResult = PerformTriangleFit(mCharge);
00158
00159
00160 if(CheckPassFilter(TotalCharge, log(LinearChi2) - log(NominalChi2), mLambdaLinearCut, -1) == false)
00161 hbhe.setFlagField(1, HcalCaloFlagLabels::HBHEFlatNoise);
00162 if(CheckPassFilter(TotalCharge, log(RMS8Max) * 2 - log(NominalChi2), mLambdaRMS8MaxCut, -1) == false)
00163 hbhe.setFlagField(1, HcalCaloFlagLabels::HBHESpikeNoise);
00164
00165
00166 if ((int)mCharge.size() >= mTrianglePeakTS)
00167 {
00168
00169 double TS4Left = 1000;
00170 double TS4Right = 1000;
00171
00172
00173 if (TriangleResult.LeftSlope > 1e-5)
00174 TS4Left = mCharge[mTrianglePeakTS] / TriangleResult.LeftSlope;
00175 if (TriangleResult.RightSlope < -1e-5)
00176 TS4Right = mCharge[mTrianglePeakTS] / -TriangleResult.RightSlope;
00177
00178 if(TS4Left > 1000 || TS4Left < -1000)
00179 TS4Left = 1000;
00180 if(TS4Right > 1000 || TS4Right < -1000)
00181 TS4Right = 1000;
00182
00183 if(mTriangleIgnoreSlow == false)
00184 {
00185 if(CheckPassFilter(mCharge[mTrianglePeakTS], TS4Left, mLeftSlopeCut, 1) == false)
00186 hbhe.setFlagField(1, HcalCaloFlagLabels::HBHETriangleNoise);
00187 else if(CheckPassFilter(mCharge[mTrianglePeakTS], TS4Right, mRightSlopeCut, 1) == false)
00188 hbhe.setFlagField(1, HcalCaloFlagLabels::HBHETriangleNoise);
00189 }
00190
00191
00192 if(CheckPassFilter(mCharge[mTrianglePeakTS], TS4Right, mRightSlopeSmallCut, -1) == false)
00193 hbhe.setFlagField(1, HcalCaloFlagLabels::HBHETriangleNoise);
00194 }
00195
00196 if(mCharge[4] + mCharge[5] > mTS4TS5ChargeThreshold && mTS4TS5ChargeThreshold>0)
00197 {
00198 double TS4TS5 = (mCharge[4] - mCharge[5]) / (mCharge[4] + mCharge[5]);
00199 if(CheckPassFilter(mCharge[4] + mCharge[5], TS4TS5, mTS4TS5UpperCut, 1) == false)
00200 hbhe.setFlagField(1, HcalCaloFlagLabels::HBHETS4TS5Noise);
00201 if(CheckPassFilter(mCharge[4] + mCharge[5], TS4TS5, mTS4TS5LowerCut, -1) == false)
00202 hbhe.setFlagField(1, HcalCaloFlagLabels::HBHETS4TS5Noise);
00203 }
00204 }
00205
00206 void HBHEPulseShapeFlagSetter::Initialize()
00207 {
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 std::vector<double> PulseShape;
00223
00224 HcalPulseShapes Shapes;
00225 HcalPulseShapes::Shape HPDShape = Shapes.hbShape();
00226
00227 PulseShape.reserve(350);
00228 for(int i = 0; i < 200; i++)
00229 PulseShape.push_back(HPDShape.at(i));
00230 PulseShape.insert(PulseShape.begin(), 150, 0);
00231
00232 CumulativeIdealPulse.reserve(350);
00233 CumulativeIdealPulse.clear();
00234 CumulativeIdealPulse.push_back(0);
00235 for(unsigned int i = 1; i < PulseShape.size(); i++)
00236 CumulativeIdealPulse.push_back(CumulativeIdealPulse[i-1] + PulseShape[i]);
00237
00238
00239 mCharge.reserve(10);
00240 }
00241
00242 TriangleFitResult HBHEPulseShapeFlagSetter::PerformTriangleFit(const std::vector<double> &Charge)
00243 {
00244
00245
00246
00247
00248
00249
00250 TriangleFitResult result;
00251 result.Chi2 = 0;
00252 result.LeftSlope = 0;
00253 result.RightSlope = 0;
00254
00255 int DigiSize = Charge.size();
00256
00257
00258 double MinimumRightChi2 = 1000000;
00259 double Numerator = 0;
00260 double Denominator = 0;
00261
00262 for(int iTS = mTrianglePeakTS + 2; iTS <= DigiSize; iTS++)
00263 {
00264
00265 Numerator = 0;
00266 Denominator = 0;
00267
00268 for(int i = mTrianglePeakTS + 1; i < iTS; i++)
00269 {
00270 Numerator += (i - mTrianglePeakTS) * (Charge[i] - Charge[mTrianglePeakTS]);
00271 Denominator += (i - mTrianglePeakTS) * (i - mTrianglePeakTS);
00272 }
00273
00274 double BestSlope = 0;
00275 if (Denominator!=0) BestSlope = Numerator / Denominator;
00276 if(BestSlope > 0)
00277 BestSlope = 0;
00278
00279
00280 if(iTS != DigiSize)
00281 {
00282
00283 if(BestSlope > -1 * Charge[mTrianglePeakTS] / (iTS - mTrianglePeakTS))
00284 BestSlope = -1 * Charge[mTrianglePeakTS] / (iTS - mTrianglePeakTS);
00285 if(BestSlope < -1 * Charge[mTrianglePeakTS] / (iTS - 1 - mTrianglePeakTS))
00286 BestSlope = -1 * Charge[mTrianglePeakTS] / (iTS - 1 - mTrianglePeakTS);
00287 }
00288 else
00289 {
00290
00291 if(BestSlope < -1 * Charge[mTrianglePeakTS] / (iTS - 1 - mTrianglePeakTS))
00292 BestSlope = -1 * Charge[mTrianglePeakTS] / (iTS - 1 - mTrianglePeakTS);
00293 }
00294
00295
00296
00297
00298
00299
00300 double Chi2 = 0;
00301 for(int i = mTrianglePeakTS + 1; i < iTS; i++)
00302 Chi2 += (Charge[mTrianglePeakTS] - Charge[i] + (i - mTrianglePeakTS) * BestSlope)
00303 * (Charge[mTrianglePeakTS] - Charge[i] + (i - mTrianglePeakTS) * BestSlope);
00304 for(int i = iTS; i < DigiSize; i++)
00305 Chi2 += Charge[i] * Charge[i];
00306
00307 if(Chi2 < MinimumRightChi2)
00308 {
00309 MinimumRightChi2 = Chi2;
00310 result.RightSlope = BestSlope;
00311 }
00312 }
00313
00314
00315 double MinimumLeftChi2 = 1000000;
00316
00317 for(int iTS = 0; iTS < (int)mTrianglePeakTS; iTS++)
00318 {
00319
00320 Numerator = 0;
00321 Denominator = 0;
00322 for(int i = iTS; i < (int)mTrianglePeakTS; i++)
00323 {
00324 Numerator = Numerator + (i - mTrianglePeakTS) * (Charge[i] - Charge[mTrianglePeakTS]);
00325 Denominator = Denominator + (i - mTrianglePeakTS) * (i - mTrianglePeakTS);
00326 }
00327
00328 double BestSlope = 0;
00329 if (Denominator!=0) BestSlope = Numerator / Denominator;
00330 if (BestSlope < 0)
00331 BestSlope = 0;
00332
00333
00334 if(iTS != 0)
00335 {
00336
00337 if(BestSlope > Charge[mTrianglePeakTS] / (mTrianglePeakTS - iTS))
00338 BestSlope = Charge[mTrianglePeakTS] / (mTrianglePeakTS - iTS);
00339 if(BestSlope < Charge[mTrianglePeakTS] / (mTrianglePeakTS + 1 - iTS))
00340 BestSlope = Charge[mTrianglePeakTS] / (mTrianglePeakTS + 1 - iTS);
00341 }
00342 else
00343 {
00344 if(BestSlope > Charge[mTrianglePeakTS] / (mTrianglePeakTS - iTS))
00345 BestSlope = Charge[mTrianglePeakTS] / (mTrianglePeakTS - iTS);
00346 }
00347
00348
00349 double Chi2 = 0;
00350 for(int i = 0; i < iTS; i++)
00351 Chi2 += Charge[i] * Charge[i];
00352 for(int i = iTS; i < (int)mTrianglePeakTS; i++)
00353 Chi2 += (Charge[mTrianglePeakTS] - Charge[i] + (i - mTrianglePeakTS) * BestSlope)
00354 * (Charge[mTrianglePeakTS] - Charge[i] + (i - mTrianglePeakTS) * BestSlope);
00355
00356 if(MinimumLeftChi2 > Chi2)
00357 {
00358 MinimumLeftChi2 = Chi2;
00359 result.LeftSlope = BestSlope;
00360 }
00361 }
00362
00363 result.Chi2 = MinimumLeftChi2 + MinimumRightChi2;
00364
00365 return result;
00366 }
00367
00368 double HBHEPulseShapeFlagSetter::PerformNominalFit(const std::vector<double> &Charge)
00369 {
00370
00371
00372
00373
00374
00375
00376
00377 int DigiSize = Charge.size();
00378
00379 double MinimumChi2 = 100000;
00380
00381 double F = 0;
00382
00383 double SumF2 = 0;
00384 double SumTF = 0;
00385 double SumT2 = 0;
00386
00387 for(int i = 0; i + 250 < (int)CumulativeIdealPulse.size(); i++)
00388 {
00389 if(CumulativeIdealPulse[i+250] - CumulativeIdealPulse[i] < 1e-5)
00390 continue;
00391
00392 SumF2 = 0;
00393 SumTF = 0;
00394 SumT2 = 0;
00395
00396 double ErrorTemp=0;
00397 for(int j = 0; j < DigiSize; j++)
00398 {
00399
00400 F = CumulativeIdealPulse[i+j*25+25] - CumulativeIdealPulse[i+j*25];
00401
00402 ErrorTemp=Charge[j];
00403 if (ErrorTemp<1)
00404 ErrorTemp=1;
00405
00406 SumF2 += F * F / ErrorTemp;
00407 SumTF += F * Charge[j] / ErrorTemp;
00408 SumT2 += fabs(Charge[j]);
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422 double Chi2 = SumT2 - SumTF * SumTF / SumF2;
00423
00424 if(Chi2 < MinimumChi2)
00425 MinimumChi2 = Chi2;
00426 }
00427
00428
00429 if(MinimumChi2 < 1e-5)
00430 MinimumChi2 = 1e-5;
00431
00432 return MinimumChi2;
00433 }
00434
00435 double HBHEPulseShapeFlagSetter::PerformDualNominalFit(const std::vector<double> &Charge)
00436 {
00437
00438
00439
00440
00441
00442
00443
00444
00445 double OverallMinimumChi2 = 1000000;
00446
00447 int AvailableDistance[] = {-100, -75, -50, 50, 75, 100};
00448
00449
00450 for(int k = 0; k < 6; k++)
00451 {
00452 double SingleMinimumChi2 = 1000000;
00453 int MinOffset = 0;
00454
00455
00456 for(int i = 0; i + 250 < (int)CumulativeIdealPulse.size(); i += 10)
00457 {
00458 double Chi2 = DualNominalFitSingleTry(Charge, i, AvailableDistance[k]);
00459
00460 if(Chi2 < SingleMinimumChi2)
00461 {
00462 SingleMinimumChi2 = Chi2;
00463 MinOffset = i;
00464 }
00465 }
00466
00467
00468 for(int i = MinOffset - 15; i + 250 < (int)CumulativeIdealPulse.size() && i < MinOffset + 15; i++)
00469 {
00470 double Chi2 = DualNominalFitSingleTry(Charge, i, AvailableDistance[k]);
00471 if(Chi2 < SingleMinimumChi2)
00472 SingleMinimumChi2 = Chi2;
00473 }
00474
00475
00476 if(SingleMinimumChi2 < OverallMinimumChi2)
00477 OverallMinimumChi2 = SingleMinimumChi2;
00478 }
00479
00480 return OverallMinimumChi2;
00481 }
00482
00483 double HBHEPulseShapeFlagSetter::DualNominalFitSingleTry(const std::vector<double> &Charge, int Offset, int Distance)
00484 {
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 int DigiSize = Charge.size();
00496
00497 if(Offset < 0 || Offset + 250 >= (int)CumulativeIdealPulse.size())
00498 return 1000000;
00499 if(CumulativeIdealPulse[Offset+250] - CumulativeIdealPulse[Offset] < 1e-5)
00500 return 1000000;
00501
00502 static std::vector<double> F1;
00503 static std::vector<double> F2;
00504
00505 F1.resize(DigiSize);
00506 F2.resize(DigiSize);
00507
00508 double SumF1F1 = 0;
00509 double SumF1F2 = 0;
00510 double SumF2F2 = 0;
00511 double SumTF1 = 0;
00512 double SumTF2 = 0;
00513
00514 double Error = 0;
00515
00516 for(int j = 0; j < DigiSize; j++)
00517 {
00518
00519 F1[j] = CumulativeIdealPulse[Offset+j*25+25] - CumulativeIdealPulse[Offset+j*25];
00520
00521
00522
00523
00524 int OffsetTemp = Offset + j * 25 + Distance;
00525
00526 double C1 = 0;
00527 double C2 = 0;
00528
00529 if(OffsetTemp + 25 < (int)CumulativeIdealPulse.size() && OffsetTemp + 25 >= 0)
00530 C1 = CumulativeIdealPulse[OffsetTemp+25];
00531 if(OffsetTemp + 25 >= (int)CumulativeIdealPulse.size())
00532 C1 = CumulativeIdealPulse[CumulativeIdealPulse.size()-1];
00533 if(OffsetTemp < (int)CumulativeIdealPulse.size() && OffsetTemp >= 0)
00534 C2 = CumulativeIdealPulse[OffsetTemp];
00535 if(OffsetTemp >= (int)CumulativeIdealPulse.size())
00536 C2 = CumulativeIdealPulse[CumulativeIdealPulse.size()-1];
00537 F2[j] = C1 - C2;
00538
00539 Error = Charge[j];
00540 if(Error < 1)
00541 Error = 1;
00542
00543 SumF1F1 += F1[j] * F1[j] / Error;
00544 SumF1F2 += F1[j] * F2[j] / Error;
00545 SumF2F2 += F2[j] * F2[j] / Error;
00546 SumTF1 += F1[j] * Charge[j] / Error;
00547 SumTF2 += F2[j] * Charge[j] / Error;
00548 }
00549
00550 double Height = 0;
00551 double Height2 = 0;
00552 if (fabs(SumF1F2*SumF1F2-SumF1F1*SumF2F2)>1e-5)
00553 {
00554 Height = (SumF1F2 * SumTF2 - SumF2F2 * SumTF1) / (SumF1F2 * SumF1F2 - SumF1F1 * SumF2F2);
00555 Height2 = (SumF1F2 * SumTF1 - SumF1F1 * SumTF2) / (SumF1F2 * SumF1F2 - SumF1F1 * SumF2F2);
00556 }
00557
00558 double Chi2 = 0;
00559 for(int j = 0; j < DigiSize; j++)
00560 {
00561 double Error = Charge[j];
00562 if(Error < 1)
00563 Error = 1;
00564
00565 double Residual = Height * F1[j] + Height2 * F2[j] - Charge[j];
00566 Chi2 += Residual * Residual / Error;
00567 }
00568
00569
00570 if(Chi2 < 1e-5)
00571 Chi2 = 1e-5;
00572
00573 return Chi2;
00574 }
00575
00576 double HBHEPulseShapeFlagSetter::CalculateRMS8Max(const std::vector<double> &Charge)
00577 {
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587 int DigiSize = Charge.size();
00588
00589 if (DigiSize<=2) return 1e-5;
00590
00591 std::vector<double> TempCharge = Charge;
00592
00593
00594 sort(TempCharge.begin(), TempCharge.end());
00595
00596 double Total = 0;
00597 double Total2 = 0;
00598 for(int i = 0; i < DigiSize - 2; i++)
00599 {
00600 Total = Total + TempCharge[i];
00601 Total2 = Total2 + TempCharge[i] * TempCharge[i];
00602 }
00603
00604
00605
00606
00607
00608
00609
00610 double RMS = sqrt(Total2 - Total * Total / (DigiSize - 2));
00611
00612 double RMS8Max = RMS / TempCharge[DigiSize-1];
00613 if(RMS8Max < 1e-5)
00614 RMS8Max = 1e-5;
00615
00616 return RMS / TempCharge[DigiSize-1];
00617 }
00618
00619 double HBHEPulseShapeFlagSetter::PerformLinearFit(const std::vector<double> &Charge)
00620 {
00621
00622
00623
00624
00625
00626
00627
00628
00629 int DigiSize = Charge.size();
00630
00631 double SumTS2OverTi = 0;
00632 double SumTSOverTi = 0;
00633 double SumOverTi = 0;
00634 double SumTiTS = 0;
00635 double SumTi = 0;
00636
00637 double Error2 = 0;
00638 for(int i = 0; i < DigiSize; i++)
00639 {
00640 Error2 = Charge[i];
00641 if(Charge[i] < 1)
00642 Error2 = 1;
00643
00644 SumTS2OverTi += 1.* i * i / Error2;
00645 SumTSOverTi += 1.* i / Error2;
00646 SumOverTi += 1. / Error2;
00647 SumTiTS += Charge[i] * i / Error2;
00648 SumTi += Charge[i] / Error2;
00649 }
00650
00651 double CM1 = SumTS2OverTi;
00652 double CM2 = SumTSOverTi;
00653 double CD1 = SumTSOverTi;
00654 double CD2 = SumOverTi;
00655 double C1 = SumTiTS;
00656 double C2 = SumTi;
00657
00658
00659 double Slope = (C1 * CD2 - C2 * CD1) / (CM1 * CD2 - CM2 * CD1);
00660 double Intercept = (C1 * CM2 - C2 * CM1) / (CD1 * CM2 - CD2 * CM1);
00661
00662
00663 double Chi2 = 0;
00664 for(int i = 0; i < DigiSize; i++)
00665 {
00666 double Deviation = Slope * i + Intercept - Charge[i];
00667 double Error2 = Charge[i];
00668 if(Charge[i] < 1)
00669 Error2 = 1;
00670 Chi2 += Deviation * Deviation / Error2;
00671 }
00672
00673
00674 if(Chi2 < 1e-5)
00675 Chi2 = 1e-5;
00676
00677 return Chi2;
00678 }
00679
00680 bool HBHEPulseShapeFlagSetter::CheckPassFilter(double Charge,
00681 double Discriminant,
00682 std::vector<std::pair<double, double> > &Cuts,
00683 int Side)
00684 {
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694 if(Cuts.size() == 0)
00695 return true;
00696
00697 if(Charge <= Cuts[0].first)
00698 return true;
00699
00700 int IndexLargerThanCharge = -1;
00701 for(int i = 1; i < (int)Cuts.size(); i++)
00702 {
00703 if(Cuts[i].first > Charge)
00704 {
00705 IndexLargerThanCharge = i;
00706 break;
00707 }
00708 }
00709
00710 double limit = 1000000;
00711
00712 if(IndexLargerThanCharge == -1)
00713 limit = Cuts[Cuts.size()-1].second;
00714 else
00715 {
00716 double C1 = Cuts[IndexLargerThanCharge].first;
00717 double C2 = Cuts[IndexLargerThanCharge-1].first;
00718 double L1 = Cuts[IndexLargerThanCharge].second;
00719 double L2 = Cuts[IndexLargerThanCharge-1].second;
00720
00721 limit = (Charge - C1) / (C2 - C1) * (L2 - L1) + L1;
00722 }
00723
00724 if(Side > 0 && Discriminant > limit)
00725 return false;
00726 if(Side < 0 && Discriminant < limit)
00727 return false;
00728
00729 return true;
00730 }
00731
00732
00733