CMS 3D CMS Logo

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