File indexing completed on 2024-09-07 04:34:51
0001 #include "CalibCalorimetry/EcalPedestalOffsets/interface/TPedValues.h"
0002 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0003
0004 #include "TAxis.h"
0005 #include "TF1.h"
0006 #include "TGraphErrors.h"
0007 #include <cassert>
0008 #include <cmath>
0009 #include <iostream>
0010
0011 void reset(double vett[256]) {
0012 for (int i = 0; i < 256; ++i)
0013 vett[i] = 0.;
0014 }
0015
0016 TPedValues::TPedValues(double RMSmax, int bestPedestal) : m_bestPedestal(bestPedestal), m_RMSmax(RMSmax) {
0017 LogDebug("EcalPedOffset") << "entering TPedValues ctor ...";
0018 for (int i = 0; i < 1700; ++i)
0019 endcapCrystalNumbers[i] = 0;
0020 }
0021
0022 TPedValues::TPedValues(const TPedValues &orig) {
0023 LogDebug("EcalPedOffset") << "entering TPedValues copyctor ...";
0024 m_bestPedestal = orig.m_bestPedestal;
0025 m_RMSmax = orig.m_RMSmax;
0026
0027 for (int gain = 0; gain < 3; ++gain)
0028 for (int crystal = 0; crystal < 1700; ++crystal)
0029 for (int DAC = 0; DAC < 256; ++DAC)
0030 m_entries[gain][crystal][DAC] = orig.m_entries[gain][crystal][DAC];
0031
0032 for (int i = 0; i < 1700; ++i)
0033 endcapCrystalNumbers[i] = orig.endcapCrystalNumbers[i];
0034 }
0035
0036 TPedValues::~TPedValues() {}
0037
0038 void TPedValues::insert(const int gainId, const int crystal, const int DAC, const int pedestal, const int endcapIndex) {
0039
0040
0041 if (gainId <= 0 || gainId >= 4) {
0042 edm::LogWarning("EcalPedOffset") << "WARNING : TPedValues : gainId " << gainId << " does not exist, entry skipped";
0043 return;
0044 }
0045
0046
0047 if (crystal <= 0 || crystal > 1700) {
0048 edm::LogWarning("EcalPedOffset") << "WARNING : TPedValues : crystal " << crystal
0049 << " does not exist, entry skipped";
0050 return;
0051 }
0052
0053
0054 if (DAC < 0 || DAC >= 256) {
0055 edm::LogWarning("EcalPedOffset") << "WARNING : TPedValues : DAC value " << DAC << " is out range, entry skipped";
0056 return;
0057 }
0058 m_entries[gainId - 1][crystal - 1][DAC].insert(pedestal);
0059 endcapCrystalNumbers[crystal - 1] = endcapIndex;
0060 return;
0061 }
0062
0063 TPedResult TPedValues::terminate(const int &DACstart, const int &DACend) const {
0064 assert(DACstart >= 0);
0065 assert(DACend <= 256);
0066
0067
0068 TPedResult bestDAC;
0069
0070 for (int gainId = 1; gainId < 4; ++gainId) {
0071
0072 for (int crystal = 0; crystal < 1700; ++crystal) {
0073
0074 double delta = 1000;
0075 int dummyBestDAC = -1;
0076 bool hasDigis = false;
0077
0078 for (int DAC = DACstart; DAC < DACend; ++DAC) {
0079 double average = m_entries[gainId - 1][crystal][DAC].average();
0080 if (average == -1)
0081 continue;
0082 hasDigis = true;
0083 if (m_entries[gainId - 1][crystal][DAC].RMSSq() > m_RMSmax * m_RMSmax)
0084 continue;
0085 if (fabs(average - m_bestPedestal) < delta && average > 1) {
0086 delta = fabs(average - m_bestPedestal);
0087 dummyBestDAC = DAC;
0088 }
0089 }
0090
0091 bestDAC.m_DACvalue[gainId - 1][crystal] = dummyBestDAC;
0092
0093 if ((dummyBestDAC == (DACend - 1) || dummyBestDAC == -1) && hasDigis) {
0094 int gainHuman;
0095 if (gainId == 1)
0096 gainHuman = 12;
0097 else if (gainId == 2)
0098 gainHuman = 6;
0099 else if (gainId == 3)
0100 gainHuman = 1;
0101 else
0102 gainHuman = -1;
0103 edm::LogError("EcalPedOffset") << " TPedValues : cannot find best DAC value for channel: "
0104 << endcapCrystalNumbers[crystal] << " gain: " << gainHuman;
0105 }
0106
0107 }
0108 }
0109 return bestDAC;
0110 }
0111
0112 int TPedValues::checkEntries(const int &DACstart, const int &DACend) const {
0113 assert(DACstart >= 0);
0114 assert(DACend <= 256);
0115 int returnCode = 0;
0116
0117 for (int gainId = 1; gainId < 4; ++gainId) {
0118
0119 for (int crystal = 0; crystal < 1700; ++crystal) {
0120
0121 for (int DAC = DACstart; DAC < DACend; ++DAC) {
0122 double average = m_entries[gainId - 1][crystal][DAC].average();
0123 if (average == -1) {
0124 ++returnCode;
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134 }
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144 }
0145 }
0146 }
0147 return returnCode;
0148 }
0149
0150
0151 int TPedValues::makePlots(TFile *rootFile,
0152 const std::string &dirName,
0153 const double maxSlope,
0154 const double minSlope,
0155 const double maxChi2OverNDF) const {
0156 using namespace std;
0157
0158 if (!rootFile->cd(dirName.c_str())) {
0159 rootFile->mkdir(dirName.c_str());
0160 rootFile->cd(dirName.c_str());
0161 }
0162
0163
0164 for (int xtl = 0; xtl < 1700; ++xtl) {
0165
0166 for (int gain = 0; gain < 3; ++gain) {
0167 vector<double> asseX;
0168 vector<double> sigmaX;
0169 vector<double> asseY;
0170 vector<double> sigmaY;
0171 asseX.reserve(256);
0172 sigmaX.reserve(256);
0173 asseY.reserve(256);
0174 sigmaY.reserve(256);
0175
0176 for (int dac = 0; dac < 256; ++dac) {
0177 double average = m_entries[gain][xtl][dac].average();
0178 if (average > -1) {
0179 double rms = m_entries[gain][xtl][dac].RMS();
0180 asseX.push_back(dac);
0181 sigmaX.push_back(0);
0182 asseY.push_back(average);
0183 sigmaY.push_back(rms);
0184 }
0185 }
0186 if (!asseX.empty()) {
0187 int lastBin = 0;
0188 while (lastBin < (int)asseX.size() - 1 && asseY[lastBin + 1] > 0 &&
0189 (asseY[lastBin + 1] - asseY[lastBin + 2]) != 0)
0190 lastBin++;
0191
0192 int fitRangeEnd = (int)asseX[lastBin];
0193 int kinkPt = 64;
0194 if (fitRangeEnd < 66)
0195 kinkPt = fitRangeEnd - 4;
0196 TGraphErrors graph(asseX.size(), &(*asseX.begin()), &(*asseY.begin()), &(*sigmaX.begin()), &(*sigmaY.begin()));
0197 char funct[120];
0198 sprintf(funct, "(x<%d)*([0]*x+[1])+(x>=%d)*([2]*x+[3])", kinkPt, kinkPt);
0199 TF1 fitFunction("fitFunction", funct, asseX[0], fitRangeEnd);
0200 fitFunction.SetLineColor(2);
0201
0202 char name[120];
0203 int gainHuman;
0204 if (gain == 0)
0205 gainHuman = 12;
0206 else if (gain == 1)
0207 gainHuman = 6;
0208 else if (gain == 2)
0209 gainHuman = 1;
0210 else
0211 gainHuman = -1;
0212 sprintf(name, "XTL%04d_GAIN%02d", endcapCrystalNumbers[xtl], gainHuman);
0213 graph.GetXaxis()->SetTitle("DAC value");
0214 graph.GetYaxis()->SetTitle("Average pedestal ADC");
0215 graph.Fit(&fitFunction, "RWQ");
0216 graph.Write(name);
0217
0218 double slope1 = fitFunction.GetParameter(0);
0219 double slope2 = fitFunction.GetParameter(2);
0220
0221 if (fitFunction.GetChisquare() / fitFunction.GetNDF() > maxChi2OverNDF ||
0222 fitFunction.GetChisquare() / fitFunction.GetNDF() < 0 || slope1 > 0 || slope2 > 0 ||
0223 ((slope1 < -29 || slope1 > -18) && slope1 < 0) || ((slope2 < -29 || slope2 > -18) && slope2 < 0)) {
0224 edm::LogError("EcalPedOffset") << "TPedValues : TGraph for channel:" << endcapCrystalNumbers[xtl]
0225 << " gain:" << gainHuman << " is not linear;"
0226 << " slope of line1:" << fitFunction.GetParameter(0)
0227 << " slope of line2:" << fitFunction.GetParameter(2) << " reduced chi-squared:"
0228 << fitFunction.GetChisquare() / fitFunction.GetNDF();
0229 }
0230
0231
0232
0233
0234
0235 if ((asseX.back() - asseX.front() + 1) != asseX.size())
0236 edm::LogError("EcalPedOffset") << "TPedValues : Pedestal average not found "
0237 << "for all DAC values scanned in channel:" << endcapCrystalNumbers[xtl]
0238 << " gain:" << gainHuman;
0239 }
0240 }
0241 }
0242
0243 return 0;
0244 }
0245
0246
0247 int TPedValues::getCrystalNumber(int xtal) const { return endcapCrystalNumbers[xtal]; }