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