File indexing completed on 2024-04-06 11:56:30
0001
0002
0003
0004
0005
0006 #include "GFOverlay.h"
0007 #include <TError.h>
0008 #include <TFile.h>
0009 #include <TList.h>
0010 #include <TObjArray.h>
0011 #include <TString.h>
0012 #include <TObjString.h>
0013 #include <TKey.h>
0014 #include <TH1.h>
0015 #include "GFUtils/GFHistManager.h"
0016
0017 #include <iostream>
0018
0019 #include <string.h>
0020
0021
0022 GFOverlay::GFOverlay(const char *fileLegendList, Option_t *option) :
0023 fHistMan(new GFHistManager), fLayer(0),
0024 fFiles(), fLegends(),
0025 fNormalise(TString(option).Contains("norm", TString::kIgnoreCase)),
0026 fSummaries(TString(option).Contains("sumperdir", TString::kIgnoreCase)),
0027 fDirNames(), fSkipDirNames(), fHistNames(), fSkipHistNames()
0028 {
0029 if (fNormalise) ::Info("GFOverlay", "Normalising hists.");
0030 if (fSummaries) ::Info("GFOverlay", "Add summary hists for each directory.");
0031
0032 fFiles.SetOwner();
0033 fLegends.SetOwner();
0034
0035 const TString opt(option);
0036
0037
0038 fDirNames = this->FindAllBetween(opt, "name(", ")");
0039 TObjArray tmp(this->FindAllBetween(opt, "nameDir(", ")"));
0040 fDirNames.AddAll(&tmp);
0041 fDirNames.SetOwner();
0042 for (Int_t iN = 0; iN < fDirNames.GetEntriesFast(); ++iN) {
0043 ::Info("GFOverlay", "Use only directories containing '%s'.", fDirNames[iN]->GetName());
0044 }
0045
0046 fHistNames = this->FindAllBetween(opt, "name(", ")");
0047 tmp = this->FindAllBetween(opt, "nameHist(", ")");
0048 fHistNames.AddAll(&tmp);
0049 fHistNames.SetOwner();
0050 for (Int_t iN = 0; iN < fHistNames.GetEntriesFast(); ++iN) {
0051 ::Info("GFOverlay", "Use only hists containing '%s'.", fHistNames[iN]->GetName());
0052 }
0053
0054
0055 fSkipDirNames = this->FindAllBetween(opt, "skip(", ")");
0056 tmp = this->FindAllBetween(opt, "skipDir(", ")");
0057 fSkipDirNames.AddAll(&tmp);
0058 fSkipDirNames.SetOwner();
0059 for (Int_t iS = 0; iS < fSkipDirNames.GetEntriesFast(); ++iS) {
0060 ::Info("GFOverlay", "Skip directories containing '%s'.", fSkipDirNames[iS]->GetName());
0061 }
0062
0063 fSkipHistNames = this->FindAllBetween(opt, "skip(", ")");
0064 tmp = this->FindAllBetween(opt, "skipHist(", ")");
0065 fSkipHistNames.AddAll(&tmp);
0066 fSkipHistNames.SetOwner();
0067 for (Int_t iS = 0; iS < fSkipHistNames.GetEntriesFast(); ++iS) {
0068 ::Info("GFOverlay", "Skip hists containing '%s'.", fSkipHistNames[iS]->GetName());
0069 }
0070
0071 fHistMan->SameWithStats(true);
0072 fHistMan->SetLegendX1Y1X2Y2(.14, .72, .42, .9);
0073
0074 this->OpenFilesLegends(fileLegendList);
0075 this->Overlay(fFiles, fLegends);
0076
0077 fHistMan->SetNumHistsXY(3,2);
0078 fHistMan->Draw();
0079 }
0080
0081
0082 GFOverlay::~GFOverlay()
0083 {
0084 delete fHistMan;
0085 }
0086
0087
0088 TObjArray GFOverlay::FindAllBetween(const TString &text,
0089 const char *startStr, const char *endStr) const
0090 {
0091 TObjArray result;
0092
0093 if (text.Contains(startStr, TString::kIgnoreCase)) {
0094 Ssiz_t start = text.Index(startStr);
0095 while (start != kNPOS && start < text.Length()) {
0096 TString name = this->FindNextBetween(text, start, startStr, endStr);
0097 if (!name.IsNull()) {
0098 result.Add(new TObjString(name));
0099 start = text.Index(startStr, start + name.Length() + TString(endStr).Length());
0100 } else {
0101 break;
0102 }
0103 }
0104 }
0105
0106 return result;
0107 }
0108
0109
0110 TString GFOverlay::FindNextBetween(const TString &input, Ssiz_t startInd,
0111 const char *startStr, const char *endStr) const
0112 {
0113
0114
0115 TString string(input);
0116 const Ssiz_t start = string.Index(startStr, startInd, TString::kIgnoreCase)
0117 + (startStr ? strlen(startStr) : 0);
0118 if (start != kNPOS) {
0119 const Ssiz_t end = string.Index(endStr, start);
0120 if (end == kNPOS) {
0121 ::Error("GFOverlay::FindNextBetween", "Miss closing '%s' after '%s'", endStr, startStr);
0122 string = "";
0123 } else {
0124 string = string(start, end - start);
0125 }
0126 } else {
0127 string = "";
0128 }
0129
0130 return string;
0131 }
0132
0133
0134 bool GFOverlay::OpenFilesLegends(const char *fileLegendList)
0135 {
0136 bool allOk = true;
0137
0138 TObjArray *fileLegPairs = TString(fileLegendList).Tokenize(",");
0139 for (Int_t iF = 0; iF < fileLegPairs->GetEntriesFast(); ++iF) {
0140 TObjArray *aFileLegPair = TString(fileLegPairs->At(iF)->GetName()).Tokenize("=");
0141
0142 const char *legend = "";
0143 if (aFileLegPair->GetEntriesFast() >= 2) {
0144 if (aFileLegPair->GetEntriesFast() > 2) {
0145 ::Error("GFOverlay::OpenFilesLegends", "File-legend pair %s: %d (>2) '=' separated parts!",
0146 fileLegPairs->At(iF)->GetName(), aFileLegPair->GetEntriesFast());
0147 }
0148 legend = aFileLegPair->At(1)->GetName();
0149 } else if (aFileLegPair->GetEntriesFast() < 1) {
0150 continue;
0151 }
0152
0153 TFile *file = TFile::Open(aFileLegPair->At(0)->GetName());
0154 if (!file) {
0155 ::Error("GFOverlay::OpenFilesLegends", "Skip file-legend pair %s due to opening problems!",
0156 fileLegPairs->At(iF)->GetName());
0157 allOk = false;
0158 } else {
0159 fFiles.Add(file);
0160 fLegends.Add(new TObjString(legend));
0161 }
0162 delete aFileLegPair;
0163 }
0164
0165 delete fileLegPairs;
0166 return allOk;
0167 }
0168
0169
0170 void GFOverlay::Overlay(const TObjArray &dirs, const TObjArray &legends)
0171 {
0172
0173
0174 TDirectory *dir1 = 0;
0175 for (Int_t iDir = 0; !dir1 && iDir < dirs.GetEntriesFast(); ++iDir) {
0176 dir1 = static_cast<TDirectory*>(dirs[iDir]);
0177 }
0178 if (!dir1) return;
0179
0180 const Int_t currentLayer = fLayer;
0181 fLayer += (fSummaries ? 2 : 1);
0182 std::vector<TH1*> meanHists, rmsHists;
0183
0184
0185
0186 UInt_t counter = 0;
0187 TIter nextKey(dir1->GetListOfKeys());
0188
0189
0190 TKey* key = NULL;
0191 while ((key = static_cast <TKey*> (nextKey()))) {
0192
0193 if (!fHistNames.IsEmpty() && !this->KeyContainsListMember(key->GetName(), fHistNames)
0194 && !fDirNames.IsEmpty() && !this->KeyContainsListMember(key->GetName(), fDirNames )) {
0195 continue;
0196 }
0197 if (this->KeyContainsListMember(key->GetName(), fSkipHistNames)
0198 && this->KeyContainsListMember(key->GetName(), fSkipDirNames)) {
0199 continue;
0200 }
0201
0202
0203 TObject *obj = key->ReadObj();
0204 if (!obj) continue;
0205 if (obj->InheritsFrom(TH1::Class())) {
0206 if (!fHistNames.IsEmpty() && !this->KeyContainsListMember(key->GetName(), fHistNames)) {
0207 continue;
0208 }
0209 if (this->KeyContainsListMember(key->GetName(), fSkipHistNames)) continue;
0210 } else if (obj->InheritsFrom(TDirectory::Class())) {
0211 if (!fDirNames.IsEmpty() && !this->KeyContainsListMember(key->GetName(), fDirNames)) {
0212 continue;
0213 }
0214 if (this->KeyContainsListMember(key->GetName(), fSkipDirNames)) continue;
0215 }
0216
0217 TObjArray hists(this->GetTypeWithNameFromDirs(TH1::Class(), key->GetName(), dirs));
0218 if (this->AddHistsAt(hists, legends, currentLayer, counter) > 0) {
0219 if (fSummaries) {
0220 this->CreateFillMeanRms(hists, currentLayer, dir1->GetName(), meanHists, rmsHists);
0221 }
0222 ++counter;
0223 }
0224
0225 TObjArray subDirs(this->GetTypeWithNameFromDirs(TDirectory::Class(), key->GetName(), dirs));
0226 if (subDirs.GetEntries()) {
0227 ::Info("GFOverlay::Overlay", "Key '%s' is directory to do recursion.", key->GetName());
0228 this->Overlay(subDirs, legends);
0229 }
0230 }
0231
0232
0233 for (unsigned int iMean = 0; iMean < meanHists.size(); ++iMean) {
0234 fHistMan->AddHistSame(meanHists[iMean], currentLayer + 1, 0, legends[iMean]->GetName());
0235 fHistMan->AddHistSame(rmsHists[iMean], currentLayer + 1, 1, legends[iMean]->GetName());
0236 }
0237 }
0238
0239
0240 bool GFOverlay::KeyContainsListMember(const TString &key, const TObjArray &list) const
0241 {
0242 for (Int_t i = 0; i < list.GetEntriesFast(); ++i) {
0243 if (key.Contains(list[i]->GetName())) return true;
0244 }
0245
0246 return false;
0247 }
0248
0249
0250 TObjArray GFOverlay::GetTypeWithNameFromDirs(const TClass *aType, const char *name,
0251 const TObjArray &dirs) const
0252 {
0253
0254
0255
0256
0257 TObjArray result(dirs.GetEntriesFast());
0258 for (Int_t iDir = 0; iDir < dirs.GetEntriesFast(); ++iDir) {
0259 TDirectory *aDir = static_cast<TDirectory*>(dirs[iDir]);
0260 TObject *obj = (aDir ? aDir->Get(name) : 0);
0261 if (obj && !obj->InheritsFrom(aType)) {
0262
0263 obj = 0;
0264 }
0265 result.Add(obj);
0266 }
0267
0268 return result;
0269 }
0270
0271
0272 Int_t GFOverlay::AddHistsAt(const TObjArray &hists, const TObjArray &legends, Int_t layer,Int_t pos)
0273 {
0274
0275
0276
0277 Int_t nHists = 0;
0278 for (Int_t iHist = 0; iHist < hists.GetEntriesFast(); ++iHist) {
0279 TH1 *hist = static_cast<TH1*>(hists[iHist]);
0280 if (!hist) continue;
0281
0282 if (fNormalise && hist->GetEntries()) {
0283 hist->Scale(1./hist->GetEntries());
0284 }
0285
0286 fHistMan->AddHistSame(hist, layer, pos, (legends[iHist] ? legends[iHist]->GetName() : 0));
0287 ++nHists;
0288 }
0289
0290 return nHists;
0291 }
0292
0293
0294 void GFOverlay::CreateFillMeanRms(const TObjArray &hists, Int_t layer, const char *dirName,
0295 std::vector<TH1*> &meanHists, std::vector<TH1*> &rmsHists) const
0296 {
0297
0298
0299 if (hists.IsEmpty()) return;
0300 TH1 *h1 = 0;
0301 for (Int_t iH = 0; !h1 && iH < hists.GetEntriesFast(); ++iH) {
0302 h1 = static_cast<TH1*>(hists[iH]);
0303 }
0304 if (!h1 || h1->GetDimension() > 1) return;
0305
0306 if (meanHists.empty()) {
0307 const Float_t min = h1->GetXaxis()->GetXmin()/3.;
0308 const Float_t max = h1->GetXaxis()->GetXmax()/3.;
0309 const Int_t nBins = h1->GetNbinsX()/2;
0310 for (Int_t iHist = 0; iHist < hists.GetEntriesFast(); ++iHist) {
0311 TH1 *hMean = new TH1F(Form("mean%d_%d", layer, iHist), Form("%s: mean", dirName),
0312 nBins, min, max);
0313 meanHists.push_back(hMean);
0314 TH1 *hRms = new TH1F(Form("rms%d_%d", layer, iHist), Form("%s: RMS", dirName),
0315 nBins, 0., max);
0316 rmsHists.push_back(hRms);
0317 }
0318 }
0319
0320
0321 for (Int_t iHist = 0; iHist < hists.GetEntriesFast(); ++iHist) {
0322 TH1 *h = static_cast<TH1*>(hists[iHist]);
0323 if (!h) continue;
0324 meanHists[iHist]->Fill(h->GetMean());
0325 rmsHists[iHist]->Fill(h->GetRMS());
0326 }
0327 }