CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_2_9_HLT1_bphpatch4/src/Validation/RecoTau/plugins/DQMHistPlotter.cc

Go to the documentation of this file.
00001 #include "Validation/RecoTau/plugins/DQMHistPlotter.h"
00002 
00003 #include "Validation/RecoTau/plugins/dqmAuxFunctions.h"
00004 
00005 // framework & common header files
00006 #include "FWCore/Framework/interface/Frameworkfwd.h"
00007 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00008 
00009 //DQM services
00010 #include "DQMServices/Core/interface/DQMStore.h"
00011 #include "FWCore/ServiceRegistry/interface/Service.h"
00012 #include "DQMServices/Core/interface/MonitorElement.h"
00013 
00014 #include <TCanvas.h>
00015 #include <TPad.h>
00016 #include <TPostScript.h>
00017 #include <TStyle.h>
00018 #include <TROOT.h>
00019 #include <TMath.h>
00020 
00021 #include <iostream>
00022 
00023 //defaults for cfgEntryProcess
00024 const double defaultScaleFactor = 1.;
00025 const std::string type_smMC = "smMC";
00026 const std::string type_bsmMC = "bsmMC";
00027 const std::string type_smSumMC = "smSumMC";
00028 const std::string type_Data = "Data";
00029 
00030 //defaults for cfgEntryAxisX
00031 const double defaultMinX = -1.;
00032 const double defaultMaxX = -1.;
00033 const double defaultXaxisTitleOffset = 1.0;
00034 const double defaultXaxisTitleSize = 0.05;
00035 
00036 //defaults for cfgEntryAxisY
00037 const double defaultMinY_linear = 0.;
00038 const double defaultMinY_log = 1.e-2;
00039 const double defaultMaxY_linear = -1.;
00040 const double defaultMaxY_log = -1.;
00041 const std::string yScale_linear = "linear";
00042 const std::string yScale_log = "log";
00043 const std::string defaultYscale = yScale_linear;
00044 const double defaultYaxisTitleOffset = 1.0;
00045 const double defaultYaxisTitleSize = 0.05;
00046 const double defaultYaxisMaximumScaleFactor_linear = 1.6;
00047 const double defaultYaxisMaximumScaleFactor_log = 5.e+2;
00048 
00049 double DQMHistPlotter::cfgEntryAxisY::yAxisNorm_ = 0.;
00050 
00051 // defaults for cfgEntryLegend
00052 const double defaultLegendPosX = 0.50;
00053 const double defaultLegendPosY = 0.55;
00054 const double defaultLegendSizeX =  0.39;
00055 const double defaultLegendSizeY =  0.34;
00056 const std::string defaultLegendHeader = "";
00057 const std::string defaultLegendOptions = "brNDC";
00058 const int defaultLegendBorderSize = 0;
00059 const int defaultLegendFillColor = 0;
00060 
00061 // defaults for cfgEntryLabel
00062 const double defaultLabelPosX = 0.66;
00063 const double defaultLabelPosY = 0.82;
00064 const double defaultLabelSizeX = 0.26;
00065 const double defaultLabelSizeY = 0.10;
00066 const std::string defaultLabelOptions = "brNDC";
00067 const int defaultLabelBorderSize = 0;
00068 const int defaultLabelFillColor = 0;
00069 const int defaultLabelTextColor = 1;
00070 const double defaultLabelTextSize = 0.05;
00071 const int defaultLabelTextAlign = 22; // horizontally and vertically centered, see documentation of TAttText
00072 const double defaultLabelTextAngle = 0.;
00073 
00074 // defaults for cfgEntryDrawOption
00075 const int defaultMarkerColor = 1;
00076 const int defaultMarkerSize = 1;
00077 const int defaultMarkerStyle = 2;
00078 const int defaultLineColor = 0;
00079 const int defaultLineStyle = 1;
00080 const int defaultLineWidth = 2;
00081 const int defaultFillColor = 0;
00082 const int defaultFillStyle = 1001;
00083 const std::string defaultDrawOption = "";
00084 const std::string defaultDrawOptionLegend = "lpf";
00085 
00086 const std::string drawOption_eBand = "eBand";
00087 
00088 // defaults for cfgEntryDrawJob
00089 const bool defaultDoOverlayPlots = false;
00090 
00091 // global defaults
00092 const int defaultCanvasSizeX = 800;
00093 const int defaultCanvasSizeY = 600;
00094 
00095 const std::string drawOptionSeparator = "#.#";
00096 
00097 const int verbosity = 0;
00098 
00099 template <class T>
00100 void checkCfgDef(const std::string& cfgEntryName, std::map<std::string, T>& def, int& errorFlag,
00101                  const std::string& defType, const std::string& drawJobName)
00102 {
00103   if ( def.find(cfgEntryName) == def.end() ) {
00104     edm::LogError ("checkCfgDef") << " " << defType << " = " << cfgEntryName << " undefined, needed by drawJob = " << drawJobName << " !!";
00105     errorFlag = 1;
00106   }
00107 }
00108 
00109 template <class T>
00110 void checkCfgDefs(const std::vector<std::string>& cfgEntryNames, std::map<std::string, T>& def, int& errorFlag,
00111                   const std::string& defType, const std::string& drawJobName)
00112 {
00113   for ( std::vector<std::string>::const_iterator cfgEntryName = cfgEntryNames.begin();
00114         cfgEntryName != cfgEntryNames.end(); ++cfgEntryName ) {
00115     checkCfgDef(*cfgEntryName, def, errorFlag, defType, drawJobName);
00116   }
00117 }
00118 
00119 template <class T>
00120 const T* findCfgDef(const std::string& cfgEntryName, std::map<std::string, T>& def,
00121                     const std::string& defType, const std::string& drawJobName)
00122 {
00123   typename std::map<std::string, T>::const_iterator it = def.find(cfgEntryName);
00124   if ( it != def.end() ) {
00125     return &(it->second);
00126   } else {
00127     edm::LogError ("findCfgDef") << " " << defType << " = " << cfgEntryName << " undefined, needed by drawJob = " << drawJobName << " !!";
00128     return NULL;
00129   } 
00130 }
00131 
00132 //
00133 //-----------------------------------------------------------------------------------------------------------------------
00134 //
00135 
00136 typedef std::pair<TH1*, std::string> histoDrawEntry;
00137 
00138 void drawHistograms(const std::list<histoDrawEntry>& histogramList, bool& isFirstHistogram)
00139 {
00140   for ( std::list<histoDrawEntry>::const_iterator it = histogramList.begin();
00141         it != histogramList.end(); ++it ) {
00142     std::string drawOption = ( isFirstHistogram ) ? it->second : std::string(it->second).append("same");
00143     it->first->Draw(drawOption.data());
00144     isFirstHistogram = false;
00145   }
00146 }
00147 
00148 //
00149 //-----------------------------------------------------------------------------------------------------------------------
00150 //
00151 
00152 bool find_vstring(const std::vector<std::string>& vs, const std::string& s)
00153 {
00154   for ( std::vector<std::string>::const_iterator it = vs.begin();
00155         it != vs.end(); ++it ) {
00156     if ( (*it) == s ) return true;
00157   }
00158   return false;
00159 }
00160 
00161 //
00162 //-----------------------------------------------------------------------------------------------------------------------
00163 //
00164 
00165 DQMHistPlotter::cfgEntryProcess::cfgEntryProcess(const std::string& name, const edm::ParameterSet& cfg)
00166 {
00167   name_ = name;
00168 
00169   dqmDirectory_ = cfg.getParameter<std::string>("dqmDirectory");
00170   
00171   legendEntry_ = cfg.getParameter<std::string>("legendEntry");
00172   legendEntryErrorBand_ = ( cfg.exists("legendEntryErrorBand") ) ? 
00173     cfg.getParameter<std::string>("legendEntryErrorBand") : std::string(legendEntry_).append(" Uncertainty");
00174 
00175   type_ = cfg.getParameter<std::string>("type");
00176   
00177   if ( verbosity ) print();
00178 }
00179 
00180 void DQMHistPlotter::cfgEntryProcess::print() const
00181 {
00182   std::cout << "<DQMHistPlotter::cfgEntryProcess::print>:" << std::endl;
00183   std::cout << " name = " << name_ << std::endl;
00184   std::cout << " dqmDirectory = " << dqmDirectory_ << std::endl;
00185   std::cout << " legendEntry = " << legendEntry_ << std::endl;
00186   std::cout << " legendEntryErrorBand = " << legendEntryErrorBand_ << std::endl;
00187   std::cout << " type = " << type_ << std::endl;
00188 }
00189 
00190 //
00191 //-----------------------------------------------------------------------------------------------------------------------
00192 //
00193 
00194 DQMHistPlotter::cfgEntryAxisX::cfgEntryAxisX(const std::string& name, const edm::ParameterSet& cfg)
00195 {
00196   name_ = name;
00197 
00198   minX_ = ( cfg.exists("minX") ) ? cfg.getParameter<double>("minX") : defaultMinX;
00199   maxX_ = ( cfg.exists("maxX") ) ? cfg.getParameter<double>("maxX") : defaultMaxX;
00200   xAxisTitle_ = cfg.getParameter<std::string>("xAxisTitle");
00201   xAxisTitleOffset_ = ( cfg.exists("xAxisTitleOffset") ) ? cfg.getParameter<double>("xAxisTitleOffset") : defaultXaxisTitleOffset;
00202   xAxisTitleSize_ = ( cfg.exists("xAxisTitleSize") ) ? cfg.getParameter<double>("xAxisTitleSize") : defaultXaxisTitleSize;
00203 
00204   if ( verbosity ) print();
00205 }
00206 
00207 void DQMHistPlotter::cfgEntryAxisX::print() const
00208 {
00209   std::cout << "<DQMHistPlotter::cfgEntryAxisX::print>:" << std::endl;
00210   std::cout << " name = " << name_ << std::endl;
00211   std::cout << " minX_ = " << minX_ << std::endl;
00212   std::cout << " maxX_ = " << maxX_ << std::endl;
00213   std::cout << " xAxisTitle = " << xAxisTitle_ << std::endl;
00214   std::cout << " xAxisTitleOffset = " << xAxisTitleOffset_ << std::endl;
00215   std::cout << " xAxisTitleSize = " << xAxisTitleSize_ << std::endl;
00216 }
00217 
00218 void DQMHistPlotter::cfgEntryAxisX::applyTo(TH1* histogram) const
00219 {
00220   if ( histogram ) {
00221     double xMin = ( minX_ != defaultMinX ) ? minX_ : histogram->GetXaxis()->GetXmin();
00222     double xMax = ( maxX_ != defaultMaxX ) ? maxX_ : histogram->GetXaxis()->GetXmax();
00223     histogram->SetAxisRange(xMin, xMax, "X");
00224     histogram->GetXaxis()->SetTitle(xAxisTitle_.data());
00225     histogram->GetXaxis()->SetTitleOffset(xAxisTitleOffset_);
00226     histogram->GetXaxis()->SetTitleSize(xAxisTitleSize_);
00227   }
00228 }
00229 
00230 //
00231 //-----------------------------------------------------------------------------------------------------------------------
00232 //
00233 
00234 DQMHistPlotter::cfgEntryAxisY::cfgEntryAxisY(const std::string& name, const edm::ParameterSet& cfg)
00235 {
00236   name_ = name;
00237 
00238   minY_linear_ = ( cfg.exists("minY_linear") ) ? cfg.getParameter<double>("minY_linear") : defaultMinY_linear;
00239   minY_log_ = ( cfg.exists("minY_log") ) ? cfg.getParameter<double>("minY_log") : defaultMinY_log;
00240   maxY_linear_ = ( cfg.exists("maxY_linear") ) ? cfg.getParameter<double>("maxY_linear") : defaultMaxY_linear;
00241   maxY_log_ = ( cfg.exists("maxY_log") ) ? cfg.getParameter<double>("maxY_log") : defaultMaxY_log;
00242   yScale_ = ( cfg.exists("yScale") ) ? cfg.getParameter<std::string>("yScale") : defaultYscale;
00243   yAxisTitle_ = cfg.getParameter<std::string>("yAxisTitle");
00244   yAxisTitleOffset_ = ( cfg.exists("yAxisTitleOffset") ) ? cfg.getParameter<double>("yAxisTitleOffset") : defaultYaxisTitleOffset;
00245   yAxisTitleSize_ = ( cfg.exists("yAxisTitleSize") ) ? cfg.getParameter<double>("yAxisTitleSize") : defaultYaxisTitleSize;
00246 
00247   if ( verbosity ) print();
00248 }
00249 
00250 void DQMHistPlotter::cfgEntryAxisY::print() const
00251 {
00252   std::cout << "<DQMHistPlotter::cfgEntryAxisY::print>:" << std::endl;
00253   std::cout << " name = " << name_ << std::endl;
00254   std::cout << " minY_linear = " << minY_linear_ << std::endl;
00255   std::cout << " minY_log = " << minY_log_ << std::endl;
00256   std::cout << " maxY_linear = " << maxY_linear_ << std::endl;
00257   std::cout << " maxY_log = " << maxY_log_ << std::endl;
00258   std::cout << " yScale = " << yScale_ << std::endl;
00259   std::cout << " yAxisTitle = " << yAxisTitle_ << std::endl;
00260   std::cout << " yAxisTitleOffset = " << yAxisTitleOffset_ << std::endl;
00261   std::cout << " yAxisTitleSize = " << yAxisTitleSize_ << std::endl;
00262 }
00263 
00264 void DQMHistPlotter::cfgEntryAxisY::applyTo(TH1* histogram) const
00265 {
00266   if ( histogram ) {
00267     bool yLogScale = ( yScale_ == yScale_log ) ? true : false;
00268     double minY = ( yLogScale ) ? minY_log_ : minY_linear_;
00269     histogram->SetMinimum(minY);
00270     double maxY = ( yLogScale ) ? maxY_log_ : maxY_linear_;
00271     double defaultMaxY = ( yLogScale ) ? defaultMaxY_log : defaultMaxY_linear;
00272     if ( maxY != defaultMaxY ) {
00273 //--- normalize y-axis range using given configuration parameter
00274       histogram->SetMaximum(maxY);
00275     } else {
00276 //--- in case configuration parameter for y-axis range not explicitely given,
00277 //    normalize y-axis range to maximum of any histogram included in drawJob
00278 //    times defaultYaxisMaximumScaleFactor (apply scale factor in order to make space for legend)
00279       double defaultYaxisMaximumScaleFactor = ( yLogScale ) ? defaultYaxisMaximumScaleFactor_log : defaultYaxisMaximumScaleFactor_linear;
00280       histogram->SetMaximum(defaultYaxisMaximumScaleFactor*yAxisNorm_);
00281     }
00282     histogram->GetYaxis()->SetTitle(yAxisTitle_.data());
00283     histogram->GetYaxis()->SetTitleOffset(yAxisTitleOffset_);
00284     histogram->GetYaxis()->SetTitleSize(yAxisTitleSize_);
00285   }
00286 }
00287 
00288 //
00289 //-----------------------------------------------------------------------------------------------------------------------
00290 //
00291 
00292 DQMHistPlotter::cfgEntryLegend::cfgEntryLegend(const std::string& name, const edm::ParameterSet& cfg)
00293 {
00294   name_ = name;
00295 
00296   posX_ = ( cfg.exists("posX") ) ? cfg.getParameter<double>("posX") : defaultLegendPosX;
00297   posY_ = ( cfg.exists("posY") ) ? cfg.getParameter<double>("posY") : defaultLegendPosY;
00298   sizeX_ = ( cfg.exists("sizeX") ) ? cfg.getParameter<double>("sizeX") : defaultLegendSizeX;
00299   sizeY_ = ( cfg.exists("sizeY") ) ? cfg.getParameter<double>("sizeY") : defaultLegendSizeY;
00300   header_ = ( cfg.exists("header") ) ? cfg.getParameter<std::string>("header") : defaultLegendHeader;
00301   option_ = ( cfg.exists("option") ) ? cfg.getParameter<std::string>("option") : defaultLegendOptions;
00302   borderSize_ = ( cfg.exists("borderSize") ) ? cfg.getParameter<int>("borderSize") : defaultLegendBorderSize;
00303   fillColor_ = ( cfg.exists("fillColor") ) ? cfg.getParameter<int>("fillColor") : defaultLegendFillColor;
00304  
00305   if ( verbosity ) print();
00306 }
00307 
00308 void DQMHistPlotter::cfgEntryLegend::print() const
00309 {
00310   std::cout << "<DQMHistPlotter::cfgEntryLegend::print>:" << std::endl;
00311   std::cout << " name = " << name_ << std::endl;
00312   std::cout << " posX = " << posX_ << std::endl;
00313   std::cout << " posY = " << posY_ << std::endl;
00314   std::cout << " sizeX = " << sizeX_ << std::endl;
00315   std::cout << " sizeY = " << sizeY_ << std::endl;
00316   std::cout << " header = " << header_ << std::endl;
00317   std::cout << " option = " << option_ << std::endl;
00318   std::cout << " borderSize = " << borderSize_ << std::endl;
00319   std::cout << " fillColor = " << fillColor_ << std::endl;
00320 }
00321 
00322 void DQMHistPlotter::cfgEntryLegend::applyTo(TLegend* legend) const
00323 {
00324   if ( legend ) {
00325     legend->SetX1(posX_);
00326     legend->SetY1(posY_);
00327     legend->SetX2(posX_ + sizeX_);
00328     legend->SetY2(posY_ + sizeY_);
00329     legend->SetHeader(header_.data());
00330     legend->SetOption(option_.data());
00331     legend->SetBorderSize(borderSize_);
00332     legend->SetFillColor(fillColor_);
00333   }
00334 }
00335 
00336 //
00337 //-----------------------------------------------------------------------------------------------------------------------
00338 //
00339 
00340 DQMHistPlotter::cfgEntryLabel::cfgEntryLabel(const std::string& name, const edm::ParameterSet& cfg)
00341 {
00342   name_ = name;
00343 
00344   posX_ = ( cfg.exists("posX") ) ? cfg.getParameter<double>("posX") : defaultLabelPosX;
00345   posY_ = ( cfg.exists("posY") ) ? cfg.getParameter<double>("posY") : defaultLabelPosY;
00346   sizeX_ = ( cfg.exists("sizeX") ) ? cfg.getParameter<double>("sizeX") : defaultLabelSizeX;
00347   sizeY_ = ( cfg.exists("sizeY") ) ? cfg.getParameter<double>("sizeY") : defaultLabelSizeY;
00348   option_ = ( cfg.exists("option") ) ? cfg.getParameter<std::string>("option") : defaultLabelOptions;
00349   borderSize_ = ( cfg.exists("borderSize") ) ? cfg.getParameter<int>("borderSize") : defaultLabelBorderSize;
00350   fillColor_ = ( cfg.exists("fillColor") ) ? cfg.getParameter<int>("fillColor") : defaultLabelFillColor;
00351   textColor_ = ( cfg.exists("textColor") ) ? cfg.getParameter<int>("textColor") : defaultLabelTextColor;
00352   textSize_ = ( cfg.exists("textSize") ) ? cfg.getParameter<double>("textSize") : defaultLabelTextSize;
00353   textAlign_ = ( cfg.exists("textAlign") ) ? cfg.getParameter<int>("textAlign") : defaultLabelTextAlign;
00354   textAngle_ = ( cfg.exists("textAngle") ) ? cfg.getParameter<double>("textAngle") : defaultLabelTextAngle;
00355   text_ = cfg.getParameter<vstring>("text");
00356  
00357   if ( verbosity ) print();
00358 }
00359 
00360 void DQMHistPlotter::cfgEntryLabel::print() const
00361 {
00362   std::cout << "<DQMHistPlotter::cfgEntryLabel::print>:" << std::endl;
00363   std::cout << " name = " << name_ << std::endl;
00364   std::cout << " posX = " << posX_ << std::endl;
00365   std::cout << " posY = " << posY_ << std::endl;
00366   std::cout << " sizeX = " << sizeX_ << std::endl;
00367   std::cout << " sizeY = " << sizeY_ << std::endl;
00368   std::cout << " option = " << option_ << std::endl;
00369   std::cout << " borderSize = " << borderSize_ << std::endl;
00370   std::cout << " fillColor = " << fillColor_ << std::endl;
00371   std::cout << " textColor = " << textColor_ << std::endl;
00372   std::cout << " textSize = " << textSize_ << std::endl;
00373   std::cout << " textAlign = " << textAlign_ << std::endl;
00374   std::cout << " textAngle = " << textAngle_ << std::endl;
00375   std::cout << " text = " << format_vstring(text_) << std::endl;
00376 }
00377 
00378 void DQMHistPlotter::cfgEntryLabel::applyTo(TPaveText* label) const
00379 {
00380   if ( label ) {
00381 //--- WARNING: need to call TPaveText::SetX1NDC, **not** TPaveText::SetX1 !!
00382 //             (see documentation of base-class constructor
00383 //               TPave::TPave(Double_t, Double_t,Double_t, Double_t, Int_t, Option_t*)
00384 //              in TPave.cxx for details)
00385     label->SetX1NDC(posX_);
00386     label->SetY1NDC(posY_);
00387     label->SetX2NDC(posX_ + sizeX_);
00388     label->SetY2NDC(posY_ + sizeY_);
00389     label->SetOption(option_.data());
00390     label->SetBorderSize(borderSize_);
00391     label->SetFillColor(fillColor_);
00392     label->SetTextColor(textColor_);
00393     label->SetTextSize(textSize_);
00394     label->SetTextAlign(textAlign_);
00395     label->SetTextAngle(textAngle_);
00396     for ( vstring::const_iterator line = text_.begin();
00397           line != text_.end(); ++line ) {
00398       label->AddText(line->data());
00399     }
00400   }
00401 }
00402 
00403 //
00404 //-----------------------------------------------------------------------------------------------------------------------
00405 //
00406 
00407 DQMHistPlotter::cfgEntryDrawOption::cfgEntryDrawOption(const std::string& name, const edm::ParameterSet& cfg)
00408 {
00409   name_ = name;
00410 
00411   markerColor_ = ( cfg.exists("markerColor") ) ? cfg.getParameter<int>("markerColor") : defaultMarkerColor;
00412   markerSize_  = ( cfg.exists("markerSize")  ) ? cfg.getParameter<double>("markerSize")  : defaultMarkerSize;
00413   markerStyle_ = ( cfg.exists("markerStyle") ) ? cfg.getParameter<int>("markerStyle") : defaultMarkerStyle;
00414   
00415   lineColor_ = ( cfg.exists("lineColor") ) ? cfg.getParameter<int>("lineColor") : defaultLineColor;
00416   lineStyle_ = ( cfg.exists("lineStyle") ) ? cfg.getParameter<int>("lineStyle") : defaultLineStyle;
00417   lineWidth_ = ( cfg.exists("lineWidth") ) ? cfg.getParameter<int>("lineWidth") : defaultLineWidth;
00418   
00419   fillColor_ = ( cfg.exists("fillColor") ) ? cfg.getParameter<int>("fillColor") : defaultFillColor;
00420   fillStyle_ = ( cfg.exists("fillStyle") ) ? cfg.getParameter<int>("fillStyle") : defaultFillStyle;
00421   
00422   drawOption_ = ( cfg.exists("drawOption") ) ? cfg.getParameter<std::string>("drawOption") : defaultDrawOption;
00423   drawOptionLegend_ = ( cfg.exists("drawOptionLegend") ) ? cfg.getParameter<std::string>("drawOptionLegend") : defaultDrawOptionLegend;
00424   
00425   if ( verbosity ) print();
00426 }
00427 
00428 DQMHistPlotter::cfgEntryDrawOption::cfgEntryDrawOption(const std::string& name, const cfgEntryDrawOption& blueprint)
00429   : name_(name),
00430     markerColor_(blueprint.markerColor_), markerSize_(blueprint.markerSize_), markerStyle_(blueprint.markerStyle_),
00431     lineColor_(blueprint.lineColor_), lineStyle_(blueprint.lineStyle_), lineWidth_(blueprint.lineWidth_),
00432     fillColor_(blueprint.fillColor_), fillStyle_(blueprint.fillStyle_),
00433     drawOption_(blueprint.drawOption_), drawOptionLegend_(blueprint.drawOptionLegend_)
00434 {
00435   if ( verbosity ) print();
00436 }
00437 
00438 void DQMHistPlotter::cfgEntryDrawOption::print() const
00439 {
00440   std::cout << "<DQMHistPlotter::cfgEntryDrawOption::print>:" << std::endl;
00441   std::cout << " name = " << name_ << std::endl;
00442   std::cout << " markerColor = " << markerColor_ << std::endl;
00443   std::cout << " markerSize = " << markerSize_ << std::endl;
00444   std::cout << " markerStyle = " << markerStyle_ << std::endl;
00445   std::cout << " lineColor = " << lineColor_ << std::endl;
00446   std::cout << " lineStyle = " << lineStyle_ << std::endl;
00447   std::cout << " lineWidth = " << lineWidth_ << std::endl;
00448   std::cout << " fillColor = " << fillColor_ << std::endl;
00449   std::cout << " fillStyle = " << fillStyle_ << std::endl;
00450   std::cout << " drawOption = " << drawOption_ << std::endl;
00451   std::cout << " drawOptionLegend = " << drawOptionLegend_ << std::endl;
00452 }
00453 
00454 void DQMHistPlotter::cfgEntryDrawOption::applyTo(TH1* histogram) const 
00455 {
00456   if ( histogram ) {
00457     histogram->SetMarkerColor(markerColor_);
00458     histogram->SetMarkerSize(markerSize_);
00459     histogram->SetMarkerStyle(markerStyle_);  
00460     histogram->SetLineColor(lineColor_);
00461     histogram->SetLineStyle(lineStyle_);
00462     histogram->SetLineWidth(lineWidth_);   
00463     histogram->SetFillColor(fillColor_);
00464     histogram->SetFillStyle(fillStyle_);
00465   }
00466 }
00467 
00468 //
00469 //-----------------------------------------------------------------------------------------------------------------------
00470 //
00471 
00472 DQMHistPlotter::plotDefEntry::plotDefEntry(const std::string& dqmMonitorElement, 
00473                                            const std::string& drawOptionEntry,
00474                                            const std::string& legendEntry,
00475                                            const std::string& legendEntryErrorBand,
00476                                            const std::string& process,
00477                                            bool doStack)
00478   : dqmMonitorElement_(dqmMonitorElement), 
00479     drawOptionEntry_(drawOptionEntry),
00480     legendEntry_(legendEntry),
00481     legendEntryErrorBand_(legendEntryErrorBand),
00482     process_(process), 
00483     doStack_(doStack),
00484     isErrorBand_(false)
00485 {
00486   //if ( verbosity ) print();
00487 }
00488 
00489 DQMHistPlotter::plotDefEntry::plotDefEntry(const plotDefEntry& blueprint)
00490   : dqmMonitorElement_(blueprint.dqmMonitorElement_), 
00491     drawOptionEntry_(blueprint.drawOptionEntry_),
00492     legendEntry_(blueprint.legendEntry_),
00493     legendEntryErrorBand_(blueprint.legendEntryErrorBand_),
00494     process_(blueprint.process_), 
00495     doStack_(blueprint.doStack_),
00496     isErrorBand_(false)
00497 {
00498   //if ( verbosity ) print();
00499 }
00500 
00501 void DQMHistPlotter::plotDefEntry::print() const
00502 {
00503   std::cout << "<DQMHistPlotter::plotDefEntry::print>:" << std::endl;
00504   std::cout << " dqmMonitorElement = " << dqmMonitorElement_ << std::endl;
00505   std::cout << " drawOptionEntry = " << drawOptionEntry_ << std::endl;
00506   std::cout << " legendEntry = " << legendEntry_ << std::endl;
00507   std::cout << " legendEntryErrorBand = " << legendEntryErrorBand_ << std::endl;
00508   std::cout << " process = " << process_ << std::endl;
00509   std::cout << " doStack = " << doStack_ << std::endl;
00510 }
00511 
00512 //
00513 //-----------------------------------------------------------------------------------------------------------------------
00514 //
00515 
00516 DQMHistPlotter::cfgEntryDrawJob::cfgEntryDrawJob(const std::string& name, 
00517                                                  const plotDefList& plotDefList, 
00518                                                  const std::string& title,
00519                                                  const std::string& xAxis, const std::string& yAxis, 
00520                                                  const std::string& legend, 
00521                                                  const vstring& labels)
00522 {
00523   name_ = name;
00524 
00525   for ( plotDefList::const_iterator it = plotDefList.begin();
00526         it != plotDefList.end(); ++it ) {
00527     plots_.push_back(plotDefEntry(*it));
00528   }
00529   
00530   title_ = title;
00531 
00532   xAxis_ = xAxis;
00533   yAxis_ = yAxis;
00534   
00535   legend_ = legend;
00536 
00537   for ( vstring::const_iterator it = labels.begin();
00538         it != labels.end(); ++it ) {
00539     labels_.push_back(std::string(*it));
00540   }
00541 
00542   if ( verbosity ) print();
00543 }
00544 
00545 void DQMHistPlotter::cfgEntryDrawJob::print() const
00546 {
00547   std::cout << "<DQMHistPlotter::cfgSetDrawJob::print>:" << std::endl;
00548   std::cout << " name = " << name_ << std::endl;
00549   std::cout << "plots = {" << std::endl;
00550   for ( plotDefList::const_iterator plot = plots_.begin();
00551         plot != plots_.end(); ++plot ) {
00552     plot->print();
00553   }
00554   std::cout << "}" << std::endl;
00555   std::cout << " title = " << title_ << std::endl;
00556   std::cout << " xAxis = " << xAxis_ << std::endl;
00557   std::cout << " yAxis = " << yAxis_ << std::endl;
00558   std::cout << " legend = " << legend_ << std::endl;
00559   std::cout << " labels = " << format_vstring(labels_) << std::endl;
00560 }
00561 
00562 //
00563 //-----------------------------------------------------------------------------------------------------------------------
00564 //
00565 
00566 DQMHistPlotter::DQMHistPlotter(const edm::ParameterSet& cfg)
00567 {
00568   std::cout << "<DQMHistPlotter::DQMHistPlotter>:" << std::endl;
00569 
00570   cfgError_ = 0;
00571 
00572 //--- configure processes  
00573   //std::cout << "--> configuring processes..." << std::endl;
00574   edm::ParameterSet cfgParSet_processes = cfg.getParameter<edm::ParameterSet>("processes");
00575   readCfgParameter<cfgEntryProcess>(cfgParSet_processes, processes_);
00576   
00577 //--- check that process types are defined
00578   //std::cout << "--> checking configuration parameters..." << std::endl;
00579 
00580   int numProcesses_Data = 0;
00581   int numProcesses_sumMC = 0;
00582   for ( std::map<std::string, cfgEntryProcess>::const_iterator process = processes_.begin();
00583         process != processes_.end(); ++process ) {
00584     const std::string& type = process->second.type_;
00585 
00586     if ( !((type == type_smMC) ||
00587            (type == type_bsmMC) ||
00588            (type == type_smSumMC) ||
00589            (type == type_Data)) ) {
00590       edm::LogError ("DQMHistPlotter") << " Undefined process type = " << type << " !!";
00591       cfgError_ = 1;
00592     }
00593 
00594     if ( type == type_smSumMC ) ++numProcesses_sumMC;
00595     if ( type == type_Data ) ++numProcesses_Data;
00596   }
00597 
00598   if ( (numProcesses_Data > 1) || (numProcesses_sumMC > 1) ) {
00599     edm::LogError ("DQMHistPlotter") << " Cannot have more than one process of types sumMC and Data !!";
00600     cfgError_ = 1;
00601   }
00602 
00603 //--- configure x-axes  
00604   //std::cout << "--> configuring x-axes..." << std::endl;
00605   edm::ParameterSet cfgParSet_xAxes = cfg.getParameter<edm::ParameterSet>("xAxes");
00606   readCfgParameter<cfgEntryAxisX>(cfgParSet_xAxes, xAxes_);
00607 
00608 //--- configure y-axes  
00609   //std::cout << "--> configuring y-axes..." << std::endl;
00610   edm::ParameterSet cfgParSet_yAxes = cfg.getParameter<edm::ParameterSet>("yAxes");
00611   readCfgParameter<cfgEntryAxisY>(cfgParSet_yAxes, yAxes_);
00612 
00613 //--- configure legends
00614   //std::cout << "--> configuring legends..." << std::endl;
00615   edm::ParameterSet cfgParSet_legends = cfg.getParameter<edm::ParameterSet>("legends");
00616   readCfgParameter<cfgEntryLegend>(cfgParSet_legends, legends_);
00617 
00618 //--- configure labels
00619   //std::cout << "--> configuring labels..." << std::endl;
00620   edm::ParameterSet cfgParSet_labels = cfg.getParameter<edm::ParameterSet>("labels");
00621   readCfgParameter<cfgEntryLabel>(cfgParSet_labels, labels_);
00622 
00623 //--- configure drawOptions
00624   //std::cout << "--> configuring drawOptions..." << std::endl;
00625   if ( cfg.exists("drawOptionSets") ) {
00626     edm::ParameterSet drawOptionSets = cfg.getParameter<edm::ParameterSet>("drawOptionSets");
00627     vstring drawOptionSetNames = drawOptionSets.getParameterNamesForType<edm::ParameterSet>();
00628     for ( vstring::const_iterator drawOptionSetName = drawOptionSetNames.begin(); 
00629           drawOptionSetName != drawOptionSetNames.end(); ++drawOptionSetName ) {
00630       edm::ParameterSet drawOptionSet = drawOptionSets.getParameter<edm::ParameterSet>(*drawOptionSetName);
00631 
00632       vstring drawOptionEntryNames = drawOptionSet.getParameterNamesForType<edm::ParameterSet>();
00633       for ( vstring::const_iterator drawOptionEntryName = drawOptionEntryNames.begin(); 
00634             drawOptionEntryName != drawOptionEntryNames.end(); ++drawOptionEntryName ) {
00635         edm::ParameterSet drawOptionEntry = drawOptionSet.getParameter<edm::ParameterSet>(*drawOptionEntryName);
00636 
00637         std::string drawOptionEntryName_full = std::string(*drawOptionSetName).append(drawOptionSeparator).append(*drawOptionEntryName);
00638         drawOptionEntries_.insert(std::pair<std::string, cfgEntryDrawOption>
00639                                   (drawOptionEntryName_full, cfgEntryDrawOption(drawOptionEntryName_full, drawOptionEntry)));
00640       }
00641     }
00642   }
00643 
00644   if ( cfg.exists("drawOptionEntries") ) {
00645     edm::ParameterSet cfgParSet_drawOptionEntries = cfg.getParameter<edm::ParameterSet>("drawOptionEntries");
00646     readCfgParameter<cfgEntryDrawOption>(cfgParSet_drawOptionEntries, drawOptionEntries_);
00647   }
00648 
00649 //--- configure drawJobs
00650   //std::cout << "--> configuring drawJobs..." << std::endl;
00651   edm::ParameterSet drawJobs = cfg.getParameter<edm::ParameterSet>("drawJobs");
00652   vstring drawJobNames = drawJobs.getParameterNamesForType<edm::ParameterSet>();
00653   for ( vstring::const_iterator drawJobName = drawJobNames.begin(); 
00654         drawJobName != drawJobNames.end(); ++drawJobName ) {
00655     edm::ParameterSet drawJob = drawJobs.getParameter<edm::ParameterSet>(*drawJobName);
00656 
00657     std::map<int, plotDefList> plotDefMap;
00658 
00659     if ( drawJob.existsAs<edm::ParameterSet>("plots") ) { // display same monitor element for different processes
00660       edm::ParameterSet plots = drawJob.getParameter<edm::ParameterSet>("plots");
00661 
00662       vstring dqmMonitorElements = plots.getParameter<vstring>("dqmMonitorElements");
00663       vstring processes = plots.getParameter<vstring>("processes");
00664 
00665       std::string drawOptionSet = drawJob.getParameter<std::string>("drawOptionSet");
00666       //std::cout << "drawOptionSet = " << drawOptionSet << std::endl;
00667 
00668       vstring stack = ( cfg.exists("stack") ) ? drawJob.getParameter<vstring>("stack") : vstring();
00669 
00670       for ( vstring::const_iterator process = processes.begin();
00671             process != processes.end(); ++process ) {
00672         int index = 0;
00673         for ( vstring::const_iterator dqmMonitorElement = dqmMonitorElements.begin();
00674               dqmMonitorElement != dqmMonitorElements.end(); ++dqmMonitorElement ) {
00675           bool stack_dqmMonitorElement = find_vstring(stack, *process);
00676           std::string drawOptionEntry = std::string(drawOptionSet).append(drawOptionSeparator).append(*process);
00677           plotDefMap[index].push_back(plotDefEntry(*dqmMonitorElement, drawOptionEntry, "", "", *process, stack_dqmMonitorElement));
00678           ++index;
00679         }
00680       }
00681     } else { // display different monitor elements for same process
00682       typedef std::vector<edm::ParameterSet> vParameterSet;
00683       vParameterSet plots = drawJob.getParameter<vParameterSet>("plots");
00684 
00685       std::string process = ( drawJob.exists("process") ) ? drawJob.getParameter<std::string>("process") : "";
00686       //std::cout << "process (globally set) = " << process << std::endl;
00687 
00688       for ( vParameterSet::const_iterator plot = plots.begin(); 
00689             plot != plots.end(); ++plot ) {
00690 
00691         if ( process == "" || plot->exists("process")) {
00692           process = plot->getParameter<std::string>("process");
00693           //std::cout << "process (locally set) = " << process << std::endl;
00694         }
00695 
00696         std::string drawOptionEntry = plot->getParameter<std::string>("drawOptionEntry");
00697         //std::cout << "drawOptionEntry = " << drawOptionEntry << std::endl;
00698 
00699         std::string legendEntry = "", legendEntryErrorBand = "";
00700         if ( plot->exists("legendEntry") ) {
00701           legendEntry = plot->getParameter<std::string>("legendEntry");
00702           legendEntryErrorBand = ( plot->exists("legendEntryErrorBand") ) ? 
00703             plot->getParameter<std::string>("legendEntryErrorBand") : std::string(legendEntry).append(" Uncertainty"); 
00704         }
00705         //std::cout << "legendEntry = " << legendEntry << std::endl;
00706         //std::cout << "legendEntryErrorBand = " << legendEntryErrorBand << std::endl;
00707 
00708         vstring dqmMonitorElements = plot->getParameter<vstring>("dqmMonitorElements");
00709         int index = 0;
00710         for ( vstring::const_iterator dqmMonitorElement = dqmMonitorElements.begin();
00711               dqmMonitorElement != dqmMonitorElements.end(); ++dqmMonitorElement ) {
00712           plotDefMap[index].push_back(plotDefEntry(*dqmMonitorElement, drawOptionEntry, legendEntry, legendEntryErrorBand, process, false));
00713           ++index;
00714         }
00715       }
00716     }
00717 
00718 //--- check that number of displayed monitor elements is the same for each plot
00719     unsigned numMonitorElements_ref = 0;
00720     bool isFirstEntry = true;
00721     for ( std::map<int, plotDefList>::const_iterator plot = plotDefMap.begin(); 
00722           plot != plotDefMap.end(); ++plot ) {
00723       if ( isFirstEntry ) {
00724         numMonitorElements_ref = plot->second.size();
00725         isFirstEntry = false;
00726       } else {
00727         if ( plot->second.size() != numMonitorElements_ref ) {
00728           edm::LogError ("DQMHistPlotter::DQMHistPlotter") << " Numbers of dqmMonitorElements must be the same for all plots" 
00729                                                            << " --> skipping drawJob = " << (*drawJobName) << " !!";
00730           cfgError_ = 1;
00731         }
00732       }
00733     }
00734 
00735 //--- expand process directories in names of dqmMonitorElements
00736     for ( std::map<int, plotDefList>::iterator plot = plotDefMap.begin(); 
00737           plot != plotDefMap.end(); ++plot ) {
00738       for ( plotDefList::iterator entry = plot->second.begin();
00739             entry != plot->second.end(); ++entry ) {
00740         std::string dqmMonitorElement = entry->dqmMonitorElement_;
00741         std::string process = entry->process_;
00742 
00743         std::map<std::string, cfgEntryProcess>::const_iterator it = processes_.find(process);
00744         if ( it != processes_.end() ) {
00745           std::string process_dqmDirectory = it->second.dqmDirectory_;
00746 
00747           //std::cout << "replacing processDir = " << process_dqmDirectory << " in drawJob = " << (*drawJobName) << std::endl;
00748 
00749           int errorFlag = 0;
00750           std::string dqmMonitorElement_expanded = replace_string(dqmMonitorElement, processDirKeyword, process_dqmDirectory, 0, 1, errorFlag);
00751           //std::cout << " dqmMonitorElement_expanded = " << dqmMonitorElement_expanded << std::endl;
00752 
00753           if ( !errorFlag ) {
00754             entry->dqmMonitorElement_ = dqmMonitorElement_expanded;
00755           } else {
00756             cfgError_ = 1;
00757           }
00758         } else {
00759           edm::LogError ("DQMHistPlotter::DQMHistPlotter") << " Undefined process = " << process << " !!";
00760           cfgError_ = 1;
00761         }
00762       }
00763     }
00764 
00765     std::string title = ( drawJob.exists("title") ) ? drawJob.getParameter<std::string>("title") : ""; 
00766 
00767     std::string xAxis = drawJob.getParameter<std::string>("xAxis"); 
00768     std::string yAxis = drawJob.getParameter<std::string>("yAxis");
00769     
00770     std::string legend = drawJob.getParameter<std::string>("legend");
00771     
00772     vstring labels = ( drawJob.exists("labels") ) ? drawJob.getParameter<vstring>("labels") : vstring();
00773 
00774 //--- expand parameters in names of dqmMonitorElements;
00775 //    create drawJob objects
00776     for ( std::map<int, plotDefList>::iterator plot = plotDefMap.begin(); 
00777           plot != plotDefMap.end(); ++plot ) {
00778       if ( drawJob.exists("parameter") ) {
00779         vstring vparameter = drawJob.getParameter<vstring>("parameter");
00780         //std::cout << "replacing parameter = " << format_vstring(vparameter) << " in drawJob = " << (*drawJobName) << std::endl;
00781 
00782         for ( vstring::const_iterator parameter = vparameter.begin();
00783               parameter != vparameter.end(); ++parameter ) {
00784 
00785           plotDefList plot_expanded;
00786 
00787           for ( plotDefList::const_iterator entry = plot->second.begin();
00788                 entry != plot->second.end(); ++entry ) {
00789             std::string dqmMonitorElement = entry->dqmMonitorElement_;
00790             
00791             int errorFlag = 0;
00792             std::string dqmMonitorElement_expanded = replace_string(dqmMonitorElement, parKeyword, *parameter, 1, 1, errorFlag);
00793             //std::cout << " dqmMonitorElement_expanded = " << dqmMonitorElement_expanded << std::endl;
00794             if ( !errorFlag ) {
00795               plot_expanded.push_back(plotDefEntry(dqmMonitorElement_expanded, entry->drawOptionEntry_, 
00796                                                    entry->legendEntry_, entry->legendEntryErrorBand_, entry->process_, entry->doStack_));
00797             } else {
00798               cfgError_ = 1;
00799             }
00800           }
00801 
00802           int errorFlag = 0;
00803           std::string title_expanded = replace_string(title, parKeyword, *parameter, 0, 1, errorFlag);
00804           //std::cout << " title_expanded = " << title_expanded << std::endl;
00805           std::string xAxis_expanded = replace_string(xAxis, parKeyword, *parameter, 0, 1, errorFlag);
00806           //std::cout << " xAxis_expanded = " << xAxis_expanded << std::endl;
00807           std::string yAxis_expanded = replace_string(yAxis, parKeyword, *parameter, 0, 1, errorFlag);
00808           //std::cout << " yAxis_expanded = " << yAxis_expanded << std::endl;
00809           if ( errorFlag ) cfgError_ = 1;
00810 
00811           drawJobs_.push_back(cfgEntryDrawJob(std::string(*drawJobName).append(*parameter),
00812                                               plot_expanded, title_expanded, xAxis_expanded, yAxis_expanded, legend, labels));
00813         }
00814       } else {
00815         drawJobs_.push_back(cfgEntryDrawJob(*drawJobName, 
00816                                             plot->second, title, xAxis, yAxis, legend, labels));
00817       }
00818     }
00819   }
00820 
00821 //--- check that all information neccessary to process drawJob is defined;
00822   for ( std::list<cfgEntryDrawJob>::const_iterator drawJob = drawJobs_.begin();
00823         drawJob != drawJobs_.end(); ++drawJob ) {
00824     for ( plotDefList::const_iterator plot = drawJob->plots_.begin();
00825           plot != drawJob->plots_.end(); ++plot ) {
00826       checkCfgDef<cfgEntryDrawOption>(plot->drawOptionEntry_, drawOptionEntries_, cfgError_, "drawOptionEntry", drawJob->name_);
00827       checkCfgDef<cfgEntryProcess>(plot->process_, processes_, cfgError_, "process", drawJob->name_);
00828     }
00829 
00830     checkCfgDef<cfgEntryAxisX>(drawJob->xAxis_, xAxes_, cfgError_, "xAxis", drawJob->name_);
00831     checkCfgDef<cfgEntryAxisY>(drawJob->yAxis_, yAxes_, cfgError_, "yAxis", drawJob->name_);
00832 
00833     checkCfgDef<cfgEntryLegend>(drawJob->legend_, legends_, cfgError_, "legend", drawJob->name_);
00834 
00835     checkCfgDefs<cfgEntryLabel>(drawJob->labels_, labels_, cfgError_, "label", drawJob->name_);
00836   }
00837 
00838 //--- configure canvas size
00839   //std::cout << "--> configuring canvas size..." << std::endl;
00840   canvasSizeX_ = ( cfg.exists("canvasSizeX") ) ? cfg.getParameter<int>("canvasSizeX") : defaultCanvasSizeX;
00841   canvasSizeY_ = ( cfg.exists("canvasSizeY") ) ? cfg.getParameter<int>("canvasSizeY") : defaultCanvasSizeY;
00842  
00843 //--- configure output files
00844   //std::cout << "--> configuring postscript output file..." << std::endl;
00845 
00846   outputFilePath_ = ( cfg.exists("outputFilePath") ) ? cfg.getParameter<std::string>("outputFilePath") : "";
00847   if ( outputFilePath_.rbegin() != outputFilePath_.rend() ) {
00848     if ( (*outputFilePath_.rbegin()) == '/' ) outputFilePath_.erase(outputFilePath_.length() - 1);
00849   }
00850   //std::cout << " outputFilePath = " << outputFilePath_ << std::endl;
00851 
00852   outputFileName_ = ( cfg.exists("outputFileName") ) ? cfg.getParameter<std::string>("outputFileName") : "";
00853   //std::cout << " outputFileName = " << outputFileName_ << std::endl;
00854 
00855   indOutputFileName_ = ( cfg.exists("indOutputFileName") ) ? cfg.getParameter<std::string>("indOutputFileName") : "";
00856   if ( indOutputFileName_ != "" && indOutputFileName_.find('.') == std::string::npos ) {
00857     edm::LogError ("DQMHistPlotter") << " Failed to determine type of graphics format from indOutputFileName = " << indOutputFileName_ << " !!";
00858     cfgError_ = 1;
00859   }
00860   //std::cout << " indOutputFileName = " << indOutputFileName_ << std::endl;
00861 
00862 //--- check that exactly one type of output is specified for the plots
00863 //    (either separate graphics files displaying one plot each 
00864 //     or postscript file displaying all plots on successive pages;
00865 //     cannot create both types of output simultaneously,
00866 //     as TCanvas::Print seems to interfere with TPostScript::NewPage)
00867   if ( outputFileName_ == "" && indOutputFileName_ == "" ) {
00868     edm::LogError ("DQMHistPlotter") << " Either outputFileName or indOutputFileName must be specified !!";
00869     cfgError_ = 1;
00870   }
00871 
00872   if ( outputFileName_ != "" && indOutputFileName_ != "" ) {
00873     edm::LogError ("DQMHistPlotter") << " Must not specify outputFileName and indOutputFileName simultaneously !!";
00874     cfgError_ = 1;
00875   }
00876 
00877   std::cout << "done." << std::endl;
00878 }
00879 
00880 DQMHistPlotter::~DQMHistPlotter() 
00881 {
00882 // nothing to be done yet...
00883 }
00884 
00885 void DQMHistPlotter::analyze(const edm::Event&, const edm::EventSetup&)
00886 {
00887 // nothing to be done yet...
00888 }
00889 
00890 void DQMHistPlotter::endJob()
00891 {
00892   std::cout << "<DQMHistPlotter::endJob>:" << std::endl;
00893 
00894 //--- check that configuration parameters contain no errors
00895   if ( cfgError_ ) {
00896     edm::LogError ("endJob") << " Error in Configuration ParameterSet --> histograms will NOT be plotted !!";
00897     return;
00898   }
00899 
00900 //--- check that DQMStore service is available
00901   if ( !edm::Service<DQMStore>().isAvailable() ) {
00902     edm::LogError ("endJob") << " Failed to access dqmStore --> histograms will NOT be plotted !!";
00903     return;
00904   }
00905 
00906   DQMStore& dqmStore = (*edm::Service<DQMStore>());
00907 
00908 //--- stop ROOT from keeping references to all hsitograms
00909   //TH1::AddDirectory(false);
00910 
00911 //--- stop ROOT from opening X-window for canvas output
00912 //    (in order to be able to run in batch mode) 
00913   gROOT->SetBatch(true);
00914 
00915 //--- initialize graphical output;
00916 //    open postscript file
00917   TCanvas canvas("DQMHistPlotter","DQMHistPlotter", canvasSizeX_, canvasSizeY_);
00918   canvas.SetFillColor(10);
00919 
00920 //--- restrict area in which histograms are drawn to quadratic TPad in the center of the TCanvas,
00921 //    in order to make space for axis labels...
00922   //TPad pad("EWKTauPad", "EWKTauPad", 0.02, 0.15, 0.98, 0.85);
00923   //pad.SetFillColor(10);
00924   //pad.Draw();
00925   //pad.Divide(1,1);
00926   //pad.cd(1);
00927 
00928   TPostScript* ps = NULL;
00929   if ( outputFileName_ != "" ) {
00930     std::string psFileName = ( outputFilePath_ != "" ) ? std::string(outputFilePath_).append("/").append(outputFileName_) : outputFileName_;
00931     ps = new TPostScript(psFileName.data(), 112);
00932   }
00933     
00934 //--- process drawJobs
00935   for ( std::list<cfgEntryDrawJob>::const_iterator drawJob = drawJobs_.begin(); 
00936         drawJob != drawJobs_.end(); ++drawJob ) {
00937     const std::string& drawJobName = drawJob->name_;
00938     std::cout << "--> processing drawJob " << drawJobName << "..." << std::endl;
00939 
00940 //--- prepare internally used histogram data-structures
00941     TH1* stackedHistogram_sum = NULL;
00942     std::list<TH1*> histogramsToDelete;
00943     std::list<plotDefEntry*> drawOptionsToDelete;
00944 
00945     typedef std::pair<TH1*, const plotDefEntry*> histogram_drawOption_pair;
00946     std::list<histogram_drawOption_pair> allHistograms;
00947 
00948     for ( plotDefList::const_iterator plot = drawJob->plots_.begin();
00949           plot != drawJob->plots_.end(); ++plot ) {
00950 
00951       std::string dqmMonitorElementName_full = dqmDirectoryName(std::string(dqmRootDirectory)).append(plot->dqmMonitorElement_);
00952       //std::cout << " dqmMonitorElementName_full = " << dqmMonitorElementName_full << std::endl;
00953       MonitorElement* dqmMonitorElement = dqmStore.get(dqmMonitorElementName_full);
00954 
00955       TH1* histogram = ( dqmMonitorElement ) ? dynamic_cast<TH1*>(dqmMonitorElement->getTH1()->Clone()) : NULL;
00956       histogramsToDelete.push_back(histogram);
00957 
00958       if ( histogram == NULL ) {
00959         edm::LogError ("endJob") << " Failed to access dqmMonitorElement = " << dqmMonitorElementName_full <<","
00960                                  << " needed by drawJob = " << drawJobName << " --> histograms will NOT be plotted !!";
00961         continue;
00962       }
00963 
00964       if ( !histogram->GetSumw2N() ) histogram->Sumw2();
00965 
00966       const cfgEntryDrawOption* drawOptionConfig = 
00967         findCfgDef<cfgEntryDrawOption>(plot->drawOptionEntry_, drawOptionEntries_, "drawOptionEntry", drawJobName);
00968       if ( drawOptionConfig == NULL ) {
00969         edm::LogError ("endJob") << " Failed to access information needed by drawJob = " << drawJobName 
00970                                  << " --> histograms will NOT be plotted !!";
00971         return;
00972       }
00973       
00974       if ( drawOptionConfig->drawOption_ == drawOption_eBand ) {
00975 //--- add histogram displaying central value as solid line
00976         TH1* histogram_centralValue = dynamic_cast<TH1*>(histogram->Clone());
00977         histogram_centralValue->SetName(std::string(histogram->GetName()).append("_centralValue").data());
00978         cfgEntryDrawOption drawOptionConfig_centralValue(*drawOptionConfig);
00979         drawOptionConfig_centralValue.fillColor_ = 0;
00980         drawOptionConfig_centralValue.fillStyle_ = 0;
00981         drawOptionConfig_centralValue.drawOption_ = "hist";
00982         drawOptionConfig_centralValue.drawOptionLegend_ = "l";
00983         std::string drawOptionName_centralValue = std::string(plot->drawOptionEntry_).append("_centralValue");
00984 //--- entries in std::map need to be unique,
00985 //    so need to check whether drawOptionEntry already exists...
00986         if ( drawOptionEntries_.find(drawOptionName_centralValue) == drawOptionEntries_.end() ) 
00987           drawOptionEntries_.insert(std::pair<std::string, cfgEntryDrawOption>
00988                                     (drawOptionName_centralValue, cfgEntryDrawOption(drawOptionName_centralValue, drawOptionConfig_centralValue)));
00989         plotDefEntry* plot_centralValue = new plotDefEntry(*plot);
00990         plot_centralValue->drawOptionEntry_ = drawOptionName_centralValue;
00991         allHistograms.push_back(histogram_drawOption_pair(histogram_centralValue, plot_centralValue));
00992         histogramsToDelete.push_back(histogram_centralValue);
00993         drawOptionsToDelete.push_back(plot_centralValue);
00994 
00995 //--- add histogram displaying uncertainty as shaded error band
00996         TH1* histogram_ErrorBand = dynamic_cast<TH1*>(histogram->Clone());
00997         histogram_ErrorBand->SetName(std::string(histogram->GetName()).append("_ErrorBand").data());
00998         cfgEntryDrawOption drawOptionConfig_ErrorBand(*drawOptionConfig);
00999         drawOptionConfig_ErrorBand.markerColor_ = drawOptionConfig_ErrorBand.fillColor_;
01000         drawOptionConfig_ErrorBand.markerSize_ = 0.;
01001         drawOptionConfig_ErrorBand.lineColor_ = drawOptionConfig_ErrorBand.fillColor_;
01002         drawOptionConfig_ErrorBand.lineWidth_ = 0;
01003         drawOptionConfig_ErrorBand.drawOption_ = "e2";
01004         drawOptionConfig_ErrorBand.drawOptionLegend_ = "f";
01005         std::string drawOptionName_ErrorBand = std::string(plot->drawOptionEntry_).append("_ErrorBand");
01006 //--- entries in std::map need to be unique,
01007 //    so need to check whether drawOptionEntry already exists...
01008         if ( drawOptionEntries_.find(drawOptionName_ErrorBand) == drawOptionEntries_.end() ) 
01009           drawOptionEntries_.insert(std::pair<std::string, cfgEntryDrawOption>
01010                                     (drawOptionName_ErrorBand, cfgEntryDrawOption(drawOptionName_ErrorBand, drawOptionConfig_ErrorBand)));
01011         plotDefEntry* plot_ErrorBand = new plotDefEntry(*plot);
01012         plot_ErrorBand->drawOptionEntry_ = drawOptionName_ErrorBand;
01013         plot_ErrorBand->isErrorBand_ = true;
01014         allHistograms.push_back(histogram_drawOption_pair(histogram_ErrorBand, plot_ErrorBand));
01015         histogramsToDelete.push_back(histogram_ErrorBand);
01016         drawOptionsToDelete.push_back(plot_ErrorBand);
01017       } else if ( plot->doStack_ ) {
01018         TH1* stackedHistogram = dynamic_cast<TH1*>(histogram->Clone());
01019         if ( stackedHistogram_sum ) stackedHistogram->Add(stackedHistogram_sum);
01020         stackedHistogram_sum = stackedHistogram;
01021         histogramsToDelete.push_back(stackedHistogram);
01022         allHistograms.push_back(histogram_drawOption_pair(stackedHistogram, &(*plot)));
01023       } else {  
01024         allHistograms.push_back(histogram_drawOption_pair(histogram, &(*plot)));
01025       }
01026     }
01027 
01028 //--- determine normalization of y-axis
01029 //    (maximum of any of the histograms included in drawJob)
01030     double yAxisNorm = 0.;
01031     for ( std::list<histogram_drawOption_pair>::const_iterator it = allHistograms.begin();
01032           it != allHistograms.end(); ++it ) {
01033       yAxisNorm = TMath::Max(yAxisNorm, it->first->GetMaximum());
01034     }
01035     //std::cout << " yAxisNorm = " << yAxisNorm << std::endl;
01036     cfgEntryAxisY::setNorm(yAxisNorm);
01037 
01038 //--- prepare histograms for drawing
01039     const cfgEntryAxisX* xAxisConfig = findCfgDef<cfgEntryAxisX>(drawJob->xAxis_, xAxes_, "xAxis", drawJobName);
01040     const cfgEntryAxisY* yAxisConfig = findCfgDef<cfgEntryAxisY>(drawJob->yAxis_, yAxes_, "yAxis", drawJobName);
01041     const cfgEntryLegend* legendConfig = findCfgDef<cfgEntryLegend>(drawJob->legend_, legends_, "legend", drawJobName);
01042     if ( xAxisConfig == NULL || yAxisConfig == NULL || legendConfig == NULL ) {
01043       edm::LogError ("endJob") << " Failed to access information needed by drawJob = " << drawJobName 
01044                                << " --> histograms will NOT be plotted !!";
01045       return;
01046     }
01047 
01048 //--- WARNING: need to call 
01049 //              TLegend::TLegend(Double_t, Double_t,Double_t, Double_t, const char* = "", Option_t* = "brNDC")
01050 //             constructor, as TLegend::TLegend default constructor causes the created TLegend object to behave differently !!
01051     TLegend legend(defaultLegendPosX, defaultLegendPosY, defaultLegendPosX + defaultLegendSizeX, defaultLegendPosY + defaultLegendSizeY);
01052     legendConfig->applyTo(&legend);
01053 
01054     std::list<histoDrawEntry> smProcessHistogramList;
01055     std::list<histoDrawEntry> bsmProcessHistogramList;
01056     std::list<histoDrawEntry> smSumHistogramList;
01057     std::list<histoDrawEntry> smSumUncertaintyHistogramList;
01058     std::list<histoDrawEntry> dataHistogramList;
01059 
01060     for ( std::list<histogram_drawOption_pair>::const_iterator it = allHistograms.begin();
01061           it != allHistograms.end(); ++it ) {
01062       TH1* histogram = it->first;
01063       const plotDefEntry* drawOption = it->second;
01064 
01065       const cfgEntryDrawOption* drawOptionConfig = 
01066         findCfgDef<cfgEntryDrawOption>(drawOption->drawOptionEntry_, drawOptionEntries_, "drawOptionEntry", drawJobName);
01067       const cfgEntryProcess* processConfig = findCfgDef<cfgEntryProcess>(drawOption->process_, processes_, "process", drawJobName);
01068       if ( drawOptionConfig == NULL || processConfig == NULL ) {
01069         edm::LogError ("endJob") << " Failed to access information needed by drawJob = " << drawJobName 
01070                                  << " --> histograms will NOT be plotted !!";
01071         return;
01072       }
01073       
01074       if ( drawJob->title_ != "" ) histogram->SetTitle(drawJob->title_.data());
01075 
01076       xAxisConfig->applyTo(histogram);
01077       yAxisConfig->applyTo(histogram);
01078 
01079       bool yLogScale = ( yAxisConfig->yScale_ == yScale_log ) ? true : false;
01080       //std::cout << " yLogScale = " << yLogScale << std::endl; 
01081       //pad.SetLogy(yLogScale);
01082       canvas.SetLogy(yLogScale);
01083 
01084       drawOptionConfig->applyTo(histogram);
01085       histogram->SetStats(false);
01086 
01087       if ( drawOption->isErrorBand_ ) {
01088         smSumUncertaintyHistogramList.push_back(histoDrawEntry(histogram, drawOptionConfig->drawOption_.data()));
01089       } else {
01090         if ( processConfig->type_ == type_smMC ) {
01091           smProcessHistogramList.push_back(histoDrawEntry(histogram, drawOptionConfig->drawOption_.data()));
01092         } else if ( processConfig->type_ == type_bsmMC ) {
01093           bsmProcessHistogramList.push_back(histoDrawEntry(histogram, drawOptionConfig->drawOption_.data()));
01094         } else if ( processConfig->type_ == type_smSumMC ) {
01095           smSumHistogramList.push_back(histoDrawEntry(histogram, drawOptionConfig->drawOption_.data()));
01096         } else if ( processConfig->type_ == type_Data ) {
01097           dataHistogramList.push_back(histoDrawEntry(histogram, drawOptionConfig->drawOption_.data()));
01098         } 
01099       }
01100 
01101       std::string legendEntry, legendDrawOption;
01102       if ( drawOption->isErrorBand_ ) {
01103         legendEntry = ( drawOption->legendEntryErrorBand_ != "" ) ? drawOption->legendEntryErrorBand_ : processConfig->legendEntryErrorBand_;
01104         legendDrawOption = "f";
01105       } else {
01106         legendEntry = ( drawOption->legendEntry_ != "" ) ? drawOption->legendEntry_ : processConfig->legendEntry_;
01107         legendDrawOption = drawOptionConfig->drawOptionLegend_;
01108       } 
01109 
01110       legend.AddEntry(histogram, legendEntry.data(), legendDrawOption.data());
01111     }
01112 
01113     std::list<TPaveText> labels;
01114     for ( vstring::const_iterator labelName = drawJob->labels_.begin();
01115           labelName != drawJob->labels_.end(); ++labelName ) {
01116       const cfgEntryLabel* labelConfig = findCfgDef<cfgEntryLabel>(*labelName, labels_, "label", drawJobName);
01117       
01118       TPaveText label;
01119       labelConfig->applyTo(&label);
01120 
01121       labels.push_back(label);
01122     }
01123 
01124 //--- draw histograms 
01125 //   - in the order:
01126 //    1. uncertainty on sum of all Standard Model processes
01127 //    2. sum of all Standard Model processes
01128 //    3. individual Standard Model processes
01129 //    4. individual beyond the Standard Model processes
01130 //    5. data
01131     bool isFirstHistogram = true;
01132     drawHistograms(smSumUncertaintyHistogramList, isFirstHistogram);
01133     drawHistograms(smSumHistogramList, isFirstHistogram);
01134 
01135 //--- process histograms for individual Standard Model processes
01136 //    in reverse order, so that most stacked histogram gets drawn first
01137     for ( std::list<histoDrawEntry>::reverse_iterator it = smProcessHistogramList.rbegin();
01138           it != smProcessHistogramList.rend(); ++it ) {
01139       std::string drawOption = ( isFirstHistogram ) ? it->second : std::string(it->second).append("same");
01140       it->first->Draw(drawOption.data());
01141       isFirstHistogram = false;
01142     }
01143         
01144     drawHistograms(bsmProcessHistogramList, isFirstHistogram);
01145     drawHistograms(dataHistogramList, isFirstHistogram);
01146 
01147     legend.Draw();
01148 
01149     for ( std::list<TPaveText>::iterator label = labels.begin();
01150           label != labels.end(); ++label ) {
01151       label->Draw();
01152     }
01153 
01154     //pad.RedrawAxis();
01155     
01156     canvas.Update();
01157     //pad.Update();
01158 
01159     if ( indOutputFileName_ != "" ) {
01160       int errorFlag = 0;
01161       std::string modIndOutputFileName = replace_string(indOutputFileName_, plotKeyword, drawJobName, 1, 1, errorFlag);
01162       if ( !errorFlag ) {
01163         std::string fullFileName = ( outputFilePath_ != "" ) ? 
01164           std::string(outputFilePath_).append("/").append(modIndOutputFileName) : modIndOutputFileName;
01165         canvas.Print(fullFileName.data());
01166       } else {
01167         edm::LogError("endJob") << " Failed to decode indOutputFileName = " << indOutputFileName_ << " --> skipping !!";
01168       }
01169     }
01170 
01171     if ( ps ) ps->NewPage();
01172 
01173 //--- delete temporarily created histogram and drawOption objects
01174     for ( std::list<TH1*>::const_iterator histogram = histogramsToDelete.begin();
01175           histogram != histogramsToDelete.end(); ++histogram ) {
01176       delete (*histogram);
01177     }
01178 
01179     for ( std::list<plotDefEntry*>::const_iterator drawOption = drawOptionsToDelete.begin();
01180           drawOption != drawOptionsToDelete.end(); ++drawOption ) {
01181       delete (*drawOption);
01182     }
01183   }
01184 
01185 //--- close postscript file
01186   canvas.Clear();
01187   std::cout << "done." << std::endl;
01188   if ( ps ) ps->Close();
01189   delete ps;
01190 }
01191 
01192 #include "FWCore/Framework/interface/MakerMacros.h"
01193 
01194 DEFINE_FWK_MODULE(DQMHistPlotter);