Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 14:33:53

0001 #include "include/PlotCompareUtility.h"
0002 
0003 #include "include/Plot1D.h"
0004 #include "include/Plot2D.h"
0005 #include "include/PlotTypes.h"
0006 #include "include/Style.h"
0007 
0008 #include <fstream>
0009 
0010 #include <TCanvas.h>
0011 #include <TFile.h>
0012 #include <TGaxis.h>
0013 #include <TH1F.h>
0014 #include <TH2F.h>
0015 #include <TLine.h>
0016 #include <TPave.h>
0017 #include <TStyle.h>
0018 #include <TText.h>
0019 using namespace std;
0020 
0021 PlotCompareUtility::PlotCompareUtility(std::string Reference,
0022                                        std::string New,
0023                                        std::string NewBasePath,
0024                                        std::string NewPrefix,
0025                                        std::string RefBasePath,
0026                                        std::string RefPrefix) {
0027   // open TFiles
0028   cout << refFile << " " << newFile << endl;
0029   refFile = new TFile(Reference.c_str(), "READ");
0030   newFile = new TFile(New.c_str(), "READ");
0031 
0032   // set the data path and prefix
0033   newBasePath = NewBasePath;
0034   newPrefix = NewPrefix;
0035   refBasePath = RefBasePath;
0036   refPrefix = RefPrefix;
0037 
0038   // set default thresholds
0039   ksThreshold = 0;
0040   chi2Threshold = 0;
0041 
0042   // overall summary of results plot
0043   summaryWidth = 700;
0044   summaryBarsThickness = 20;
0045   summaryTopMargin = 60;
0046   summaryLeftMargin = 250;  // former 180
0047   summaryRightMargin = 60;
0048   summaryBottomMargin = 60;
0049 
0050   // summary of results for 2d projections
0051   projectionsHeight = 340;
0052   projectionsBarsThickness = 20;
0053   projectionsTopMargin = 20;
0054   projectionsBottomMargin = 60;
0055   projectionsLeftMargin = 100;
0056   projectionsRightMargin = 40;
0057 
0058   // 1d distribution overlays
0059   plotsWidth = 680;
0060   plotsHeight = 500;
0061   plotsTopMargin = 50;
0062   plotsBottomMargin = 80;
0063   plotsLeftMargin = 100;
0064   plotsRightMargin = 40;
0065 
0066   // initialize the 'final result' variable (set to false by any failing test)
0067   finalResult = true;
0068 
0069   // use (near as possible) tdrstyle for plots
0070   static TStyle style = genStyle();
0071   style.cd();
0072 }
0073 
0074 PlotCompareUtility::~PlotCompareUtility() {
0075   // close TFiles
0076   if (refFile != nullptr)
0077     refFile->Close();
0078   if (newFile != nullptr)
0079     newFile->Close();
0080 }
0081 
0082 void PlotCompareUtility::dump() {
0083   cout << "RefFile     = " << refFile->GetName() << endl
0084        << "RefBasePath = " << refBasePath << endl
0085        << "RefPrefix   = " << refPrefix << endl
0086        << "NewFile     = " << newFile->GetName() << endl
0087        << "NewBasePath = " << newBasePath << endl
0088        << "NewPrefix   = " << newPrefix << endl
0089        << "NumHistos   = " << histos.size() << endl;
0090 }
0091 
0092 bool PlotCompareUtility::compare(HistoData *HD) {
0093   bool retval = false;
0094   switch (HD->getType()) {
0095     case Plot1D:
0096       retval = compare<Plot1D>(HD);
0097       break;
0098     case Plot2D:
0099       retval = compare<Plot2D>(HD);
0100       break;
0101   }
0102 
0103   finalResult &= retval;
0104   return retval;
0105 }
0106 
0107 void PlotCompareUtility::makePlots(HistoData *HD) {
0108   switch (HD->getType()) {
0109     case Plot1D:
0110       makePlots<Plot1D>(HD);
0111       break;
0112     case Plot2D:
0113       makePlots<Plot2D>(HD);
0114       break;
0115   }
0116 }
0117 
0118 void PlotCompareUtility::makeHTML(HistoData *HD) {
0119   switch (HD->getType()) {
0120     case Plot1D:
0121       makeHTML<Plot1D>(HD);
0122       break;
0123     case Plot2D:
0124       makeHTML<Plot2D>(HD);
0125       break;
0126   }
0127 }
0128 
0129 HistoData *PlotCompareUtility::addHistoData(string NewName, string RefName, int Type) {
0130   // location of this HistoData within the PCU
0131   static int bin = 0;
0132   bin++;
0133 
0134   // location of histograms in files
0135   string newPath = newBasePath + "/" + newPrefix + "/" + NewName;
0136   string refPath = refBasePath + "/" + refPrefix + "/" + RefName;
0137   cout << "NewPath     = " << newPath << endl;
0138   cout << "RefPath     = " << refPath << endl;
0139   // store the HistoData information
0140   HistoData hd(NewName, Type, bin, newPath, newFile, refPath, refFile);
0141   histos.push_back(hd);
0142   // histos.insert(histos.begin(),hd);
0143   return &(*histos.rbegin());
0144 }
0145 
0146 HistoData *PlotCompareUtility::addProjectionXData(
0147     HistoData *Parent, std::string Name, int Type, int Bin, TH1 *NewHisto, TH1 *RefHisto) {
0148   // store the HistoData/projection information
0149   HistoData hd(Name, Type, Bin, NewHisto, RefHisto);
0150   projectionsX[Parent].push_back(hd);
0151   return &(*projectionsX[Parent].rbegin());
0152 }
0153 
0154 HistoData *PlotCompareUtility::addProjectionYData(
0155     HistoData *Parent, std::string Name, int Type, int Bin, TH1 *NewHisto, TH1 *RefHisto) {
0156   // store the HistoData/projection information
0157   HistoData hd(Name, Type, Bin, NewHisto, RefHisto);
0158   projectionsY[Parent].push_back(hd);
0159   return &(*projectionsY[Parent].rbegin());
0160 }
0161 
0162 bool PlotCompareUtility::isValid() const {
0163   string newPath = newBasePath + "/" + newPrefix;
0164   string refPath = refBasePath + "/" + refPrefix;
0165   // check the files and that the paths are valid
0166   bool refValid = (refFile != nullptr) && (refFile->Get(refPath.c_str()) != nullptr);
0167   bool newValid = (newFile != nullptr) && (newFile->Get(newPath.c_str()) != nullptr);
0168 
0169   return refValid && newValid;
0170 }
0171 
0172 void PlotCompareUtility::centerRebin(TH1 *H1, TH1 *H2) {
0173   // determine x axis range and binning requirements
0174   float h1RMS = H1->GetRMS();
0175   float h2RMS = H2->GetRMS();
0176   float rms = TMath::Max(h1RMS, h2RMS);
0177   float h1Mean = H1->GetMean();
0178   float h2Mean = H2->GetMean();
0179   float mean = 0.5 * (h1Mean + h2Mean);
0180   float nBins = H2->GetNbinsX();
0181   float minX = H2->GetXaxis()->GetXmin();
0182   float maxX = H2->GetXaxis()->GetXmax();
0183   float dX = maxX - minX;
0184   float dNdX = 1;
0185   float newMinX = 0;
0186   float newMaxX = 1;
0187 
0188   if (rms > 0) {
0189     dNdX = 100. / (10 * rms);
0190     newMinX = mean - 5 * rms;
0191     newMaxX = mean + 5 * rms;
0192   }
0193 
0194   // center the histograms onto a common range
0195   H1->GetXaxis()->SetRangeUser(newMinX, newMaxX);
0196   H2->GetXaxis()->SetRangeUser(newMinX, newMaxX);
0197 
0198   // rebin the histograms if appropriate
0199   if (dX * dNdX > 0) {
0200     int rebinning = (int)(float(nBins) / (dX * dNdX));
0201     H1->Rebin(rebinning);
0202     H2->Rebin(rebinning);
0203   }
0204 
0205   // determine y axis range
0206   float maxY1 = H1->GetMaximum();
0207   float maxY2 = H2->GetMaximum();
0208   float newMinY = 1e-1;
0209   float newMaxY = maxY1 > maxY2 ? maxY1 : maxY2;
0210   newMaxY *= 2;
0211 
0212   // ensure that the peaks will be drawn when combined
0213   H1->GetYaxis()->SetRangeUser(newMinY, newMaxY);
0214   H2->GetYaxis()->SetRangeUser(newMinY, newMaxY);
0215 }
0216 
0217 void PlotCompareUtility::renormalize(TH1 *H1, TH1 *H2) {
0218   // normalize H2 to H1 (typically this would be hnew to href)
0219   H2->SetNormFactor(H1->GetEntries());
0220 }
0221 
0222 double PlotCompareUtility::getThreshold() const {
0223   double threshold;
0224 
0225   // the largest non-zero threshold
0226   if (ksThreshold > 0 && chi2Threshold > 0)
0227     threshold = ksThreshold < chi2Threshold ? ksThreshold : chi2Threshold;
0228   else
0229     threshold = ksThreshold > 0 ? ksThreshold : chi2Threshold;
0230 
0231   return threshold;
0232 }
0233 
0234 void PlotCompareUtility::makeSummary(string Name) {
0235   // produce plot and html
0236   makeSummaryPlot(Name);
0237   makeSummaryHTML(Name);
0238 }
0239 
0240 void PlotCompareUtility::makeDefaultPlots() {
0241   // make a default plot for when there i nothing to display
0242   TCanvas noDataCanvas("noDataCanvas", "noDataCanvas", plotsWidth, plotsHeight);
0243   noDataCanvas.SetFrameFillColor(10);
0244   noDataCanvas.Draw();
0245   TText noData(0.5, 0.5, "No Data");
0246   noData.Draw();
0247   noDataCanvas.Print("NoData_Results.gif");
0248 }
0249 
0250 void PlotCompareUtility::makeSummaryPlot(string Name) {
0251   // generate a reasonable height for the summary plot
0252   int numHistos = histos.size();
0253   summaryHeight = summaryBottomMargin + summaryTopMargin + int(float(numHistos * summaryBarsThickness) * 1.5);
0254 
0255   // the canvas is rescaled during gif conversion, so add padding to Canvas
0256   // dimensions
0257   int summaryCanvasWidth = summaryWidth + 4;
0258   int summaryCanvasHeight = summaryHeight + 28;
0259 
0260   // create and setup summary canvas
0261   TCanvas summaryCanvas("summaryCanvas", "summaryCanvas", summaryCanvasWidth, summaryCanvasHeight);
0262   summaryCanvas.SetFrameFillColor(10);
0263   summaryCanvas.SetLogx(1);
0264   summaryCanvas.SetGrid();
0265   summaryCanvas.SetTopMargin(float(summaryTopMargin) / summaryHeight);
0266   summaryCanvas.SetLeftMargin(float(summaryLeftMargin) / summaryWidth);
0267   summaryCanvas.SetRightMargin(float(summaryRightMargin) / summaryWidth);
0268   summaryCanvas.SetBottomMargin(float(summaryBottomMargin) / summaryHeight);
0269   summaryCanvas.Draw();
0270 
0271   // create and setup the summary histogram
0272   TH1F summary("summary", "Compatibility with Reference Histograms", numHistos, 1, numHistos + 1);
0273   summary.GetXaxis()->SetLabelSize(float(summaryLeftMargin) / (11 * summaryWidth));  // used to be 3*
0274   summary.GetYaxis()->SetLabelSize(summary.GetXaxis()->GetLabelSize());
0275   summary.GetYaxis()->SetTitle("Compatibility");
0276   summary.SetStats(false);
0277   summary.GetYaxis()->SetRangeUser(getThreshold() / 10, 2);
0278   summary.Draw("hbar0");
0279 
0280   // loop over hd's and draw result
0281   vector<HistoData>::iterator hd;
0282   for (hd = histos.begin(); hd != histos.end(); hd++)
0283     hd->drawResult(&summary, false, true);
0284 
0285   // draw the pass/fail cutoff line
0286   TLine passLine(getThreshold(), 1, getThreshold(), numHistos + 1);
0287   passLine.SetLineColor(kRed);
0288   passLine.SetLineWidth(2);
0289   passLine.SetLineStyle(2);
0290   passLine.Draw("SAME");
0291 
0292   // create the summary image
0293   string gifName = Name + ".gif";
0294   summaryCanvas.Print(gifName.c_str());
0295 }
0296 
0297 void PlotCompareUtility::makeSummaryHTML(string Name) {
0298   // create HTML support code
0299   string gifName = Name + ".gif";
0300   string html = "index.html";
0301   ofstream fout(html.c_str());
0302 
0303   // print top portion of document
0304   fout << "<!DOCTYPE gif PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">" << endl
0305        << "<html>" << endl
0306        << endl
0307        << "  <head>" << endl
0308        << "    <script type=\"text/javascript\">" << endl
0309        << "      function tn(target, image) {" << endl
0310        << "        document.getElementById(\"thumblink\").href = target" << endl
0311        << "        document.getElementById(\"thumb\").src = image" << endl
0312        << "      }" << endl
0313        << "    </script>" << endl
0314        << "  </head>" << endl
0315        << endl
0316        << "  <body>" << endl
0317        << endl
0318        << "    <style type=\"text/css\">" << endl
0319        << "      #thumb_d {position: absolute; position: fixed; left: 5px; "
0320           "top: 80px; text-align: center; }"
0321        << endl
0322        << "      #main_d {position: relative; left: 175px; }" << endl
0323        << "    </style>" << endl
0324        << endl
0325        << "    <!-- added for IE compatibility (untested)" << endl
0326        << "    <script language=\"JScript\">" << endl
0327        << "      if (document.recalc && document.body.attachEvent) {" << endl
0328        << "        theDiv.style.setExpression(\"top\", "
0329           "\"document.body.scrollTop + 150\"); "
0330        << endl
0331        << "        document.body.onscroll = function() { document.recalc(true) "
0332           "}; "
0333        << endl
0334        << "      }" << endl
0335        << "    </script> -->" << endl
0336        << endl
0337        << "    <div id=\"main_d\">" << endl
0338        << "      <img src=\"" << gifName << "\" usemap=\"#" << Name << "\" alt=\"\" style=\"border-style: none;\""
0339        << " height=" << summaryHeight << " width=" << summaryWidth << " border=0>" << endl
0340        << "      <map id=\"" << Name << "\" name=\"" << Name << "\">" << endl;
0341 
0342   // loop over HistoData entries
0343   vector<HistoData>::iterator hd;
0344   for (hd = histos.begin(); hd != histos.end(); hd++) {
0345     // determine map coordinates for this bin (2 pixel offset due to borders?)
0346     int bin = hd->getBin();
0347     int x1 = summaryLeftMargin;
0348     int y1 = summaryHeight - summaryBottomMargin - int(float(bin * 1.5 - .25) * summaryBarsThickness) + 2;
0349     int x2 = summaryWidth - summaryRightMargin;
0350     int y2 = y1 + summaryBarsThickness;
0351     string image = hd->getResultImage();
0352     string target = hd->getResultTarget();
0353 
0354     // add coordinates area to image map
0355     fout << "        <area shape=\"rect\" alt=\"\" coords=\"" << x1 << "," << y1 << "," << x2 << "," << y2
0356          << "\" href=\"" << target << "\" onMouseOver=\"tn('" << target << "','" << image << "')\">" << endl;
0357   }
0358 
0359   // print bottom portion of document
0360   fout << "        <area shape=\"default\" nohref=\"nohref\" alt=\"\">" << endl
0361        << "      </map>" << endl
0362        << "    </div>" << endl
0363        << endl
0364        << "    <div id=\"thumb_d\">" << endl
0365        << "      <a href=\"#\" id=\"thumblink\"><img src=\"NoData_Results.gif\" "
0366           "id=\"thumb\" width=200 height=150 border=0></a>"
0367        << endl
0368        << "      <br><a href=\"log.txt\">Root Output</a>" << endl
0369        << "      <br><a href=\"err.txt\">Root Warnings</a>" << endl
0370        << "    </div>" << endl
0371        << endl
0372        << "  </body>" << endl
0373        << endl
0374        << "</html>" << endl;
0375 
0376   // close the file
0377   fout.close();
0378 }