File indexing completed on 2024-04-06 11:59:37
0001 #include "CalibTracker/SiPixelSCurveCalibration/interface/SiPixelSCurveCalibrationAnalysis.h"
0002 #include "TMath.h"
0003
0004 #include <fstream>
0005 #include <iostream>
0006
0007 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0008 #include "CondFormats/SiPixelObjects/interface/DetectorIndex.h"
0009 #include "CondFormats/SiPixelObjects/interface/ElectronicIndex.h"
0010 #include "CondFormats/SiPixelObjects/interface/LocalPixel.h"
0011 #include "CondFormats/SiPixelObjects/interface/SiPixelFrameConverter.h"
0012 #include "DataFormats/SiPixelDigi/interface/SiPixelCalibDigiError.h"
0013 #include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
0014 #include <sstream>
0015
0016
0017 std::vector<float> SiPixelSCurveCalibrationAnalysis::efficiencies_(0);
0018 std::vector<float> SiPixelSCurveCalibrationAnalysis::effErrors_(0);
0019
0020 void SiPixelSCurveCalibrationAnalysis::calibrationEnd() {
0021 if (printoutthresholds_)
0022 makeThresholdSummary();
0023 }
0024
0025 void SiPixelSCurveCalibrationAnalysis::makeThresholdSummary(void) {
0026 std::ofstream myfile;
0027 myfile.open(thresholdfilename_.c_str());
0028 for (detIDHistogramMap::iterator thisDetIdHistoGrams = histograms_.begin(); thisDetIdHistoGrams != histograms_.end();
0029 ++thisDetIdHistoGrams) {
0030
0031 const MonitorElement *sigmahist = (*thisDetIdHistoGrams).second[kSigmas];
0032 const MonitorElement *thresholdhist = (*thisDetIdHistoGrams).second[kThresholds];
0033 uint32_t detid = (*thisDetIdHistoGrams).first;
0034 std::string name = sigmahist->getTitle();
0035 std::string rocname = name.substr(0, name.size() - 7);
0036 rocname += "_ROC";
0037 int total_rows = sigmahist->getNbinsY();
0038 int total_columns = sigmahist->getNbinsX();
0039
0040 for (int irow = 0; irow < total_rows; ++irow) {
0041 for (int icol = 0; icol < total_columns; ++icol) {
0042 float threshold_error = sigmahist->getBinContent(icol + 1, irow + 1);
0043 if (writeZeroes_ || (!writeZeroes_ && threshold_error > 0)) {
0044
0045 int realfedID = -1;
0046 for (int fedid = 0; fedid <= 40; ++fedid) {
0047 SiPixelFrameConverter converter(theCablingMap_.product(), fedid);
0048 if (converter.hasDetUnit(detid)) {
0049 realfedID = fedid;
0050 break;
0051 }
0052 }
0053 if (realfedID == -1) {
0054 std::cout << "error: could not obtain real fed ID" << std::endl;
0055 }
0056 sipixelobjects::DetectorIndex detector = {detid, irow, icol};
0057 sipixelobjects::ElectronicIndex cabling;
0058 SiPixelFrameConverter formatter(theCablingMap_.product(), realfedID);
0059 formatter.toCabling(cabling, detector);
0060
0061
0062
0063 sipixelobjects::LocalPixel::DcolPxid loc;
0064 loc.dcol = cabling.dcol;
0065 loc.pxid = cabling.pxid;
0066
0067
0068
0069
0070
0071
0072
0073 sipixelobjects::LocalPixel locpixel(loc);
0074 sipixelobjects::CablingPathToDetUnit path = {static_cast<unsigned int>(realfedID),
0075 static_cast<unsigned int>(cabling.link),
0076 static_cast<unsigned int>(cabling.roc)};
0077 const sipixelobjects::PixelROC *theRoc = theCablingMap_->findItem(path);
0078
0079 int newrow = locpixel.rocRow();
0080 int newcol = locpixel.rocCol();
0081 myfile << rocname << theRoc->idInDetUnit() << " " << newcol << " " << newrow << " "
0082 << thresholdhist->getBinContent(icol + 1, irow + 1) << " "
0083 << threshold_error;
0084 myfile << "\n";
0085 }
0086 }
0087 }
0088 }
0089 myfile.close();
0090 }
0091
0092
0093 void chi2toMinimize(int &npar, double *grad, double &fcnval, double *xval, int iflag) {
0094 TF1 *theFormula = SiPixelSCurveCalibrationAnalysis::fitFunction_;
0095
0096 for (int i = 0; i < npar; i++)
0097 theFormula->SetParameter(i, xval[i]);
0098 fcnval = 0;
0099
0100 const std::vector<short> *theVCalValues = SiPixelSCurveCalibrationAnalysis::getVcalValues();
0101 for (uint32_t i = 0; i < theVCalValues->size(); i++) {
0102 float chi = (SiPixelSCurveCalibrationAnalysis::efficiencies_[i] - theFormula->Eval((*theVCalValues)[i]));
0103 chi /= SiPixelSCurveCalibrationAnalysis::effErrors_[i];
0104 fcnval += chi * chi;
0105 }
0106 }
0107
0108 void SiPixelSCurveCalibrationAnalysis::doSetup(const edm::ParameterSet &iConfig) {
0109 edm::LogInfo("SiPixelSCurveCalibrationAnalysis") << "Setting up calibration paramters.";
0110 std::vector<uint32_t> anEmptyDefaultVectorOfUInts;
0111 std::vector<uint32_t> detIDsToSaveVector_;
0112 useDetectorHierarchyFolders_ = iConfig.getUntrackedParameter<bool>("useDetectorHierarchyFolders", true);
0113 saveCurvesThatFlaggedBad_ = iConfig.getUntrackedParameter<bool>("saveCurvesThatFlaggedBad", false);
0114 detIDsToSaveVector_ =
0115 iConfig.getUntrackedParameter<std::vector<uint32_t>>("detIDsToSave", anEmptyDefaultVectorOfUInts);
0116 maxCurvesToSave_ = iConfig.getUntrackedParameter<uint32_t>("maxCurvesToSave", 1000);
0117 write2dHistograms_ = iConfig.getUntrackedParameter<bool>("write2dHistograms", true);
0118 write2dFitResult_ = iConfig.getUntrackedParameter<bool>("write2dFitResult", true);
0119 printoutthresholds_ = iConfig.getUntrackedParameter<bool>("writeOutThresholdSummary", true);
0120 thresholdfilename_ = iConfig.getUntrackedParameter<std::string>("thresholdOutputFileName", "thresholds.txt");
0121 minimumChi2prob_ = iConfig.getUntrackedParameter<double>("minimumChi2prob", 0);
0122 minimumThreshold_ = iConfig.getUntrackedParameter<double>("minimumThreshold", -10);
0123 maximumThreshold_ = iConfig.getUntrackedParameter<double>("maximumThreshold", 300);
0124 minimumSigma_ = iConfig.getUntrackedParameter<double>("minimumSigma", 0);
0125 maximumSigma_ = iConfig.getUntrackedParameter<double>("maximumSigma", 100);
0126 minimumEffAsymptote_ = iConfig.getUntrackedParameter<double>("minimumEffAsymptote", 0);
0127 maximumEffAsymptote_ = iConfig.getUntrackedParameter<double>("maximumEffAsymptote", 1000);
0128 maximumSigmaBin_ = iConfig.getUntrackedParameter<double>("maximumSigmaBin", 10);
0129 maximumThresholdBin_ = iConfig.getUntrackedParameter<double>("maximumThresholdBin", 255);
0130
0131 writeZeroes_ = iConfig.getUntrackedParameter<bool>("alsoWriteZeroThresholds", false);
0132
0133
0134 for (unsigned int i = 0; i < detIDsToSaveVector_.size(); i++)
0135 detIDsToSave_.insert(std::make_pair(detIDsToSaveVector_[i], true));
0136 }
0137
0138 SiPixelSCurveCalibrationAnalysis::~SiPixelSCurveCalibrationAnalysis() {
0139
0140 }
0141
0142 void SiPixelSCurveCalibrationAnalysis::buildACurveHistogram(const uint32_t &detid,
0143 const uint32_t &row,
0144 const uint32_t &col,
0145 sCurveErrorFlag errorFlag,
0146 const std::vector<float> &efficiencies,
0147 const std::vector<float> &errors) {
0148 if (curvesSavedCounter_ > maxCurvesToSave_) {
0149 edm::LogWarning("SiPixelSCurveCalibrationAnalysis")
0150 << "WARNING: Request to save curve for [detid](col/row): [" << detid << "](" << col << "/" << row
0151 << ") denied. Maximum number of saved curves (defined in .cfi) "
0152 "exceeded.";
0153 return;
0154 }
0155 std::ostringstream rootName;
0156 rootName << "SCurve_row_" << row << "_col_" << col;
0157 std::ostringstream humanName;
0158 humanName << translateDetIdToString(detid) << "_" << rootName.str() << "_ErrorFlag_" << (int)errorFlag;
0159
0160 unsigned int numberOfVCalPoints = vCalPointsAsFloats_.size() - 1;
0161
0162 if (efficiencies.size() != numberOfVCalPoints || errors.size() != numberOfVCalPoints) {
0163 edm::LogError("SiPixelSCurveCalibrationAnalysis")
0164 << "Error saving single curve histogram! Number of Vcal values (" << numberOfVCalPoints
0165 << ") does not match number of efficiency points or error points!";
0166 return;
0167 }
0168 setDQMDirectory(detid);
0169 float *vcalValuesToPassToCrappyRoot = &vCalPointsAsFloats_[0];
0170 MonitorElement *aBadHisto =
0171 bookDQMHistogram1D(detid,
0172 rootName.str(),
0173 humanName.str(),
0174 numberOfVCalPoints,
0175 vcalValuesToPassToCrappyRoot);
0176
0177 curvesSavedCounter_++;
0178 for (unsigned int iBin = 0; iBin < numberOfVCalPoints; ++iBin) {
0179 int rootBin = iBin + 1;
0180 aBadHisto->setBinContent(rootBin, efficiencies[iBin]);
0181 aBadHisto->setBinError(rootBin, errors[iBin]);
0182 }
0183 }
0184
0185 void SiPixelSCurveCalibrationAnalysis::calibrationSetup(const edm::EventSetup &iSetup) {
0186 edm::LogInfo("SiPixelSCurveCalibrationAnalysis")
0187 << "Calibration Settings: VCalLow: " << vCalValues_[0] << " VCalHigh: " << vCalValues_[vCalValues_.size() - 1]
0188 << " nVCal: " << vCalValues_.size() << " nTriggers: " << nTriggers_;
0189 curvesSavedCounter_ = 0;
0190 if (saveCurvesThatFlaggedBad_) {
0191
0192
0193 const std::vector<short> *theVCalValues = this->getVcalValues();
0194 unsigned int numberOfVCalPoints = theVCalValues->size();
0195 edm::LogWarning("SiPixelSCurveCalibrationAnalysis")
0196 << "WARNING: Option set to save indiviual S-Curves - max number: " << maxCurvesToSave_
0197 << " This can lead to large memory consumption! (Got " << numberOfVCalPoints << " VCal Points";
0198 for (unsigned int i = 0; i < numberOfVCalPoints; i++) {
0199 vCalPointsAsFloats_.push_back(static_cast<float>((*theVCalValues)[i]));
0200 edm::LogInfo("SiPixelSCurveCalibrationAnalysis") << "Adding calibration Vcal: " << (*theVCalValues)[i];
0201 }
0202
0203 vCalPointsAsFloats_.push_back(vCalPointsAsFloats_[numberOfVCalPoints - 1] + 1);
0204 }
0205
0206 fitFunction_ = new TF1("sCurve",
0207 "0.5*[2]*(1+TMath::Erf( (x-[0]) / ([1]*sqrt(2)) ) )",
0208 vCalValues_[0],
0209 vCalValues_[vCalValues_.size() - 1]);
0210 }
0211
0212 bool SiPixelSCurveCalibrationAnalysis::checkCorrectCalibrationType() {
0213 if (calibrationMode_ == "SCurve")
0214 return true;
0215 else if (calibrationMode_ == "unknown") {
0216 edm::LogInfo("SiPixelSCurveCalibrationAnalysis")
0217 << "calibration mode is: " << calibrationMode_ << ", continuing anyway...";
0218 return true;
0219 } else {
0220
0221
0222
0223 }
0224 return false;
0225 }
0226
0227 sCurveErrorFlag SiPixelSCurveCalibrationAnalysis::estimateSCurveParameters(const std::vector<float> &eff,
0228 float &threshold,
0229 float &sigma) {
0230 sCurveErrorFlag output = errAllZeros;
0231 bool allZeroSoFar = true;
0232 int turnOnBin = -1;
0233 int saturationBin = -1;
0234 for (uint32_t iVcalPt = 0; iVcalPt < eff.size(); iVcalPt++) {
0235 if (allZeroSoFar && eff[iVcalPt] != 0) {
0236 turnOnBin = iVcalPt;
0237 allZeroSoFar = false;
0238 output = errNoTurnOn;
0239 } else if (eff[iVcalPt] > 0.90) {
0240 saturationBin = iVcalPt;
0241 short turnOnVcal = vCalValues_[turnOnBin];
0242 short saturationVcal = vCalValues_[saturationBin];
0243 short delta = saturationVcal - turnOnVcal;
0244 sigma = delta * 0.682;
0245 if (sigma < 1)
0246
0247 sigma = 1;
0248 threshold = turnOnVcal + (0.5 * delta);
0249 return errOK;
0250 }
0251 }
0252 return output;
0253 }
0254
0255 sCurveErrorFlag SiPixelSCurveCalibrationAnalysis::fittedSCurveSanityCheck(float threshold,
0256 float sigma,
0257 float amplitude) {
0258
0259 if (threshold > vCalValues_[vCalValues_.size() - 1] || threshold < vCalValues_[0] ||
0260 sigma > vCalValues_[vCalValues_.size() - 1] - vCalValues_[0])
0261 return errFitNonPhysical;
0262
0263 if (threshold < minimumThreshold_ || threshold > maximumThreshold_ || sigma < minimumSigma_ ||
0264 sigma > maximumSigma_ || amplitude < minimumEffAsymptote_ || amplitude > maximumEffAsymptote_)
0265 return errFlaggedBadByUser;
0266
0267 return errOK;
0268 }
0269
0270 void calculateEffAndError(int nADCResponse, int nTriggers, float &eff, float &error) {
0271 eff = (float)nADCResponse / (float)nTriggers;
0272 double effForErrorCalculation = eff;
0273 if (eff <= 0 || eff >= 1)
0274 effForErrorCalculation = 0.5 / (double)nTriggers;
0275 error = TMath::Sqrt(effForErrorCalculation * (1 - effForErrorCalculation) / (double)nTriggers);
0276 }
0277
0278
0279 void SiPixelSCurveCalibrationAnalysis::newDetID(uint32_t detid) {
0280 edm::LogInfo("SiPixelSCurveCalibrationAnalysis")
0281 << "Found a new DetID (" << detid << ")! Checking to make sure it has not been added.";
0282
0283 sCurveHistogramHolder tempMap;
0284 std::pair<detIDHistogramMap::iterator, bool> insertResult;
0285 insertResult = histograms_.insert(std::make_pair(detid, tempMap));
0286 if (insertResult.second)
0287 {
0288 edm::LogInfo("SiPixelSCurveCalibrationAnalysisHistogramReport")
0289 << "Histogram Map.insert() returned true! Booking new histogrames for "
0290 "detID: "
0291 << detid;
0292
0293 if (useDetectorHierarchyFolders_)
0294 setDQMDirectory(detid);
0295
0296 std::string detIdName = translateDetIdToString(detid);
0297 if (write2dHistograms_) {
0298 MonitorElement *D2sigma = bookDQMHistoPlaquetteSummary2D(detid, "ScurveSigmas", detIdName + " Sigmas");
0299 MonitorElement *D2thresh = bookDQMHistoPlaquetteSummary2D(detid, "ScurveThresholds", detIdName + " Thresholds");
0300 MonitorElement *D2chi2 = bookDQMHistoPlaquetteSummary2D(detid, "ScurveChi2Prob", detIdName + " Chi2Prob");
0301 insertResult.first->second.insert(std::make_pair(kSigmas, D2sigma));
0302 insertResult.first->second.insert(std::make_pair(kThresholds, D2thresh));
0303 insertResult.first->second.insert(std::make_pair(kChi2s, D2chi2));
0304 }
0305 if (write2dFitResult_) {
0306 MonitorElement *D2FitResult = bookDQMHistoPlaquetteSummary2D(detid, "ScurveFitResult", detIdName + " Fit Result");
0307 insertResult.first->second.insert(std::make_pair(kFitResults, D2FitResult));
0308 }
0309 MonitorElement *D1sigma =
0310 bookDQMHistogram1D(detid, "ScurveSigmasSummary", detIdName + " Sigmas Summary", 100, 0, maximumSigmaBin_);
0311 MonitorElement *D1thresh = bookDQMHistogram1D(
0312 detid, "ScurveThresholdSummary", detIdName + " Thresholds Summary", 255, 0, maximumThresholdBin_);
0313 MonitorElement *D1chi2 =
0314 bookDQMHistogram1D(detid, "ScurveChi2ProbSummary", detIdName + " Chi2Prob Summary", 101, 0, 1.01);
0315 MonitorElement *D1FitResult =
0316 bookDQMHistogram1D(detid, "ScurveFitResultSummary", detIdName + " Fit Result Summary", 10, -0.5, 9.5);
0317 insertResult.first->second.insert(std::make_pair(kSigmaSummary, D1sigma));
0318 insertResult.first->second.insert(std::make_pair(kThresholdSummary, D1thresh));
0319 insertResult.first->second.insert(std::make_pair(kChi2Summary, D1chi2));
0320 insertResult.first->second.insert(std::make_pair(kFitResultSummary, D1FitResult));
0321 }
0322 }
0323
0324 bool SiPixelSCurveCalibrationAnalysis::doFits(uint32_t detid, std::vector<SiPixelCalibDigi>::const_iterator calibDigi) {
0325 sCurveErrorFlag errorFlag = errOK;
0326 uint32_t nVCalPts = calibDigi->getnpoints();
0327
0328 efficiencies_.resize(0);
0329 effErrors_.resize(0);
0330 for (uint32_t iVcalPt = 0; iVcalPt < nVCalPts; iVcalPt++) {
0331 float eff;
0332 float error;
0333 calculateEffAndError(calibDigi->getnentries(iVcalPt), nTriggers_, eff, error);
0334 edm::LogInfo("SiPixelSCurveCalibrationAnalysis")
0335 << "Eff: " << eff << " Error: " << error << " nEntries: " << calibDigi->getnentries(iVcalPt)
0336 << " nTriggers: " << nTriggers_ << " VCalPt " << vCalValues_[iVcalPt];
0337 efficiencies_.push_back(eff);
0338 effErrors_.push_back(error);
0339 }
0340
0341
0342 float thresholdGuess = -1.0;
0343 float sigmaGuess = -1.0;
0344 errorFlag = estimateSCurveParameters(efficiencies_, thresholdGuess, sigmaGuess);
0345
0346
0347
0348 Double_t sigma = -1.0;
0349 Double_t sigmaError = -1.0;
0350 Double_t threshold = -1.0;
0351 Double_t thresholdError = -1.0;
0352 Double_t amplitude = -1.0;
0353 Double_t amplitudeError = -1.0;
0354 Double_t chi2 = -1.0;
0355
0356 Int_t nDOF = vCalValues_.size() - 3;
0357 Double_t chi2probability = 0;
0358
0359 if (errorFlag == errOK)
0360 {
0361
0362 TMinuit *gMinuit = new TMinuit(3);
0363 gMinuit->SetPrintLevel(-1);
0364 gMinuit->SetFCN(chi2toMinimize);
0365
0366
0367 gMinuit->DefineParameter(0, "Threshold", (Double_t)thresholdGuess, 1, -50, 300);
0368
0369 gMinuit->DefineParameter(1, "Sigma", (Double_t)sigmaGuess, 0.1, 0, 255);
0370
0371 gMinuit->DefineParameter(2, "Amplitude", 1, 0.1, -0.001, 200);
0372
0373
0374 gMinuit->Migrad();
0375 gMinuit->GetParameter(0, threshold, thresholdError);
0376 gMinuit->GetParameter(1, sigma, sigmaError);
0377 gMinuit->GetParameter(2, amplitude, amplitudeError);
0378
0379
0380 Double_t params[3] = {threshold, sigma, amplitude};
0381 gMinuit->Eval(3, nullptr, chi2, params, 0);
0382
0383 if (nDOF <= 0)
0384 chi2probability = 0;
0385 else
0386 chi2probability = TMath::Prob(chi2, nDOF);
0387
0388
0389 if (chi2probability > minimumChi2prob_)
0390 errorFlag = fittedSCurveSanityCheck(threshold, sigma, amplitude);
0391 else
0392 errorFlag = errBadChi2Prob;
0393
0394 edm::LogInfo("SiPixelSCurveCalibrationAnalysis")
0395 << "Fit finished with errorFlag: " << errorFlag << " - threshold: " << threshold << " sigma: " << sigma
0396 << " chi2: " << chi2 << " nDOF: " << nDOF << " chi2Prob: " << chi2probability
0397 << " chi2MinUser: " << minimumChi2prob_;
0398
0399 delete gMinuit;
0400 }
0401
0402 uint32_t row = calibDigi->row();
0403 uint32_t col = calibDigi->col();
0404
0405
0406 detIDHistogramMap::iterator thisDetIdHistoGrams;
0407 thisDetIdHistoGrams = histograms_.find(detid);
0408 if (thisDetIdHistoGrams != histograms_.end()) {
0409 edm::LogInfo("SiPixelSCurveCalibrationAnalysisHistogramReport")
0410 << "Filling histograms for [detid](col/row): [" << detid << "](" << col << "/" << row
0411 << ") ErrorFlag: " << errorFlag;
0412
0413 (*thisDetIdHistoGrams).second[kFitResultSummary]->Fill(errorFlag);
0414 if (write2dFitResult_)
0415 (*thisDetIdHistoGrams)
0416 .second[kFitResults]
0417 ->setBinContent(col + 1,
0418 row + 1,
0419 errorFlag);
0420
0421
0422 (*thisDetIdHistoGrams).second[kSigmaSummary]->Fill(sigma);
0423 (*thisDetIdHistoGrams).second[kThresholdSummary]->Fill(threshold);
0424 if (write2dHistograms_) {
0425 (*thisDetIdHistoGrams)
0426 .second[kSigmas]
0427 ->setBinContent(col + 1,
0428 row + 1,
0429 sigma);
0430 (*thisDetIdHistoGrams)
0431 .second[kThresholds]
0432 ->setBinContent(col + 1,
0433 row + 1,
0434 threshold);
0435 }
0436
0437 (*thisDetIdHistoGrams).second[kChi2Summary]->Fill(chi2probability);
0438 if (write2dHistograms_)
0439 (*thisDetIdHistoGrams).second[kChi2s]->Fill(col, row, chi2probability);
0440 }
0441
0442 if (saveCurvesThatFlaggedBad_) {
0443 bool thisDetIDinList = false;
0444 if (detIDsToSave_.find(detid) != detIDsToSave_.end())
0445 thisDetIDinList = true;
0446
0447 if (errorFlag != errOK || thisDetIDinList) {
0448 edm::LogError("SiPixelSCurveCalibrationAnalysis") << "Saving error histogram for [detid](col/row): [" << detid
0449 << "](" << col << "/" << row << ") ErrorFlag: " << errorFlag;
0450 buildACurveHistogram(detid, row, col, errorFlag, efficiencies_, effErrors_);
0451 }
0452 }
0453
0454 return true;
0455 }