CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/DQMServices/Diagnostic/src/HDQMInspector.cc

Go to the documentation of this file.
00001 //---------------------------------------------------------//
00002 //
00003 //-- extract summary informations from historic DB --
00004 //-- plot summary informations vs run number or vs detID --
00005 //
00006 //---------------------------------------------------------//
00007 //---------------------------------------------------------//
00008 // 
00009 //  12-08-2008 - domenico.giordano@cern.ch 
00010 //  12-06-2008 - anne-catherine.le.bihan@cern.ch 
00011 //
00012 //---------------------------------------------------------//
00013 
00014 #include "DQMServices/Diagnostic/interface/HDQMInspector.h"
00015 #include <time.h>
00016 #include "TGraphErrors.h"
00017 #include "TCanvas.h"
00018 #include "TString.h"
00019 #include "TROOT.h"
00020 #include "TStyle.h"
00021 #include "TAxis.h"
00022 #include "TMath.h"
00023 #include "TLegend.h"
00024 #include "TVirtualPad.h"
00025 #include "TFormula.h"
00026 #include "TObjArray.h"
00027 #include "TObjString.h"
00028 
00029 
00030 void HDQMInspector::style()
00031 {
00032   TStyle* theStyle= new TStyle();
00033   theStyle->SetOptStat(0);
00034   //gROOT->SetStyle("Plain");
00035   theStyle->SetOptStat(0);
00036   theStyle->SetOptFit(111);
00037   theStyle->SetStatFont(12);
00038   theStyle->SetStatBorderSize(1);
00039   theStyle->SetCanvasColor(0);
00040   theStyle->SetCanvasBorderMode(0);
00041   theStyle->SetPadBorderMode(0);
00042   theStyle->SetPadColor(0);
00043   theStyle->SetLineWidth(1);
00044   theStyle->SetLineStyle(2);
00045   theStyle->SetPalette(1);
00046   theStyle->SetMarkerStyle(20);
00047   theStyle->SetMarkerColor(2);
00048   theStyle->SetLabelSize(0.05,"y");
00049   theStyle->SetLabelSize(0.04,"x");
00050   theStyle->SetTitleFontSize(0.2);
00051   theStyle->SetTitleW(0.9);
00052   theStyle->SetTitleH(0.06);
00053   theStyle->SetPadLeftMargin(0.12);   
00054   theStyle->SetPadTopMargin(0.13);
00055   theStyle->cd();
00056 }
00057 
00058 void HDQMInspector::setDB(const std::string & DBName, const std::string & DBTag, const std::string & DBauth)
00059 {
00060   if( DBName_==DBName && DBTag_==DBTag && DBauth_ == DBauth)
00061     return;
00062 
00063   DBName_= DBName;
00064   DBTag_= DBTag;
00065   DBauth_ = DBauth;
00066 
00067   std::cout << "Name of DB = "<< DBName << std::endl;
00068   std::cout << "DBTag = "<< DBTag << std::endl;
00069   std::cout << "DBauth = "<< DBauth << std::endl;
00070   std::cout <<std::endl;
00071 
00072   accessDB();
00073   
00074   fOutFile = new TFile( "historicDQM.root","RECREATE" );
00075   if (!fOutFile->IsOpen()) {
00076     std::cerr << "ERROR: cannot open output file" << std::endl;
00077     exit(1);
00078   }
00079   fOutFile->cd();
00080 }
00081 
00082 void HDQMInspector::accessDB()
00083 {
00084   //double start, end;
00085   // start = clock();   
00086  
00087   if(Iterator!=0)
00088     delete Iterator;
00089   
00090   Iterator = new CondCachedIter<HDQMSummary>(); 
00091 
00092   std::cout << "creating connection" << std::endl;
00093   Iterator->create(DBName_,DBTag_,DBauth_);
00094   std::cout << "connection created" << std::endl;
00095 
00096   
00097   InitializeIOVList();
00098   //  end = clock();
00099   //  if(iDebug)
00100   //std::cout <<"Time Creation link with Database = " <<  ((double) (end - start)) << " (a.u.)" <<std::endl; 
00101 }
00102 
00103 
00104 void  HDQMInspector::setBlackList(std::string const & ListItems)
00105 {
00106 
00107   // Run over entire input string
00108   for (std::string::const_iterator Pos = ListItems.begin(); Pos != ListItems.end(); ) {
00109 
00110     // The rest of the string
00111     std::string Remainder(Pos, ListItems.end());
00112 
00113     // This entry will be from the beginning of the remainder to either a ","
00114     // or the end of the string
00115     std::string Entry = Remainder.substr(0, Remainder.find(","));
00116 
00117     // If we find a "-" we know it's a blacklist range
00118     if ( Entry.find("-") ) {
00119 
00120       // Get the first and last runs from this range
00121       int const FirstRun = atoi( Entry.substr(0, Entry.find("-")).c_str() );
00122       int const LastRun  = atoi( Entry.substr(Entry.find("-")+1).c_str() );
00123 
00124       // If you entered it stupidly we're going to stop here.
00125       if (FirstRun > LastRun) {
00126         std::cerr << "ERROR: FirstRun > LastRun in blackList" << std::endl;
00127         exit(1);
00128       }
00129 
00130       // For now the simplest thing to do is fill in gaps including each end
00131       for (int i = FirstRun; i <= LastRun; ++i) {
00132         blackList.push_back(i);
00133       }
00134 
00135     } else {
00136       // If we didn't see a "-" just add it to the list
00137       blackList.push_back( atoi(Entry.c_str()) );
00138     }
00139 
00140     // This is to make sure we are in the correct position as we go on.
00141     Pos += Entry.size();
00142     if (Pos != ListItems.end()) {
00143       Pos += 1;
00144     }
00145 
00146   }
00147 
00148   // sort the list for faster searching later
00149   std::sort(blackList.begin(), blackList.end());
00150 
00151   return;
00152 }
00153 
00154 void  HDQMInspector::setWhiteList(std::string const & ListItems)
00155 {
00156 
00157   // Run over entire input string
00158   for (std::string::const_iterator Pos = ListItems.begin(); Pos != ListItems.end(); ) {
00159 
00160     // The rest of the string
00161     std::string Remainder(Pos, ListItems.end());
00162 
00163     // This entry will be from the beginning of the remainder to either a ","
00164     // or the end of the string
00165     std::string Entry = Remainder.substr(0, Remainder.find(","));
00166 
00167     // If we find a "-" we know it's a whitelist range
00168     if ( Entry.find("-") ) {
00169 
00170       // Get the first and last runs from this range
00171       int const FirstRun = atoi( Entry.substr(0, Entry.find("-")).c_str() );
00172       int const LastRun  = atoi( Entry.substr(Entry.find("-")+1).c_str() );
00173 
00174       // If you entered it stupidly we're going to stop here.
00175       if (FirstRun > LastRun) {
00176         std::cerr << "ERROR: FirstRun > LastRun in WhiteList" << std::endl;
00177         exit(1);
00178       }
00179 
00180       // For now the simplest thing to do is fill in gaps including each end
00181       for (int i = FirstRun; i <= LastRun; ++i) {
00182         whiteList.push_back(i);
00183       }
00184 
00185     } else {
00186       // If we didn't see a "-" just add it to the list
00187       whiteList.push_back( atoi(Entry.c_str()) );
00188     }
00189 
00190     // This is to make sure we are in the correct position as we go on.
00191     Pos += Entry.size();
00192     if (Pos != ListItems.end()) {
00193       Pos += 1;
00194     }
00195 
00196   }
00197 
00198   // sort the list for faster searching later
00199   std::sort(whiteList.begin(), whiteList.end());
00200 
00201   return;
00202 }
00203 
00204 std::string HDQMInspector::readListFromFile(const std::string & listFileName)
00205 {
00206   std::ifstream listFile;
00207   listFile.open(listFileName.c_str());
00208   std::string listString;
00209   if( !listFile ) {
00210     std::cout << "Warning: list file" << listFileName << " not found" << std::endl;
00211     return listString;
00212   }
00213   while( !listFile.eof() ) {
00214     std::string line;
00215     listFile >> line;
00216     if( line != "" ) {
00217       listString += line;
00218       listString += ",";
00219     }
00220   }
00221   // Remove the last ","
00222   std::string::size_type pos = listString.find_last_of(",");
00223   if( pos != std::string::npos ) {
00224     listString.erase(pos);
00225   }
00226   std::cout << "whiteList = " << listString << std::endl;
00227   return listString;
00228 }
00229 
00230 bool  HDQMInspector::isListed(unsigned int run, std::vector<unsigned int>& vList)
00231 {
00232   // This routine expectes a sorted list and returns true if the run is in the list,
00233   // false otherwise
00234 
00235   // Binary search is much faster, but you MUST give it a sorted list.
00236   if (std::binary_search(vList.begin(), vList.end(), run)) {
00237     if(iDebug) {
00238       std::cout << "\n Run "<< run << " is listed !!\n" << std::endl;
00239     }
00240     return true;
00241   }
00242 
00243   return false;
00244 
00245 }
00246 
00247 
00248 void HDQMInspector::InitializeIOVList()
00249 {
00250   const HDQMSummary* reference;
00251   while((reference = Iterator->next())) {
00252     iovList.push_back(Iterator->getStartTime());
00253     if (iDebug) {
00254       std::cout << "iovList " << iovList.back() << std::endl;
00255     }
00256   } 
00257   Iterator->rewind();
00258 }
00259 
00260 bool HDQMInspector::setRange(unsigned int& firstRun, unsigned int& lastRun)
00261 {
00262   unsigned int first,last;
00263 
00264   for(size_t i=0;i<iovList.size();++i) {
00265     if (iDebug) {
00266       std::cout << iovList.at(i)<< std::endl;
00267     }
00268   }
00269 
00270   std::vector<unsigned int>::iterator iter;
00271 
00272   iter=std::lower_bound(iovList.begin(),iovList.end(),firstRun);
00273   if (iter!=iovList.end())
00274     first=*iter;
00275   else{
00276     std::cout << "firstRun (" << firstRun << ") > last iov ("<<iovList.back()<< ")"<<std::endl; 
00277     return false;
00278   }
00279 
00280   iter=std::lower_bound(iovList.begin(),iovList.end(),lastRun);
00281   if (iter!=iovList.end()){
00282     if (*iter>lastRun) last = *(iter-1);
00283     else last=*iter;
00284   }
00285   else{
00286     last=iovList.back();
00287   }
00288   
00289   firstRun=first;
00290   lastRun=last; 
00291   std::cout << "setting Range firstRun (" << first << ") - lastRun ("<<last<< ")"<<std::endl; 
00292   Iterator->setRange(first,last);
00293   
00294   return true;
00295 }
00296 
00297 void HDQMInspector::createTrendLastRuns(const std::string ListItems, const std::string CanvasName,
00298                                         const int logy, const std::string Conditions, std::string const& Labels, const unsigned int nRuns, int const UseYRange, double const& YMin, double const& YMax)
00299 {
00300   unsigned int first,last;
00301   unsigned int iovListSize = iovList.size();
00302 
00303   if (iovListSize>0) 
00304   { 
00305     last = iovList.back();
00306 
00307     if (iovListSize>=nRuns) {
00308       first = iovList.at(iovListSize-nRuns);
00309     } else {
00310       first = *iovList.begin();
00311     }
00312   }
00313   else return;
00314 
00315   createTrend(ListItems,CanvasName,logy,Conditions,Labels,first,last, UseYRange, YMin, YMax);
00316 
00317   return;
00318 }
00319 
00320 void HDQMInspector::createTrend(std::string ListItems, std::string CanvasName, int logy, std::string Conditions, std::string const& Labels, unsigned int firstRun, unsigned int lastRun, int const UseYRange, double const& YMin, double const& YMax)
00321 {
00322   std::cout << "\n****************\nCreateTrend\n****************\n" << std::endl;
00323   std::cout << "ListItems : " << ListItems << std::endl;
00324   std::cout << "Conditions : " << Conditions << std::endl;
00325 
00326   vRun_.clear();
00327   vSummary_.clear();
00328   vDetIdItemList_.clear();
00329 
00330   std::vector<DetIdItemList> vDetIdItemListCut;
00331   
00332   size_t nPads=unpackItems(ListItems);   
00333 
00334   unpackConditions(Conditions,vDetIdItemListCut);
00335  
00336   //   double start = clock(); 
00337 
00338   std::cout << "firstRun " << firstRun << " lastRun " << lastRun << std::endl;
00339   if(!setRange(firstRun,lastRun)){
00340     Iterator->rewind();
00341     return;
00342   }
00343   const HDQMSummary* reference;
00344   while((reference = Iterator->next())) { 
00345 
00346 
00347     // Check the run and black and white lists
00348     if(Iterator->getStartTime()<firstRun || Iterator->getStartTime()>lastRun || isListed(reference->getRunNr(), blackList)) {
00349       continue;
00350     }
00351     if (whiteList.size() > 0 && !isListed(reference->getRunNr(), whiteList)) {
00352       continue;
00353     }
00354 
00355     if(vDetIdItemListCut.size()){
00356       for(size_t ij=0;ij!=vDetIdItemListCut.size();++ij){
00357         vDetIdItemListCut[ij].values=reference->getSummaryObj(vDetIdItemListCut[ij].detid, vDetIdItemListCut[ij].items);
00358       }
00359 
00360       if(!ApplyConditions(Conditions,vDetIdItemListCut))
00361         continue;
00362     }
00363 
00364     vRun_.push_back(reference->getRunNr());
00365 
00366     for(size_t ij=0;ij!=vDetIdItemList_.size();++ij){
00367       vDetIdItemList_[ij].values=reference->getSummaryObj(vDetIdItemList_[ij].detid, vDetIdItemList_[ij].items);
00368      
00369       vSummary_.insert(vSummary_.end(),vDetIdItemList_[ij].values.begin(),vDetIdItemList_[ij].values.end());   
00370       if(iDebug){
00371         std::cout << ListItems  << " run " << vRun_.back() << " values \n" ;
00372         DetIdItemList detiditemlist=vDetIdItemList_[ij];
00373         for(size_t i=0;i<detiditemlist.items.size();++i) {
00374           std::cout << "\t" << detiditemlist.items[i] << " " << detiditemlist.values[i] <<" " << i << " \n";
00375         }
00376         std::cout << "\n" << std::endl;
00377       }
00378     }
00379   }
00380 
00381   if(vRun_.size()) {
00382     plot(nPads, CanvasName, logy, Labels, UseYRange, YMin, YMax);
00383   }
00384    
00385      
00386   std::cout << "\n****** Ignore this error *****\n" << std::endl;
00387   Iterator->rewind();
00388   std::cout << "\n******************************\n" << std::endl;
00389 }
00390 
00391 void HDQMInspector::plot(size_t& nPads, std::string CanvasName, int logy, std::string const& Labels, int const UseYRange, double const YMin, double const YMax)
00392 {
00393   std::cout << "\n********\nplot\n*****\n"<< std::endl;
00394 
00395   style();
00396 
00397   double *X, *Y, *EX, *EY, *YCumul;
00398   X=new double[vRun_.size()];
00399   Y=new double[vRun_.size()];
00400   EX=new double[vRun_.size()]; 
00401   EY=new double[vRun_.size()];  
00402   YCumul=new double[vRun_.size()];
00403   
00404   size_t index;
00405   TCanvas *C;
00406   TGraphErrors *graph;
00407 
00408   if(CanvasName==""){
00409     char name[128];
00410     sprintf(name,"%d",(int) clock());
00411     CanvasName=std::string(name);
00412   }
00413   
00414   std::string rootCName = CanvasName;
00415   rootCName.replace(rootCName.find("."),rootCName.size()-rootCName.find("."),"");
00416  
00417   C=new TCanvas(rootCName.c_str(),"");
00418   int ndiv=(int) sqrt(nPads);
00419   C->Divide(ndiv,nPads/ndiv+ (nPads%ndiv?1:0));
00420  
00421   int padCount=0;
00422 
00423   vlistItems_.clear();
00424   vdetId_.clear();
00425 
00426   for(size_t ic=0;ic<vDetIdItemList_.size();++ic){
00427     vlistItems_.insert(vlistItems_.end(),vDetIdItemList_[ic].items.begin(),vDetIdItemList_[ic].items.end());
00428     vdetId_.insert(vdetId_.end(),vDetIdItemList_[ic].items.size(),vDetIdItemList_[ic].detid);
00429   }
00430 
00431   // Vector of graphs in this request and DetNames which correspond to them
00432   std::vector<TGraphErrors*> VectorOfGraphs;
00433   std::vector<std::string> VectorOfDetNames;
00434 
00435   for(size_t i=0;i<vlistItems_.size();++i){
00436     std::cout <<  "TkRegion " << vdetId_[i] << " " << vlistItems_[i] << std::endl;
00437 
00438     if(vlistItems_.at(i).find("Summary")!= std::string::npos) vlistItems_.at(i).replace(vlistItems_.at(i).find("Summary_"),8,"");
00439     if(vlistItems_.at(i).find(fSep)!= std::string::npos) vlistItems_.at(i).replace(vlistItems_.at(i).find(fSep),fSep.size(),"_");
00440     
00441  
00442     std::stringstream ss;
00443     if (fHDQMInspectorConfig != 0x0) {
00444       ss << fHDQMInspectorConfig->translateDetId( vdetId_[i] ) << vlistItems_[i];
00445       VectorOfDetNames.push_back( fHDQMInspectorConfig->translateDetId( vdetId_[i] ));
00446     } else {
00447       ss << "Id " << vdetId_[i] << " " << vlistItems_[i];
00448       VectorOfDetNames.push_back( "???" );
00449     }
00450 
00451     
00452     bool const itemForIntegration = fHDQMInspectorConfig ? fHDQMInspectorConfig->computeIntegral(vlistItems_[i]) : false;
00453    
00454     int addShift=0;
00455     for(size_t j=0;j<vRun_.size();++j){
00456       index=j*vlistItems_.size()+i;
00457       X[j]=vRun_[j];
00458       EX[j]=0;
00459       Y[j]=vSummary_[index];
00460       //if (Y[j]==-10 || Y[j]==-9999 || Y[j] ==-99) {EY[j] = 0; Y[j] = 0;}
00461        
00462       // -9999 : existing HDQMSummary object in DB but part of the information not uploaded
00463       // -99   : HDQMSummary object not existing for this detId, informations are missing for all quantities 
00464       // -10 bad fit ?
00465 
00466       //std::cout << "dhidas " << vlistItems_[i] << "  " << vRun_[j] << "  " << vSummary_[index] << std::endl;
00467      
00468       if(vlistItems_[i].find("mean")!=std::string::npos){
00469         //if the quantity requested is mean, the error is evaluated as the error on the mean=rms/sqrt(entries)
00470         EY[j]=vSummary_[index+2]>0?vSummary_[index+1]/sqrt(vSummary_[index+2]):0;
00471         addShift=2;
00472       }else if (vlistItems_[i].find("entries")!=std::string::npos) {
00473         addShift=0;
00474       }else if (vlistItems_[i].find("landauPeak")!=std::string::npos){
00475         EY[j]=vSummary_[index+1];
00476         addShift=1;
00477       }
00478       else if (vlistItems_[i].find("gaussMean")!=std::string::npos){
00479         EY[j]=vSummary_[index+1];
00480         addShift=1;
00481       }
00482       else if (vlistItems_[i].find("Chi2NDF")!=std::string::npos || vlistItems_[i].find("rms")!=std::string::npos){
00483         EY[j]= 0.;
00484       }
00485       else {
00486         //EY[j]=vSummary_[index+1];
00487         EY[j]=0;// dhidas hack fix for now.  needs to be fixed
00488         addShift=1;
00489       }
00490 
00491       // integrate
00492       if (j == 0 ) YCumul[j] = Y[j]; 
00493       else         YCumul[j] = Y[j] + YCumul[j-1];
00494 
00495       // dhidas HACK for now
00496       EY[j] = 0;
00497 
00498       if(iDebug) {
00499         std::cout << index-j*vlistItems_.size() <<  " " << j  << " " << X[j]  << " " << Y[j] << " " << EY[j] << std::endl;
00500       }
00501     }
00502 
00503     C->cd(++padCount);
00504     gPad->SetLogy(logy);
00505 
00506     // Loop over all values and correct them for user defined range
00507     if (UseYRange != 0) {
00508       for (size_t iRun = 0; iRun != vRun_.size(); ++iRun) {
00509         if (UseYRange % 2 == 1 && Y[iRun] < YMin) {
00510           Y[iRun] = YMin;
00511           EY[iRun] = 0;
00512         }
00513         if (UseYRange >= 2  && Y[iRun] > YMax) {
00514           Y[iRun] = YMax;
00515           EY[iRun] = 0;
00516         }
00517       }
00518     }
00519     
00520     graph = new TGraphErrors((int) vRun_.size(),X,Y,EX,EY);
00521     if( fSkip99s || fSkip0s ) {
00522       int iptTGraph = 0;
00523       for (size_t ipt = 0; ipt != vRun_.size(); ++ipt) {
00524         // skip 99s or 0s when requested
00525         // std::cout << "point = " << Y[ipt] << std::endl;
00526         // if( Y[ipt] == 0 ) {
00527         //   std::cout << "fSkip0s = " << fSkip0s << std::endl;
00528         // }
00529         // if( (Y[ipt] == -10 || Y[ipt] == -9999 || Y[ipt] == -999 || Y[ipt] == -99) ) {
00530         //   std::cout << "fSkip99s = " << fSkip99s << std::endl;
00531         // }
00532         if( ((Y[ipt] == -10 || Y[ipt] == -9999 || Y[ipt] == -999 || Y[ipt] == -99) && fSkip99s) || (Y[ipt] == 0 && fSkip0s) ) {
00533           // std::cout << "removing point Y["<<ipt<<"] = " << Y[ipt] << ", when graph->GetN() = " << graph->GetN() << " and iptTGraph = " << iptTGraph << std::endl;
00534           // Int_t point = graph->RemovePoint(iptTGraph);
00535           // std::cout << "point removed = " << point << std::endl;
00536           graph->RemovePoint(iptTGraph);
00537         }
00538         else {
00539           // The TGraph is shrinked everytime a point is removed. We use another counter that
00540           // is increased only when not removing elements from the TGraph.
00541           ++iptTGraph;
00542         }
00543       }
00544     }
00545         
00546     graph->SetTitle(ss.str().c_str());
00547     if (UseYRange % 2 == 1) {
00548       graph->SetMinimum(YMin);
00549     }
00550     if (UseYRange >= 2) {
00551       graph->SetMaximum(YMax);
00552     }
00553 
00554     graph->Draw("Ap");
00555     graph->SetName(ss.str().c_str());
00556     graph->GetXaxis()->SetTitle("Run number");
00557     graph->Write();
00558 
00559     // put the graph in the vector eh.
00560     VectorOfGraphs.push_back(graph);
00561 
00562     // dhidas
00563     // Want to get some values into file... testing
00564     //for (int iDean = 0; iDean != graph.GetN(); ++iDean) {
00565     //  static std::ofstream OutFile("DeanOut.txt");
00566     //  fprintf("%9i %9i %12.3f\n", iDean, graph.GetX()[iDean], graph.GetY()[iDean]);
00567     //}
00568 
00569     if (itemForIntegration)
00570     {  
00571       std::stringstream ss2; std::stringstream ss3; std::stringstream ss4;
00572       std::string title =  vlistItems_.at(i);
00573      
00574       ss2 << title << "_Integral";
00575       ss3 << title << "_Integrated.gif";
00576       ss4 << title << "_Integrated.root";
00577 
00578       TCanvas* C2 = new TCanvas(ss2.str().c_str(),"");
00579       TGraphErrors* graph2 = new TGraphErrors((int) vRun_.size(),X,YCumul,EX,EX);
00580       graph2->SetTitle(ss2.str().c_str());
00581       graph2->SetMarkerColor(1);
00582       graph2->Draw("Ap");
00583       graph2->SetName(ss2.str().c_str());
00584       graph2->GetXaxis()->SetTitle("Run number");
00585       graph2->Write();
00586       C2->Write();
00587       C2->SaveAs(ss3.str().c_str());
00588       C2->SaveAs(ss4.str().c_str());
00589       // dhidas commented out below because it doesn't seem useful.  uncomment if you like, it was just annoying me.
00590       //C2->SaveAs(ss3.str().replace(ss3.str().find("."),ss3.str().size()-ss3.str().find("."),".C").c_str());
00591       }
00592     i+=addShift;
00593   }
00594   C->Write();
00595   C->SaveAs(CanvasName.c_str());
00596   // dhidas commented out below because it doesn't seem useful.  uncomment if you like, it was just annoying me.
00597   //C->SaveAs(CanvasName.replace(CanvasName.find("."),CanvasName.size()-CanvasName.find("."),".C").c_str());//savewith .C
00598   // dhidas commented out below because it doesn't seem useful.  uncomment if you like, it was just annoying me.
00599   //C->SaveAs(CanvasName.replace(CanvasName.find("."),CanvasName.size()-CanvasName.find("."),".C").c_str());//savewith .C
00600 
00601 
00602   // Okay, we wrote the first canvas, not let's try to overlay the graphs on another one..
00603   if (VectorOfGraphs.size() > 1) {
00604 
00605     // Create the legend for this overlay graph
00606     TLegend OverlayLegend(0.80,0.35,0.99,0.65);
00607 
00608     // Use for storing the global min/max.
00609     float max = -9999;
00610     float min =  9999;
00611 
00612     // Canvas we'll paint the overlays on
00613     TCanvas DeanCan("DeanCan", "DeanCan");
00614     TVirtualPad* VPad = DeanCan.cd();
00615     VPad->SetRightMargin(0.21);
00616     VPad->SetTopMargin(0.13);
00617 
00618     // Replace default legend names with labels if they exist
00619     TString const LNames = Labels;
00620     TObjArray* MyArrayPtr = LNames.Tokenize(",");
00621     if (MyArrayPtr) {
00622       MyArrayPtr->SetOwner(kTRUE);
00623       for( int i = 0; i <= MyArrayPtr->GetLast(); ++i ) {
00624         if( i < int(VectorOfDetNames.size()) ) {
00625           VectorOfDetNames[i] = ((TObjString*) MyArrayPtr->At(i) )->GetString().Data();
00626         }
00627       }
00628       MyArrayPtr->Delete();
00629     }
00630         
00631 
00632     // Let's loop over all graphs in this request
00633     for (size_t i = 0; i != VectorOfGraphs.size(); ++i) {
00634 
00635       // Strip off the det name in the i-th hist title
00636       TString MyTitle = VectorOfGraphs[i]->GetTitle();
00637       std::cout << "dhidas " << MyTitle << " : " << VectorOfDetNames[i] << std::endl;
00638       MyTitle.ReplaceAll(VectorOfDetNames[i]+"_", "");
00639       MyTitle.ReplaceAll("_"+VectorOfDetNames[i], "");
00640       MyTitle.ReplaceAll(VectorOfDetNames[i], "");
00641       std::cout << "dhidas " << MyTitle << std::endl;
00642       VectorOfGraphs[i]->SetTitle( MyTitle );
00643 
00644       // Add this to the legend, sure, good
00645       OverlayLegend.AddEntry(VectorOfGraphs[i], VectorOfDetNames[i].c_str(), "p");
00646 
00647       // You have to get the min and max by hand because root is completely retarded
00648       if (min > findGraphMin(VectorOfGraphs[i]) ) {
00649         min = findGraphMin(VectorOfGraphs[i]);
00650       }
00651       if (max < findGraphMax(VectorOfGraphs[i])) {
00652         max = findGraphMax(VectorOfGraphs[i]);
00653       }
00654 
00655       // let's use these colors and shapes for now
00656       VectorOfGraphs[i]->SetMarkerStyle(20+i);
00657       VectorOfGraphs[i]->SetMarkerColor(2+i);
00658     }
00659     // May as well set the min and max for first graph we'll draw
00660     VectorOfGraphs[0]->SetMinimum((min)-((max)-(min))/5.);
00661     VectorOfGraphs[0]->SetMaximum((max)+((max)-(min))/5.);
00662     if (UseYRange % 2 == 1) {
00663       VectorOfGraphs[0]->SetMinimum(YMin);
00664     }
00665     if (UseYRange >= 2) {
00666       VectorOfGraphs[0]->SetMaximum(YMax);
00667     }
00668 
00669     // Draw the first one with axis (A) and the rest just points (p), draw the legend, and save that canvas
00670     
00671     VectorOfGraphs[0]->Draw("Ap");
00672     for (size_t i = 1; i != VectorOfGraphs.size(); ++i) {
00673       VectorOfGraphs[i]->Draw("p");
00674     }
00675     OverlayLegend.Draw("same");
00676     //OverlayLegend.SetTextSize(1.5);
00677     DeanCan.SaveAs(CanvasName.replace(CanvasName.find("."),CanvasName.size()-CanvasName.find("."),"_Overlay.gif").c_str());
00678   }
00679 
00680   // While I'm here I may as well try deleting the graphs since people don't like to clean up after themselves
00681   for (size_t i = 0; i != VectorOfGraphs.size(); ++i) {
00682     delete VectorOfGraphs[i];
00683   }
00684 
00685   // Why do people never put a friggin return statement?
00686   return;
00687 
00688 }
00689 
00690 size_t HDQMInspector::unpackItems(std::string& ListItems)
00691 {
00692   std::string::size_type oldloc=0; 
00693   std::string::size_type loc = ListItems.find( ",", oldloc );
00694   size_t count=1;
00695   while( loc != std::string::npos ) {
00696     setItems(ListItems.substr(oldloc,loc-oldloc));
00697     oldloc=loc+1;
00698     loc=ListItems.find( ",", oldloc );
00699     count++; 
00700   } 
00701   //there is a single item
00702   setItems(ListItems.substr(oldloc,loc-oldloc));
00703   std::cout << std::endl;
00704   return count;
00705 }
00706 
00707 void HDQMInspector::unpackConditions( std::string& Conditions, std::vector<DetIdItemList>& vdetIdItemList)
00708 {
00709   char * pch;
00710   char delimiters[128]="><=+-*/&|() ";
00711   char copyConditions[1024];
00712   sprintf(copyConditions,"%s",Conditions.c_str());
00713   pch = strtok (copyConditions,delimiters);
00714   while (pch != NULL){
00715     if(strstr(pch,fSep.c_str())!=NULL){
00716       DetIdItemList detiditemlist;
00717       std::string itemD(pch);
00718       detiditemlist.detid=atol(itemD.substr(0,itemD.find(fSep)).c_str());
00719       detiditemlist.items.push_back(itemD.substr(itemD.find(fSep)+fSep.size())); // dhidas update +.size instead of "1"
00720       if (iDebug) {
00721         std::cout << "Found a Condition " << detiditemlist.items.back() << " for detId " << detiditemlist.detid << std::endl;
00722       }
00723       
00724       if(vdetIdItemList.size())
00725         if(vdetIdItemList.back().detid==detiditemlist.detid)
00726           vdetIdItemList.back().items.insert(vdetIdItemList.back().items.end(),detiditemlist.items.begin(),detiditemlist.items.end());
00727         else
00728           vdetIdItemList.push_back(detiditemlist);
00729       else
00730         vdetIdItemList.push_back(detiditemlist); 
00731     }
00732     pch = strtok (NULL,delimiters);
00733   }
00734 }
00735 
00736 bool HDQMInspector::ApplyConditions(std::string& Conditions, std::vector<DetIdItemList>& vdetIdItemList)
00737 {
00738   double resultdbl=1;
00739   char cConditions[1024];
00740   char singleCondition[1024];
00741   char condCVal[1024];   
00742 
00743   sprintf(cConditions,"%s",Conditions.c_str());
00744   if (iDebug) {
00745     std::cout << "Conditions " << cConditions << std::endl;
00746   }
00747   for(size_t ic=0;ic<vdetIdItemList.size();++ic)
00748     for(size_t jc=0;jc<vdetIdItemList[ic].items.size();++jc){
00749       //scientific precision doesn't work in HDQMExpressionEvaluator...
00750       //sprintf(condCVal,"%g",vdetIdItemList[ic].values[jc]);
00751       sprintf(condCVal,"%f",vdetIdItemList[ic].values[jc]);
00752       sprintf(singleCondition,"%d%s%s",vdetIdItemList[ic].detid,fSep.c_str(),vdetIdItemList[ic].items[jc].c_str());
00753       //printf("dhidas %d  %s  %s\n",vdetIdItemList[ic].detid,fSep.c_str(),vdetIdItemList[ic].items[jc].c_str());
00754       //printf("dhidas %s %s\n", cConditions, singleCondition);
00755       char* fpos = strstr(cConditions,singleCondition);
00756       //printf("dhidas %s %s %i\n", fpos, condCVal, strlen(condCVal));
00757       strncpy(fpos,condCVal,strlen(condCVal));
00758       memset(fpos+strlen(condCVal),' ',strlen(singleCondition)-strlen(condCVal));
00759       //std::cout << "fpos " << fpos << " len condCVal " << strlen(condCVal) << " strlen(singleCondition) " << strlen(singleCondition) << " len cConditions " << strlen(cConditions)<<std::endl;
00760       //std::cout << "Conditions Replace: Condition " << singleCondition << " string changed in " << cConditions << std::endl;
00761     }
00762 
00763   std::string stringToEvaluate;
00764   char * pch;
00765   pch = strtok (cConditions," ");
00766   while (pch != NULL){
00767     stringToEvaluate.append(pch);
00768     pch = strtok (NULL, " ");
00769   } 
00770   //for(size_t i=0;i<strlen(cConditions);++i)
00771   // if(cConditions[i] != " ")
00772   //  stringToEvaluate.push_back(cConditions[i]);
00773 
00774   if(iDebug) {
00775     std::cout << "Conditions After SubStitution " << stringToEvaluate << std::endl;
00776   }
00777   TFormula Formula("condition", stringToEvaluate.c_str());
00778   resultdbl = Formula.Eval(0);
00779   if(iDebug) {
00780     std::cout << "Result " << resultdbl << std::endl;
00781   }
00782   if(!resultdbl) {
00783     return false;
00784   }
00785   return true;
00786 }
00787 
00788 void HDQMInspector::setItems(std::string itemD)
00789 {
00790   DetIdItemList detiditemlist;
00791   detiditemlist.detid=atol(itemD.substr(0,itemD.find(fSep)).c_str());
00792 
00793   std::string item=itemD.substr(itemD.find(fSep)+fSep.size());
00794   detiditemlist.items.push_back(item);
00795 
00796   if(iDebug)
00797     std::cout << "Found new item " << detiditemlist.items.back() << " for detid " << detiditemlist.detid << std::endl;
00798 
00799   if(item.find("mean")!=std::string::npos){
00800     detiditemlist.items.push_back(item.replace(item.find("mean"),4,"rms")); 
00801     if(iDebug)
00802       std::cout << "Found new item " << detiditemlist.items.back() << std::endl;
00803     detiditemlist.items.push_back(item.replace(item.find("rms"),3,"entries")); 
00804     if(iDebug)
00805       std::cout << "Found new item " << detiditemlist.items.back() << std::endl;
00806   }
00807   else if(item.find("landauPeak")!=std::string::npos){
00808     detiditemlist.items.push_back(item.replace(item.find("landauPeak"),10,"landauPeakErr")); 
00809     if(iDebug)
00810       std::cout << "Found new item " << detiditemlist.items.back() << std::endl;
00811   }
00812   else if(item.find("gaussMean")!=std::string::npos){
00813     detiditemlist.items.push_back(item.replace(item.find("gaussMean"),9,"gaussSigma")); 
00814     if(iDebug)
00815       std::cout << "Found new item " << detiditemlist.items.back() << std::endl;
00816   }
00817 
00818   if(vDetIdItemList_.size()) {
00819     if(vDetIdItemList_.back().detid==detiditemlist.detid) {
00820       vDetIdItemList_.back().items.insert(vDetIdItemList_.back().items.end(),detiditemlist.items.begin(),detiditemlist.items.end());
00821     } else {
00822       vDetIdItemList_.push_back(detiditemlist);
00823     }
00824   } else {
00825     vDetIdItemList_.push_back(detiditemlist);
00826   }
00827 
00828   return;
00829 }
00830 
00831 
00832 double HDQMInspector::findGraphMax(TGraphErrors* g)
00833 {
00834   // GetMaximum() doesn't work ....
00835   int n = g->GetN();
00836   double* y = g->GetY();
00837   int locmax = TMath::LocMax(n,y);
00838   return  y[locmax];
00839 }
00840 
00841 
00842 double HDQMInspector::findGraphMin(TGraphErrors* g)
00843 {
00844   // GetMinimum() doesn't work ....
00845   int n = g->GetN();
00846   double* y = g->GetY();
00847   int locmin = TMath::LocMin(n,y);
00848   return  y[locmin];
00849 }
00850 
00851