00001 #include "ForIA/D3PD/RootHistogrammer.hh"
00002
00003 #include "TH1D.h"
00004 #include "TH2D.h"
00005 #include "TH3D.h"
00006 #include "TFile.h"
00007 #include "TDirectory.h"
00008 #include "TProfile.h"
00009
00010 #include <iostream>
00011
00012 namespace ForIA {
00013
00014 RootHistogrammer::RootHistogrammer(const string &rootFileName) : IHistogrammer(), m_rootFileName(rootFileName), m_rootDir("/"){
00015 m_directories["/"] = &m_rootDir;
00016 TH1::AddDirectory(false);
00017 }
00018
00020 const string &RootHistogrammer::outputName()const{
00021 return m_rootFileName;
00022 }
00023
00025 void RootHistogrammer::bookHistogram1D(const string &path, const string &name,
00026 const string &title,
00027 int nBins, double xMin, double xMax,
00028 bool divideBinWidths){
00029
00030 if(xMin > xMax){
00031 throw BinError(xMin, xMax);
00032 }
00033
00034 TH1D *histo = new TH1D(name.c_str(), title.c_str(), nBins, xMin, xMax);
00035 histo->Sumw2();
00036 histo->ResetStats();
00037 histo->Reset();
00038
00039 try{
00040 addHisto(path, name, histo, divideBinWidths);
00041 }catch(DuplicateHistogramException er){
00042 delete histo;
00043 throw er;
00044 }
00045
00046 return;
00047 }
00048
00050 void RootHistogrammer::bookHistogram1D(const string &path, const string &name,
00051 const string &title, const vector<double> &bins,
00052 bool divideBinWidths){
00053
00054 TH1D *histo = new TH1D(name.c_str(), title.c_str(), bins.size() - 1, &(bins[0]));
00055 histo->Sumw2();
00056 histo->ResetStats();
00057 histo->Reset();
00058
00059 try{
00060 addHisto(path, name, histo, divideBinWidths);
00061 }catch(DuplicateHistogramException er){
00062 delete histo;
00063 throw er;
00064 }
00065
00066 return;
00067 }
00068
00070 void RootHistogrammer::bookProfile1D(const string &path, const string &name,
00071 const string &title, int nBins,
00072 double xMin, double xMax){
00073
00074 TProfile *prof = new TProfile(name.c_str(), title.c_str(), nBins, xMin, xMax);
00075 prof->Sumw2();
00076 try{
00077 addProfile(path, name, prof);
00078 }catch(DuplicateHistogramException er){
00079 delete prof;
00080 throw er;
00081 }
00082
00083 return;
00084 }
00085
00087 void RootHistogrammer::bookHistogram2D(const string &path, const string &name, const string &title,
00088 int nBinsX, double xMin, double xMax,
00089 int nBinsY, double yMin, double yMax,
00090 bool divideBinWidths){
00091
00092 if(xMin > xMax){
00093 throw BinError(xMin, xMax);
00094 }
00095
00096 if(yMin > yMax){
00097 throw BinError(xMin, xMax);
00098 }
00099
00100 TH2D *histo = new TH2D(name.c_str(), title.c_str(), nBinsX, xMin, xMax, nBinsY, yMin, yMax);
00101 histo->Sumw2();
00102
00103 try{
00104 addHisto(path, name, histo, divideBinWidths);
00105 }catch(DuplicateHistogramException er){
00106 delete histo;
00107 throw er;
00108 }
00109
00110 return ;
00111 }
00112
00114 void RootHistogrammer::bookHistogram2D(const string &path, const string &name, const string &title,
00115 const vector<double> &xbins, const vector<double> &ybins,
00116 bool divideBinWidths){
00117
00118 TH2D *histo = new TH2D(name.c_str(), title.c_str(),
00119 xbins.size() - 1, &(xbins[0]), ybins.size() - 1, &(ybins[0]));
00120 histo->Sumw2();
00121
00122 try{
00123 addHisto(path, name, histo, divideBinWidths);
00124 }catch(DuplicateHistogramException er){
00125
00126 delete histo;
00127 throw er;
00128 }
00129 return;
00130 }
00131
00133 void RootHistogrammer::bookHistogram3D(const string &path, const string &name, const string &title,
00134 int nBinsX, double xMin, double xMax,
00135 int nBinsY, double yMin, double yMax,
00136 int nBinsZ, double zMin, double zMax,
00137 bool divideBinWidths){
00138
00139 if(xMin > xMax){
00140 throw BinError(xMin, xMax);
00141 }
00142
00143 if(yMin > yMax){
00144 throw BinError(xMin, xMax);
00145 }
00146
00147 if(zMin > zMax){
00148 throw BinError(zMin, zMax);
00149 }
00150
00151 TH3D *histo = new TH3D(name.c_str(), title.c_str(),
00152 nBinsX, xMin, xMax,
00153 nBinsY, yMin, yMax,
00154 nBinsZ, zMin, zMax);
00155 histo->Sumw2();
00156
00157 try{
00158 addHisto(path, name, histo, divideBinWidths);
00159 }catch(DuplicateHistogramException er){
00160
00161 delete histo;
00162 throw er;
00163 }
00164 return;
00165 }
00167 void RootHistogrammer::fillHistogram1D(const string &path, const string &name,
00168 double value, double weight){
00169
00170 boost::unordered_map<string, Directory*>::iterator dir = m_directories.find(path);
00171
00172 if(dir == m_directories.end()) throw NoSuchHistogramException(path, name, this);
00173
00174 TH1D *histo = dir->second->histogram(name);
00175
00176 if(histo == 0) throw NoSuchHistogramException(path, name, this);
00177
00178 histo->Fill(value, weight);
00179
00180 return;
00181 }
00182
00184 void RootHistogrammer::fillProfile1D(const string &path, const string &name,
00185 double xVal, double yVal, double weight){
00186
00187 boost::unordered_map<string, Directory*>::iterator dir = m_directories.find(path);
00188
00189 if(dir == m_directories.end())throw NoSuchHistogramException(path, name, this);
00190
00191 TProfile *prof = dir->second->profile(name);
00192
00193 if(prof == 0) throw NoSuchHistogramException(path, name, this);
00194
00195 prof->Fill(xVal, yVal, weight);
00196
00197 return;
00198 }
00199
00201 void RootHistogrammer::fillHistogram2D(const string &path, const string &name,
00202 double xVal, double yVal, double weight){
00203 boost::unordered_map<string, Directory*>::iterator dir = m_directories.find(path);
00204 if(dir == m_directories.end()) throw NoSuchHistogramException(path, name, this);
00205
00206 TH2D *histo = dir->second->histogram2D(name);
00207 if(histo ==0) throw NoSuchHistogramException(path, name, this);
00208
00209 histo->Fill(xVal, yVal, weight);
00210 return;
00211 }
00212
00214 void RootHistogrammer::fillHistogram3D(const string &path, const string &name,
00215 double xVal, double yVal, double zVal,
00216 double weight){
00217
00218 boost::unordered_map<string, Directory*>::iterator dir = m_directories.find(path);
00219 if(dir == m_directories.end()) throw NoSuchHistogramException(path, name, this);
00220
00221 TH3D *histo = dir->second->histogram3D(name);
00222 if(histo ==0) throw NoSuchHistogramException(path, name, this);
00223
00224 histo->Fill(xVal, yVal, zVal, weight);
00225 return;
00226 }
00228 void RootHistogrammer::finalise(){
00229
00230
00231 for(boost::unordered_map<string, Directory*>::iterator dir = m_directories.begin();
00232 dir != m_directories.end(); ++dir){
00233
00234 for(Directory::iterator histo = dir->second->begin(); histo != dir->second->end(); ++histo){
00235
00236 if(histo->second == 0) throw NoSuchHistogramException(dir->first, histo->first);
00237
00238 if(! dir->second->doDivideBinWidths(histo->second)){
00239 std::cout<<"Histogram "<< histo->first<<" is not normalised by bin widths"<<std::endl;
00240 continue;
00241 }
00242
00243 double nEntries = histo->second->GetEntries();
00244
00245 int nBins = histo->second->GetNbinsX() +1;
00246 for(int bin=1; bin != nBins; ++bin){
00247 double area = histo->second->GetBinContent(bin);
00248 double width = histo->second->GetBinWidth(bin);
00249 double error = histo->second->GetBinError(bin) / width;
00250 double height = area / width;
00251 histo->second->SetBinContent(bin, height);
00252 histo->second->SetBinError(bin, error);
00253 }
00254
00255 histo->second->SetEntries(nEntries);
00256
00257 }
00258
00259 for(Directory::iterator2D histo = dir->second->begin2D(); histo != dir->second->end2D(); ++histo){
00260
00261 if(histo->second == 0) throw NoSuchHistogramException(dir->first, histo->first);
00262
00263 if(! dir->second->doDivideBinWidths(histo->second)){
00264 std::cout<<"Histogram "<< histo->first<<" is not normalised by bin widths"<<std::endl;
00265 continue;
00266 }
00267
00268 int nBinsX = histo->second->GetNbinsX() + 1;
00269 int nBinsY = histo->second->GetNbinsY() + 1;
00270
00271 double nEntries = histo->second->GetEntries();
00272
00273 for(int xbin =1; xbin != nBinsX; ++xbin){
00274 for(int ybin = 1; ybin != nBinsY; ++ybin){
00275 int bin = histo->second->GetBin(xbin, ybin);
00276 double volume = histo->second->GetBinContent(bin);
00277 double xWidth = histo->second->GetXaxis()->GetBinWidth(xbin);
00278 double yWidth = histo->second->GetYaxis()->GetBinWidth(ybin);
00279 double area = xWidth * yWidth;
00280 double height = volume / area;
00281 double error = histo->second->GetBinError(bin) / area;
00282 histo->second->SetBinContent(bin, height);
00283 histo->second->SetBinError(bin, error);
00284 }
00285 }
00286 histo->second->SetEntries(nEntries);
00287 }
00288
00289 for(Directory::iterator3D histo = dir->second->begin3D(); histo != dir->second->end3D(); ++histo){
00290
00291 if(histo->second == 0) throw NoSuchHistogramException(dir->first, histo->first);
00292
00293 if(! dir->second->doDivideBinWidths(histo->second)){
00294 std::cout<<"Histogram "<<histo->first<<" is not normalised by bin widths"<<std::endl;
00295 continue;
00296 }
00297
00298 int nBinsX = histo->second->GetNbinsX() + 1;
00299 int nBinsY = histo->second->GetNbinsY() + 1;
00300 int nBinsZ = histo->second->GetNbinsZ() + 1;
00301
00302 double nEntries = histo->second->GetEntries();
00303
00304 for(int xbin = 1; xbin != nBinsX; ++xbin){
00305 for(int ybin = 1; ybin != nBinsY; ++ybin){
00306 for(int zbin = 1; zbin != nBinsZ; ++zbin){
00307 int bin = histo->second->GetBin(xbin, ybin, zbin);
00308 double volume = histo->second->GetBinContent(bin);
00309 double xWidth = histo->second->GetXaxis()->GetBinWidth(bin);
00310 double yWidth = histo->second->GetYaxis()->GetBinWidth(bin);
00311 double zWidth = histo->second->GetZaxis()->GetBinWidth(bin);
00312 double dxdydz = xWidth * yWidth * zWidth;
00313 double height = volume / dxdydz;
00314 double error = histo->second->GetBinError(bin) / dxdydz;
00315 histo->second->SetBinContent(bin, height);
00316 histo->second->SetBinError(bin, error);
00317 }
00318 }
00319 }
00320 histo->second->SetEntries(nEntries);
00321 }
00322
00323 }
00324
00325 string filename = m_rootFileName + ".root";
00326
00327 TFile *file = new TFile(filename.c_str(), "RECREATE");
00328
00329 m_rootDir.write(file);
00330
00331 file->Close();
00332 return;
00333 }
00334
00336 void RootHistogrammer::normaliseHistogram1D(const string &path, const string &name, double norm){
00337 boost::unordered_map<string, Directory*>::iterator dir = m_directories.find(path);
00338
00339 if(dir == m_directories.end()) throw NoSuchHistogramException(path, name);
00340
00341 TH1D *histo = dir->second->histogram(name);
00342
00343 if(histo == 0) throw NoSuchHistogramException(path, name);
00344
00345 double intgl = histo->Integral();
00346 histo->Scale(norm / intgl);
00347
00348 return;
00349 }
00350
00352 void RootHistogrammer::scaleHistogram1D(const string &path, const string &name, double scale){
00353 boost::unordered_map<string, Directory*>::iterator dir = m_directories.find(path);
00354
00355 if(dir == m_directories.end()) throw NoSuchHistogramException(path, name);
00356
00357 TH1D *histo = dir->second->histogram(name);
00358
00359 if(histo == 0) throw NoSuchHistogramException(path, name);
00360
00361 histo->Scale(scale);
00362
00363 return;
00364 }
00366 void RootHistogrammer::normaliseHistogram2D(const string &path, const string &name, double norm){
00367 boost::unordered_map<string, Directory*>::iterator dir = m_directories.find(path);
00368
00369 if(dir == m_directories.end()) throw NoSuchHistogramException(path, name);
00370
00371 TH2D *histo = dir->second->histogram2D(name);
00372
00373 if(histo == 0) throw NoSuchHistogramException(path, name);
00374
00375 double intgl = histo->Integral();
00376 histo->Scale(norm / intgl);
00377
00378 return;
00379 }
00381 void RootHistogrammer::scaleHistogram2D(const string &path, const string &name, double scale){
00382 boost::unordered_map<string, Directory*>::iterator dir = m_directories.find(path);
00383
00384 if(dir == m_directories.end()) throw NoSuchHistogramException(path, name);
00385
00386 TH2D *histo = dir->second->histogram2D(name);
00387
00388 if(histo == 0) throw NoSuchHistogramException(path, name);
00389
00390 histo->Scale(scale);
00391
00392 return;
00393 }
00394
00396 void RootHistogrammer::showHistograms(std::ostream &out)const{
00397
00398 for(boost::unordered_map<string, Directory*>::const_iterator dir = m_directories.begin();
00399 dir != m_directories.end(); ++dir){
00400
00401 for(Directory::const_iterator histo = dir->second->begin();
00402 histo != dir->second->end(); ++histo){
00403 out<<dir->first<<histo->first<<std::endl;
00404 }
00405
00406 for(Directory::const_iterator2D histo = dir->second->begin2D();
00407 histo != dir->second->end2D(); ++histo){
00408 out<<dir->first<<histo->first<<std::endl;
00409 }
00410
00411 }
00412
00413 return;
00414 }
00415
00417 Directory::Directory(const string &name):
00418 m_name(name){
00419 stripSlash(m_name);
00420 }
00421
00423 const string &Directory::name()const{
00424 return m_name;
00425 }
00426
00428 pair<string, Directory*> Directory::addDirectory(string path){
00429
00430 stripSlash(path);
00431
00432 size_t pos = path.find("/");
00433
00434 string dirName;
00435
00436 bool addMore = false;
00437 string nextDir = "";
00438
00439 if(pos == string::npos){
00440 dirName = path;
00441 }else{
00442 dirName = path.substr(0, pos);
00443 nextDir = path.substr(pos);
00444 addMore = true;
00445 }
00446
00447 map<string, Directory>::iterator dir = m_dirs.find(dirName);
00448 if(dir==m_dirs.end()){
00449 Directory newDir(dirName);
00450 dir = m_dirs.insert(std::pair<string, Directory>(dirName, newDir)).first;
00451 }
00452
00453 string resultName = "/" + dirName;
00454 Directory *resultDir = &(dir->second);
00455
00456 if(addMore){
00457 pair<string, Directory*> added = dir->second.addDirectory(nextDir);
00458 resultName = resultName + added.first;
00459 resultDir = added.second;
00460 }
00461
00462 return pair<string, Directory*>(resultName, resultDir);
00463 }
00464
00466 string &Directory::stripSlash(string &path){
00467 string::iterator c = path.begin();
00468
00469 if(strncmp(&(*c), "/", 1) == 0){
00470 path.erase(c);
00471 }
00472
00473 return path;
00474 }
00475
00477 void Directory::addHistogram(const string &name, TH1D *histo, bool divideBinWidths){
00478
00479 if(m_histos[name]!=0) throw DuplicateHistogramException(this->name(), name);
00480
00481 m_histos[name] = histo;
00482
00483 if(!divideBinWidths){
00484 m_noDivideBinWidths.insert(histo);
00485 }
00486
00487 return;
00488 }
00489
00491 void Directory::addProfile(const string &name, TProfile *prof){
00492 if(m_profile1Ds[name]!=0) throw DuplicateHistogramException(this->name(), name);
00493
00494 m_profile1Ds[name] = prof;
00495
00496 return;
00497 }
00498
00500 void Directory::addHistogram(const string &name, TH2D *histo, bool divideBinWidths){
00501
00502 if(m_2dHistos[name] !=0) throw DuplicateHistogramException(this->name(), name);
00503
00504 m_2dHistos[name] = histo;
00505
00506 if(!divideBinWidths){
00507 m_noDivideBinWidths.insert(histo);
00508 }
00509
00510 return;
00511 }
00512
00513 void Directory::addHistogram(const string &name, TH3D *histo, bool divideBinWidths){
00514 if(m_3dHistos[name] != 0) throw DuplicateHistogramException(this->name(), name);
00515
00516 m_3dHistos[name] = histo;
00517
00518 if(!divideBinWidths){
00519 m_noDivideBinWidths.insert(histo);
00520 }
00521
00522 return;
00523 }
00524
00526 TH1D *Directory::histogram(const string &name){
00527 return m_histos[name];
00528 }
00529
00531 TProfile *Directory::profile(const string &name){
00532 return m_profile1Ds[name];
00533 }
00534
00536 TH2D *Directory::histogram2D(const string &name){
00537 return m_2dHistos[name];
00538 }
00539
00541 TH3D *Directory::histogram3D(const string &name){
00542 return m_3dHistos[name];
00543 }
00544
00546 bool Directory::doDivideBinWidths(const TH1 *histo)const{
00547
00548 if(m_noDivideBinWidths.count(histo) != 0) return false;
00549
00550 return true;
00551 }
00552
00554 bool Directory::write(TDirectory *dir) const{
00555
00556 if(dir==0) return false;
00557
00558 dir->cd();
00559
00560 for(boost::unordered_map<string, TH1D*>::const_iterator histo = m_histos.begin();
00561 histo != m_histos.end(); ++histo){
00562 histo->second->Write();
00563 }
00564
00565 for(boost::unordered_map<string, TProfile*>::const_iterator prof = m_profile1Ds.begin();
00566 prof != m_profile1Ds.end(); ++prof){
00567 prof->second->Write();
00568 }
00569
00570 for(boost::unordered_map<string, TH2D*>::const_iterator histo = m_2dHistos.begin();
00571 histo != m_2dHistos.end(); ++histo){
00572 histo->second->Write();
00573 }
00574
00575 for(boost::unordered_map<string, TH3D*>::const_iterator histo = m_3dHistos.begin();
00576 histo != m_3dHistos.end(); ++histo){
00577 histo->second->Write();
00578 }
00579
00580 for(map<string, Directory>::const_iterator dirIt = m_dirs.begin();
00581 dirIt != m_dirs.end(); ++dirIt){
00582 TDirectory *newDir = dir->mkdir(dirIt->second.m_name.c_str());
00583 dirIt->second.write(newDir);
00584 }
00585
00586 return true;
00587 }
00588
00589 }