00001 #include "CalibTracker/SiPixelSCurveCalibration/interface/SiPixelSCurveCalibrationAnalysis.h"
00002 #include "TMath.h"
00003
00004 #include <iostream>
00005 #include <fstream>
00006
00007 #include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
00008 #include "DataFormats/SiPixelDigi/interface/SiPixelCalibDigiError.h"
00009 #include "CondFormats/SiPixelObjects/interface/SiPixelFrameConverter.h"
00010 #include "CondFormats/SiPixelObjects/interface/ElectronicIndex.h"
00011 #include "CondFormats/SiPixelObjects/interface/DetectorIndex.h"
00012 #include "CondFormats/SiPixelObjects/interface/LocalPixel.h"
00013 #include <sstream>
00014
00015
00016 std::vector<float> SiPixelSCurveCalibrationAnalysis::efficiencies_(0);
00017 std::vector<float> SiPixelSCurveCalibrationAnalysis::effErrors_(0);
00018
00019
00020 void SiPixelSCurveCalibrationAnalysis::calibrationEnd(){
00021 if(printoutthresholds_)
00022 makeThresholdSummary();
00023 }
00024
00025 void SiPixelSCurveCalibrationAnalysis::makeThresholdSummary(void){
00026 ofstream myfile;
00027 myfile.open (thresholdfilename_.c_str());
00028 for(detIDHistogramMap::iterator thisDetIdHistoGrams= histograms_.begin(); thisDetIdHistoGrams != histograms_.end(); ++thisDetIdHistoGrams){
00029
00030 const MonitorElement *sigmahist = (*thisDetIdHistoGrams).second[kSigmas];
00031 const MonitorElement *thresholdhist = (*thisDetIdHistoGrams).second[kThresholds];
00032 uint32_t detid = (*thisDetIdHistoGrams).first;
00033 std::string name = sigmahist->getTitle();
00034 std::string rocname = name.substr(0,name.size()-7);
00035 rocname+="_ROC";
00036 int total_rows = sigmahist ->getNbinsY();
00037 int total_columns = sigmahist->getNbinsX();
00038
00039 for (int irow=0; irow<total_rows; ++irow){
00040 for (int icol=0; icol<total_columns; ++icol){
00041 float threshold_error = sigmahist->getBinContent(icol+1,irow+1);
00042 if(writeZeroes_ ||(!writeZeroes_ && threshold_error>0)){
00043
00044 int realfedID=-1;
00045 for(int fedid=0; fedid<=40; ++fedid){
00046 SiPixelFrameConverter converter(theCablingMap_.product(),fedid);
00047 if(converter.hasDetUnit(detid)){
00048 realfedID=fedid;
00049 break;
00050 }
00051 }
00052 if (realfedID==-1){
00053 std::cout<<"error: could not obtain real fed ID"<<std::endl;
00054 }
00055 sipixelobjects::DetectorIndex detector ={detid,irow,icol};
00056 sipixelobjects::ElectronicIndex cabling;
00057 SiPixelFrameConverter formatter(theCablingMap_.product(),realfedID);
00058 formatter.toCabling(cabling,detector);
00059
00060
00061 sipixelobjects::LocalPixel::DcolPxid loc;
00062 loc.dcol = cabling.dcol;
00063 loc.pxid = cabling.pxid;
00064
00065
00066
00067
00068 sipixelobjects::LocalPixel locpixel(loc);
00069 sipixelobjects::CablingPathToDetUnit path = {realfedID, cabling.link, cabling.roc};
00070 const sipixelobjects::PixelROC *theRoc = theCablingMap_->findItem(path);
00071
00072 int newrow= locpixel.rocRow();
00073 int newcol = locpixel.rocCol();
00074 myfile<<rocname<<theRoc->idInDetUnit()<<" "<<newcol<<" "<<newrow<<" "<<thresholdhist->getBinContent(icol+1, irow+1)<<" "<<threshold_error;
00075 myfile<<"\n";
00076 }
00077 }
00078 }
00079 }
00080 myfile.close();
00081 }
00082
00083
00084 void chi2toMinimize(int &npar, double* grad, double &fcnval, double* xval, int iflag)
00085 {
00086 TF1 * theFormula = SiPixelSCurveCalibrationAnalysis::fitFunction_;
00087
00088 for (int i = 0; i < npar; i++)
00089 theFormula->SetParameter(i, xval[i]);
00090 fcnval = 0;
00091
00092 const std::vector<short>* theVCalValues = SiPixelSCurveCalibrationAnalysis::getVcalValues();
00093 for (uint32_t i = 0; i < theVCalValues->size(); i++)
00094 {
00095 float chi = (SiPixelSCurveCalibrationAnalysis::efficiencies_[i] - theFormula->Eval((*theVCalValues)[i]) );
00096 chi /= SiPixelSCurveCalibrationAnalysis::effErrors_[i];
00097 fcnval += chi*chi;
00098 }
00099 }
00100
00101 void
00102 SiPixelSCurveCalibrationAnalysis::doSetup(const edm::ParameterSet& iConfig)
00103 {
00104 edm::LogInfo("SiPixelSCurveCalibrationAnalysis") << "Setting up calibration paramters.";
00105 std::vector<uint32_t> anEmptyDefaultVectorOfUInts;
00106 std::vector<uint32_t> detIDsToSaveVector_;
00107 useDetectorHierarchyFolders_ = iConfig.getUntrackedParameter<bool>("useDetectorHierarchyFolders", true);
00108 saveCurvesThatFlaggedBad_ = iConfig.getUntrackedParameter<bool>("saveCurvesThatFlaggedBad", false);
00109 detIDsToSaveVector_ = iConfig.getUntrackedParameter<std::vector<uint32_t> >("detIDsToSave", anEmptyDefaultVectorOfUInts);
00110 maxCurvesToSave_ = iConfig.getUntrackedParameter<uint32_t>("maxCurvesToSave", 1000);
00111 write2dHistograms_ = iConfig.getUntrackedParameter<bool>("write2dHistograms", true);
00112 write2dFitResult_ = iConfig.getUntrackedParameter<bool>("write2dFitResult", true);
00113 printoutthresholds_ = iConfig.getUntrackedParameter<bool>("writeOutThresholdSummary",true);
00114 thresholdfilename_ = iConfig.getUntrackedParameter<std::string>("thresholdOutputFileName","thresholds.txt");
00115 minimumChi2prob_ = iConfig.getUntrackedParameter<double>("minimumChi2prob", 0);
00116 minimumThreshold_ = iConfig.getUntrackedParameter<double>("minimumThreshold", -10);
00117 maximumThreshold_ = iConfig.getUntrackedParameter<double>("maximumThreshold", 300);
00118 minimumSigma_ = iConfig.getUntrackedParameter<double>("minimumSigma", 0);
00119 maximumSigma_ = iConfig.getUntrackedParameter<double>("maximumSigma", 100);
00120 minimumEffAsymptote_ = iConfig.getUntrackedParameter<double>("minimumEffAsymptote", 0);
00121 maximumEffAsymptote_ = iConfig.getUntrackedParameter<double>("maximumEffAsymptote", 1000);
00122 maximumSigmaBin_ = iConfig.getUntrackedParameter<double>("maximumSigmaBin", 10);
00123 maximumThresholdBin_ = iConfig.getUntrackedParameter<double>("maximumThresholdBin", 255);
00124
00125 writeZeroes_= iConfig.getUntrackedParameter<bool>("alsoWriteZeroThresholds", false);
00126
00127
00128 for(unsigned int i = 0; i < detIDsToSaveVector_.size(); i++)
00129 detIDsToSave_.insert( std::make_pair(detIDsToSaveVector_[i], true) );
00130 }
00131
00132 SiPixelSCurveCalibrationAnalysis::~SiPixelSCurveCalibrationAnalysis()
00133 {
00134
00135 }
00136
00137 void SiPixelSCurveCalibrationAnalysis::buildACurveHistogram(const uint32_t& detid, const uint32_t& row, const uint32_t& col, sCurveErrorFlag errorFlag, const std::vector<float>& efficiencies, const std::vector<float>& errors)
00138 {
00139 if (curvesSavedCounter_ > maxCurvesToSave_)
00140 {
00141 edm::LogWarning("SiPixelSCurveCalibrationAnalysis") << "WARNING: Request to save curve for [detid](col/row): [" << detid << "](" << col << "/" << row << ") denied. Maximum number of saved curves (defined in .cfi) exceeded.";
00142 return;
00143 }
00144 std::ostringstream rootName;
00145 rootName << "SCurve_row_" << row << "_col_" << col;
00146 std::ostringstream humanName;
00147 humanName << translateDetIdToString(detid) << "_" << rootName.str() << "_ErrorFlag_" << (int)errorFlag;
00148
00149 unsigned int numberOfVCalPoints = vCalPointsAsFloats_.size()-1;
00150 if (efficiencies.size() != numberOfVCalPoints || errors.size() != numberOfVCalPoints)
00151 {
00152 edm::LogError("SiPixelSCurveCalibrationAnalysis") << "Error saving single curve histogram! Number of Vcal values (" << numberOfVCalPoints << ") does not match number of efficiency points or error points!";
00153 return;
00154 }
00155 setDQMDirectory(detid);
00156 float * vcalValuesToPassToCrappyRoot = &vCalPointsAsFloats_[0];
00157 MonitorElement * aBadHisto = bookDQMHistogram1D(detid, rootName.str(), humanName.str(), numberOfVCalPoints, vcalValuesToPassToCrappyRoot);
00158 curvesSavedCounter_++;
00159 for(unsigned int iBin = 0; iBin < numberOfVCalPoints; ++iBin)
00160 {
00161 int rootBin = iBin + 1;
00162 aBadHisto->setBinContent(rootBin, efficiencies[iBin]);
00163 aBadHisto->setBinError(rootBin, errors[iBin]);
00164 }
00165 }
00166
00167 void SiPixelSCurveCalibrationAnalysis::calibrationSetup(const edm::EventSetup& iSetup)
00168 {
00169 edm::LogInfo("SiPixelSCurveCalibrationAnalysis") << "Calibration Settings: VCalLow: " << vCalValues_[0] << " VCalHigh: " << vCalValues_[vCalValues_.size()-1] << " nVCal: " << vCalValues_.size() << " nTriggers: " << nTriggers_;
00170 curvesSavedCounter_ = 0;
00171 if (saveCurvesThatFlaggedBad_)
00172 {
00173
00174 const std::vector<short>* theVCalValues = this->getVcalValues();
00175 unsigned int numberOfVCalPoints = theVCalValues->size();
00176 edm::LogWarning("SiPixelSCurveCalibrationAnalysis") << "WARNING: Option set to save indiviual S-Curves - max number: "
00177 << maxCurvesToSave_ << " This can lead to large memory consumption! (Got " << numberOfVCalPoints << " VCal Points";
00178 for(unsigned int i = 0; i < numberOfVCalPoints; i++)
00179 {
00180 vCalPointsAsFloats_.push_back( static_cast<float>((*theVCalValues)[i]) );
00181 edm::LogInfo("SiPixelSCurveCalibrationAnalysis") << "Adding calibration Vcal: " << (*theVCalValues)[i];
00182 }
00183
00184 vCalPointsAsFloats_.push_back( vCalPointsAsFloats_[numberOfVCalPoints-1] + 1 );
00185 }
00186
00187 fitFunction_ = new TF1("sCurve", "0.5*[2]*(1+TMath::Erf( (x-[0]) / ([1]*sqrt(2)) ) )", vCalValues_[0], vCalValues_[vCalValues_.size()-1]);
00188 }
00189
00190 bool
00191 SiPixelSCurveCalibrationAnalysis::checkCorrectCalibrationType()
00192 {
00193 if(calibrationMode_=="SCurve")
00194 return true;
00195 else if(calibrationMode_=="unknown"){
00196 edm::LogInfo("SiPixelSCurveCalibrationAnalysis") << "calibration mode is: " << calibrationMode_ << ", continuing anyway..." ;
00197 return true;
00198 }
00199 else{
00200
00201 }
00202 return false;
00203 }
00204
00205 sCurveErrorFlag SiPixelSCurveCalibrationAnalysis::estimateSCurveParameters(const std::vector<float>& eff, float& threshold, float& sigma)
00206 {
00207 sCurveErrorFlag output = errAllZeros;
00208 bool allZeroSoFar = true;
00209 int turnOnBin = -1;
00210 int saturationBin = -1;
00211 for (uint32_t iVcalPt = 0; iVcalPt < eff.size(); iVcalPt++)
00212 {
00213 if (allZeroSoFar && eff[iVcalPt] != 0 ) {
00214 turnOnBin = iVcalPt;
00215 allZeroSoFar = false;
00216 output = errNoTurnOn;
00217 } else if (eff[iVcalPt] > 0.90)
00218 {
00219 saturationBin = iVcalPt;
00220 short turnOnVcal = vCalValues_[turnOnBin];
00221 short saturationVcal = vCalValues_[saturationBin];
00222 short delta = saturationVcal - turnOnVcal;
00223 sigma = delta * 0.682;
00224 if (sigma < 1)
00225 sigma = 1;
00226 threshold = turnOnVcal + (0.5 * delta);
00227 return errOK;
00228 }
00229 }
00230 return output;
00231 }
00232
00233 sCurveErrorFlag SiPixelSCurveCalibrationAnalysis::fittedSCurveSanityCheck(float threshold, float sigma, float amplitude)
00234 {
00235
00236 if (threshold > vCalValues_[vCalValues_.size()-1] || threshold < vCalValues_[0] ||
00237 sigma > vCalValues_[vCalValues_.size()-1] - vCalValues_[0] )
00238 return errFitNonPhysical;
00239
00240 if (threshold < minimumThreshold_ || threshold > maximumThreshold_ ||
00241 sigma < minimumSigma_ || sigma > maximumSigma_ ||
00242 amplitude < minimumEffAsymptote_ || amplitude > maximumEffAsymptote_)
00243 return errFlaggedBadByUser;
00244
00245 return errOK;
00246 }
00247
00248 void calculateEffAndError(int nADCResponse, int nTriggers, float& eff, float& error)
00249 {
00250 eff = (float)nADCResponse / (float)nTriggers;
00251 double effForErrorCalculation = eff;
00252 if (eff <= 0 || eff >= 1)
00253 effForErrorCalculation = 0.5 / (double)nTriggers;
00254 error = TMath::Sqrt(effForErrorCalculation*(1-effForErrorCalculation) / (double)nTriggers);
00255 }
00256
00257
00258 void SiPixelSCurveCalibrationAnalysis::newDetID(uint32_t detid)
00259 {
00260 edm::LogInfo("SiPixelSCurveCalibrationAnalysis") << "Found a new DetID (" << detid << ")! Checking to make sure it has not been added.";
00261
00262 sCurveHistogramHolder tempMap;
00263 std::pair<detIDHistogramMap::iterator, bool> insertResult;
00264 insertResult = histograms_.insert(std::make_pair(detid, tempMap));
00265 if (insertResult.second)
00266 {
00267 edm::LogInfo("SiPixelSCurveCalibrationAnalysisHistogramReport") << "Histogram Map.insert() returned true! Booking new histogrames for detID: " << detid;
00268
00269 if (useDetectorHierarchyFolders_)
00270 setDQMDirectory(detid);
00271
00272 std::string detIdName = translateDetIdToString(detid);
00273 if (write2dHistograms_){
00274 MonitorElement * D2sigma = bookDQMHistoPlaquetteSummary2D(detid,"ScurveSigmas", detIdName + " Sigmas");
00275 MonitorElement * D2thresh = bookDQMHistoPlaquetteSummary2D(detid,"ScurveThresholds", detIdName + " Thresholds");
00276 MonitorElement * D2chi2 = bookDQMHistoPlaquetteSummary2D(detid,"ScurveChi2Prob",detIdName + " Chi2Prob");
00277 insertResult.first->second.insert(std::make_pair(kSigmas, D2sigma));
00278 insertResult.first->second.insert(std::make_pair(kThresholds, D2thresh));
00279 insertResult.first->second.insert(std::make_pair(kChi2s, D2chi2));
00280 }
00281 if (write2dFitResult_){
00282 MonitorElement * D2FitResult = bookDQMHistoPlaquetteSummary2D(detid,"ScurveFitResult", detIdName + " Fit Result");
00283 insertResult.first->second.insert(std::make_pair(kFitResults, D2FitResult));
00284 }
00285 MonitorElement * D1sigma = bookDQMHistogram1D(detid,"ScurveSigmasSummary", detIdName + " Sigmas Summary", 100, 0, maximumSigmaBin_);
00286 MonitorElement * D1thresh = bookDQMHistogram1D(detid,"ScurveThresholdSummary", detIdName + " Thresholds Summary", 255, 0, maximumThresholdBin_);
00287 MonitorElement * D1chi2 = bookDQMHistogram1D(detid,"ScurveChi2ProbSummary", detIdName + " Chi2Prob Summary", 101, 0, 1.01);
00288 MonitorElement * D1FitResult = bookDQMHistogram1D(detid,"ScurveFitResultSummary", detIdName + " Fit Result Summary", 10, -0.5, 9.5);
00289 insertResult.first->second.insert(std::make_pair(kSigmaSummary, D1sigma));
00290 insertResult.first->second.insert(std::make_pair(kThresholdSummary, D1thresh));
00291 insertResult.first->second.insert(std::make_pair(kChi2Summary, D1chi2));
00292 insertResult.first->second.insert(std::make_pair(kFitResultSummary, D1FitResult));
00293 }
00294 }
00295
00296 bool SiPixelSCurveCalibrationAnalysis::doFits(uint32_t detid, std::vector<SiPixelCalibDigi>::const_iterator calibDigi)
00297 {
00298 sCurveErrorFlag errorFlag = errOK;
00299 uint32_t nVCalPts = calibDigi->getnpoints();
00300
00301 efficiencies_.resize(0);
00302 effErrors_.resize(0);
00303 for (uint32_t iVcalPt = 0; iVcalPt < nVCalPts; iVcalPt++)
00304 {
00305 float eff;
00306 float error;
00307 calculateEffAndError(calibDigi->getnentries(iVcalPt), nTriggers_, eff, error);
00308 edm::LogInfo("SiPixelSCurveCalibrationAnalysis") << "Eff: " << eff << " Error: " << error << " nEntries: " << calibDigi->getnentries(iVcalPt) << " nTriggers: " << nTriggers_ << " VCalPt " << vCalValues_[iVcalPt];
00309 efficiencies_.push_back(eff);
00310 effErrors_.push_back(error);
00311 }
00312
00313
00314 float thresholdGuess;
00315 float sigmaGuess;
00316 errorFlag = estimateSCurveParameters(efficiencies_, thresholdGuess, sigmaGuess);
00317
00318
00319 Double_t sigma = -1.0;
00320 Double_t sigmaError = -1.0;
00321 Double_t threshold = -1.0;
00322 Double_t thresholdError = -1.0;
00323 Double_t amplitude = -1.0;
00324 Double_t amplitudeError = -1.0;
00325 Double_t chi2 = -1.0;
00326
00327 Int_t nDOF = vCalValues_.size() - 3;
00328 Double_t chi2probability = 0;
00329
00330 if (errorFlag == errOK)
00331 {
00332
00333 TMinuit *gMinuit = new TMinuit(3);
00334 gMinuit->SetPrintLevel(-1);
00335 gMinuit->SetFCN(chi2toMinimize);
00336
00337
00338 gMinuit->DefineParameter(0, "Threshold", (Double_t)thresholdGuess, 1, -50, 300);
00339
00340 gMinuit->DefineParameter(1, "Sigma", (Double_t)sigmaGuess, 0.1, 0, 255);
00341
00342 gMinuit->DefineParameter(2, "Amplitude", 1, 0.1, -0.001, 200);
00343
00344
00345 gMinuit->Migrad();
00346 gMinuit->GetParameter(0, threshold, thresholdError);
00347 gMinuit->GetParameter(1, sigma, sigmaError);
00348 gMinuit->GetParameter(2, amplitude, amplitudeError);
00349
00350
00351 Double_t params[3] = {threshold, sigma, amplitude};
00352 gMinuit->Eval(3, NULL, chi2, params, 0);
00353
00354 if (nDOF <= 0)
00355 chi2probability = 0;
00356 else
00357 chi2probability = TMath::Prob(chi2, nDOF);
00358
00359
00360 if (chi2probability > minimumChi2prob_)
00361 errorFlag = fittedSCurveSanityCheck(threshold, sigma, amplitude);
00362 else
00363 errorFlag = errBadChi2Prob;
00364
00365 edm::LogInfo("SiPixelSCurveCalibrationAnalysis") << "Fit finished with errorFlag: " << errorFlag << " - threshold: " << threshold << " sigma: " << sigma << " chi2: " << chi2 << " nDOF: " << nDOF << " chi2Prob: " << chi2probability << " chi2MinUser: " << minimumChi2prob_;
00366
00367 delete gMinuit;
00368 }
00369
00370 uint32_t row = calibDigi->row();
00371 uint32_t col = calibDigi->col();
00372
00373
00374 detIDHistogramMap::iterator thisDetIdHistoGrams;
00375 thisDetIdHistoGrams = histograms_.find(detid);
00376 if (thisDetIdHistoGrams != histograms_.end())
00377 {
00378 edm::LogInfo("SiPixelSCurveCalibrationAnalysisHistogramReport") << "Filling histograms for [detid](col/row): [" << detid << "](" << col << "/" << row << ") ErrorFlag: " << errorFlag;
00379
00380 (*thisDetIdHistoGrams).second[kFitResultSummary]->Fill(errorFlag);
00381 if (write2dFitResult_)
00382 (*thisDetIdHistoGrams).second[kFitResults]->setBinContent(col+1, row+1, errorFlag);
00383
00384
00385 (*thisDetIdHistoGrams).second[kSigmaSummary]->Fill(sigma);
00386 (*thisDetIdHistoGrams).second[kThresholdSummary]->Fill(threshold);
00387 if (write2dHistograms_)
00388 {
00389 (*thisDetIdHistoGrams).second[kSigmas]->setBinContent(col+1, row+1, sigma);
00390 (*thisDetIdHistoGrams).second[kThresholds]->setBinContent(col+1, row+1, threshold);
00391 }
00392
00393 (*thisDetIdHistoGrams).second[kChi2Summary]->Fill(chi2probability);
00394 if (write2dHistograms_)
00395 (*thisDetIdHistoGrams).second[kChi2s]->Fill(col, row, chi2probability);
00396 }
00397
00398 if (saveCurvesThatFlaggedBad_)
00399 {
00400 bool thisDetIDinList = false;
00401 if (detIDsToSave_.find(detid) != detIDsToSave_.end())
00402 thisDetIDinList = true;
00403
00404 if (errorFlag != errOK || thisDetIDinList)
00405 {
00406 edm::LogError("SiPixelSCurveCalibrationAnalysis") << "Saving error histogram for [detid](col/row): [" << detid << "](" << col << "/" << row << ") ErrorFlag: " << errorFlag;
00407 buildACurveHistogram(detid, row, col, errorFlag, efficiencies_, effErrors_);
00408 }
00409 }
00410
00411 return true;
00412
00413 }