// author: Ionut Cristian Arsene // Date: 01/09/2010 #include #include using namespace std; #include #include #include #include #include #include #include #include #include #include #include #include #include #include "AliCFContainer.h" #include "AliDielectronCFdraw.h" /* This macro makes projections and saves histograms from a list of CF containers generated with the dielectron package. These histograms can later be used to calculate efficiencies. To use it, the following modifications are needed: 1) Modify the global variables listed below according to your needs. 2) Make projections by applying as many cut sets as needed on the CF containers. Call the FillHistograms() after each cut set. 3) To extract efficiencies use the ExtractEfficiencies() function where one needs to specify the indexes for the nominator and denominator histograms. The indexes are based on the CF step number, cut set number and histogram number as defined in the global variables below. */ // The CF variable indexes ------------------------------------------------ enum Variables { // create an enumeration item for every variable from your CF container kNothing = -1, // kNothing should be always here kPt = 0, kY, kThetaCS, kThetaHE, kM, kPairType, // kPhi, kLeg1_Pt, kLeg1_NclsTPC, kLeg1_Eta, //kLeg1_Phi, // kLeg1_TPC_nSigma_Electrons, // kLeg1_P, //kLeg2_Phi, // kLeg2_TPC_nSigma_Electrons, kLeg2_Pt, // kLeg2_P, kLeg2_NclsTPC, kLeg2_Eta, kNVariables // kNVariables should be always here! }; const Char_t* gkVarNames[kNVariables] = { // variable names to be put on histograms axes and titles "p_{T} [GeV/c]", "y", "cos #theta^{*}_{CS}", "cos #theta^{*}_{HE}", "M [GeV/c^{2}]", "Pair type (0=++; 1=+-; 2=--)", // "#phi(J/#Psi) [rad.]", //"#phi^{leg1}", // "TPC n #sigma electrons (leg1)", "p_{T}^{leg1} [GeV/c]", // "P^{leg1} [GeV/c]", "# TPC clusters (leg1)", "#eta^{leg1}", //"#phi^{leg2}", // "TPC n #sigma electrons (leg2)", "p_{T}^{leg2} [GeV/c]", // "P^{leg2} [GeV/c]", "# TPC clusters (leg2)" "#eta^{leg2}", }; Int_t gNbins[kNVariables]; // number of bins for every variable --> filled automatically Double_t* gBinLimits[kNVariables]; // bin limits for every variable --> filled automatically // ------------------------------------------------------------------------ // Put here all the CF steps of interest ---------------------------------- enum Steps { // step indexes in the CF containers to be analyzed kPureMC = 0, kESDSPDany = 2, kESDSPDfirst = 4, kESDv0SPDany = 6, kESDv0SPDfirst = 8, kFullSPDany = 10, kFullSPDfirst = 12, kNSteps = 7 // total number of steps (the number of steps above) }; const Int_t gkStepNumbers[kNSteps] = { // array with step indexes (all from the enumeration above) kPureMC, kESDSPDany, kESDSPDfirst, kESDv0SPDany, kESDv0SPDfirst, kFullSPDany, kFullSPDfirst }; const Char_t* gkStepNames[kNSteps][2] = {// names for each CF step {"PureMC", "Pure MC"}, // NOTE: short names go to histo names, long names go to titles {"ESDSPDany", "ESD track cuts, SPD any"}, {"ESDSPDfirst", "ESD track cuts, SPD first"}, {"ESDv0SPDany", "ESD track cuts, conv. cuts, SPD any"}, {"ESDv0SPDfirst", "ESD track cuts, conv. cuts, SPD first"}, {"FullSPDany", "All track cuts (with SPD any) and TPC-PID"}, {"FullSPDfirst", "All track cuts (with SPD first) and TPC-PID"} }; //------------------------------------------------------------------------ // Put here info about the cut sets for which projections will be made --- const Int_t gkNCutSets = 10*3; // number of cut sets for which histos will be filled const Char_t* gkCutSetNames[gkNCutSets][2] = { // short and long names for all the cut sets // baseline {"Ycut", "|y_{J/#Psi}|<0.9 & 01.0 GeV/c & Ncls_TPC>70"}, {"Ycut1LegsFull", "|y_{J/#Psi}|<0.3 & 01.0 GeV/c & Ncls_TPC>70"}, {"Ycut2LegsFull", "0.31.0 GeV/c & Ncls_TPC>70"}, {"Ycut3LegsFull", "-0.91.0 GeV/c & Ncls_TPC>70"}, {"YcutPt1LegsFull", "|y_{J/#Psi}|<0.9 & 01.0 GeV/c & Ncls_TPC>70"}, {"YcutPt2LegsFull", "|y_{J/#Psi}|<0.9 & 1.01.0 GeV/c & Ncls_TPC>70"}, {"YcutPt3LegsFull", "|y_{J/#Psi}|<0.9 & 2.01.0 GeV/c & Ncls_TPC>70"}, {"YcutPt4LegsFull", "|y_{J/#Psi}|<0.9 & 3.01.0 GeV/c & Ncls_TPC>70"}, {"YcutPt5LegsFull", "|y_{J/#Psi}|<0.9 & 5.01.0 GeV/c & Ncls_TPC>70"}, {"YcutPt6LegsFull", "|y_{J/#Psi}|<0.9 & 7.01.0 GeV/c & Ncls_TPC>70"}, // track cuts + cut on signal integration range {"YcutMcutLegsFull", "|y_{J/#Psi}|<0.9 & 01.0 GeV/c & Ncls_TPC>70"}, {"Ycut1McutLegsFull", "|y_{J/#Psi}|<0.3 & 01.0 GeV/c & Ncls_TPC>70"}, {"Ycut2McutLegsFull", "0.31.0 GeV/c & Ncls_TPC>70"}, {"Ycut3McutLegsFull", "-0.91.0 GeV/c & Ncls_TPC>70"}, {"YcutPt1McutLegsFull", "|y_{J/#Psi}|<0.9 & 01.0 GeV/c & Ncls_TPC>70"}, {"YcutPt2McutLegsFull", "|y_{J/#Psi}|<0.9 & 1.01.0 GeV/c & Ncls_TPC>70"}, {"YcutPt3McutLegsFull", "|y_{J/#Psi}|<0.9 & 2.01.0 GeV/c & Ncls_TPC>70"}, {"YcutPt4McutLegsFull", "|y_{J/#Psi}|<0.9 & 3.01.0 GeV/c & Ncls_TPC>70"}, {"YcutPt5McutLegsFull", "|y_{J/#Psi}|<0.9 & 5.01.0 GeV/c & Ncls_TPC>70"}, {"YcutPt6McutLegsFull", "|y_{J/#Psi}|<0.9 & 7.01.0 GeV/c & Ncls_TPC>70"} }; // ----------------------------------------------------------------------- // Put here info about the histograms to be filled ----------------------- const Int_t gkNhistos = 3; // how many histograms for every (step,cut set) combination const Char_t* gkHistoNames[gkNhistos][2] = { // short and long names of the histograms {"pt","p_{T}(J/#Psi)"}, // NOTE: short names go to the histo name, long name goes to title // {"y","y(J/#Psi)"}, // {"pty","p_{T} vs y(J/#Psi)"}, // {"phi","#phi(J/#Psi) [rad.]"}, //{"m","e^{+}e^{-} invariant mass"}, {"ThetaCS","cos #theta^{*}_{CS}"}, {"ThetaHE","cos #theta^{*}_{HE}"} // {"Minv", "Invariant mass"} }; const Int_t gkDims[gkNhistos][4] = { // dimensions and variables for histograms // ndim xVar yVar zVar {1, kPt, kNothing, kNothing}, // pt dependence // {1, kY, kNothing, kNothing}, // y dependence // {2, kY, kPt, kNothing}, // pt,y dependence // {1, kPhi, kNothing, kNothing}, // phi dependence // {1, kM, kNothing, kNothing}, // inv. mass dependence {1, kThetaCS, kNothing, kNothing}, // cos theta* CS dependence {1, kThetaHE, kNothing, kNothing} // cos theta* HE dependence //{1, kM, kNothing, kNothing} // invariant mass }; // ----------------------------------------------------------------------- // ******************************************************************************** // Define here all the efficiencies you want (if any) // Efficiency = (nominator histogram)/(denominator histogram) // A histogram is defined by its step,cut set, and number defined according the // global variables above // ******************************************************************************** const Int_t gkNeffs = 20*3*5; const Int_t gkEffs[gkNeffs][6] = { //nominator: Step Cut Histo | denominator: Step Cut Histo comment // full corrections, pt dependence { 5, 10, 0, 0, 0, 0 }, // full correction, SPD any -0.9=offset+howMany) break; cout << "=================== run " << run << " ============================" << endl; ProjectAll(Form("%s/%s/listCF.txt", pattern, readString), Form("%s/%s/Projections.root",pattern, readString), 100, 0); runCounter++; } } //_______________________________________________________________________________________ void ProjectAll(const Char_t* inputList, const Char_t* outfilename, Int_t howMany, Int_t offset) { // // Main function for making projections from a list of CF containers (inputList). // The resulting histograms are placed in the ROOT file specified by outfilename // // Modify the global variables above to match your requirements // // open the output file TFile *outFile = new TFile(outfilename,"RECREATE"); // ----------------------------------------------------------------------------- // copy the current ExtractEfficiency macro in the same dir as the output file TString outStr = ""; outStr += outfilename; outStr.ReplaceAll(".root", "_ExtractEfficienciesMacro.C"); gSystem->Exec(Form("cp ExtractEfficiencies.C %s", outStr.Data())); // --------------------------------------------------------------------------- // create the container for all the histograms --------------------- TObjArray *histoArray=new TObjArray(); histoArray->SetOwner(); //------------------------------------------------------------------ // loop over all CF files, project and merge ----------------------- ifstream input; input.open(inputList); Int_t currentFile=0; Bool_t firstTime = kTRUE; while(input.good()) { Char_t readString[256]; input.getline(readString, 256, '\n'); // get a chunk TString readStringString = readString; if(readStringString[0]!='/') continue; if(!readStringString.Contains(".root")) continue; if(currentFile=offset+howMany) break; cout << "file: " << readString << endl; AliDielectronCFdraw *cf=new AliDielectronCFdraw(readString); AliCFContainer* cont=cf->GetCFContainer(); // **************************************************************************** // Below apply all your cut sets then call the FillHistograms() function // Don't forget to increment the "currentCutSet" variable after every cut set // **************************************************************************** // pair type (0 ++, 1 +-, 2 --) ---------------------------------- cf->SetRangeUser("PairType", 1.1, 1.9); // Pair rapidity cut cf->SetRangeUser("Y", -0.899, 0.899); cf->SetRangeUser("Pt", 0.001, 9.999); Int_t currentCutSet = 0; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi -0.3SetRangeUser("Y", -0.299, 0.299); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 0.3SetRangeUser("Y", 0.301, 0.899); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi -0.9SetRangeUser("Y", -0.899, -0.301); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 0SetRangeUser("Y", -0.899, 0.899); cf->SetRangeUser("Pt", 0.001, 0.999); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 1.0SetRangeUser("Pt", 1.001, 1.999); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 2.0SetRangeUser("Pt", 2.001, 2.999); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 3.0SetRangeUser("Pt", 3.001, 4.999); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 5.0SetRangeUser("Pt", 5.001, 6.999); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 7.0SetRangeUser("Pt", 7.001, 9.999); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // Leg pseudo-rapidity cut --------------------------------------- cf->SetRangeUser("Pt", 0.001, 9.999); cf->SetRangeUser("Y", -0.899, 0.899); cf->SetRangeUser("Leg1_Eta", -0.899, 0.899); cf->SetRangeUser("Leg2_Eta", -0.899, 0.899); cf->SetRangeUser("Leg1_Pt", 1.001, 10.0); cf->SetRangeUser("Leg2_Pt", 1.001, 10.0); cf->SetRangeUser("Leg1_NclsTPC", 70.1, 160.0); cf->SetRangeUser("Leg2_NclsTPC", 70.1, 160.0); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi -0.3SetRangeUser("Y", -0.299, 0.299); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 0.3SetRangeUser("Y", 0.301, 0.899); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi -0.9SetRangeUser("Y", -0.899, -0.301); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 0SetRangeUser("Y", -0.899, 0.899); cf->SetRangeUser("Pt", 0.001, 0.999); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 1.0SetRangeUser("Pt", 1.001, 1.999); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 2.0SetRangeUser("Pt", 2.001, 2.999); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 3.0SetRangeUser("Pt", 3.001, 4.999); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 5.0SetRangeUser("Pt", 5.001, 6.999); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 7.0SetRangeUser("Pt", 7.001, 9.999); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 2.92SetRangeUser("Pt", 0.001, 9.999); cf->SetRangeUser("Y", -0.899, 0.899); cf->SetRangeUser("M", 2.9201, 3.1599); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi -0.3SetRangeUser("Y", -0.299, 0.299); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 0.3SetRangeUser("Y", 0.301, 0.899); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi -0.9SetRangeUser("Y", -0.899, -0.301); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 0SetRangeUser("Pt", 0.001, 0.999); cf->SetRangeUser("Y", -0.899, 0.899); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 1.0SetRangeUser("Pt", 1.001, 1.999); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 2.0SetRangeUser("Pt", 2.001, 2.999); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 3.0SetRangeUser("Pt", 3.001, 4.999); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 5.0SetRangeUser("Pt", 5.001, 6.999); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); // j/psi 7.0SetRangeUser("Pt", 7.001, 9.999); currentCutSet++; FillHistograms(histoArray, cont, currentCutSet, firstTime); currentFile++; firstTime = kFALSE; delete cont; delete cf; } // end loop over CF files outFile->cd(); histoArray->Write(); outFile->Close(); delete histoArray; return; } //_______________________________________________________________________________________ void ExtractEfficienciesMany(const Char_t* runList, const Char_t* pattern, const Char_t* outAscii, Int_t howMany, Int_t offset) { // // // // loop over all runs ----------------------- ifstream input; input.open(runList); Int_t runCounter = 0; TGraphErrors* trends[gkNeffs]; Double_t weightedEffs[gkNeffs]; Double_t weightedErrs[gkNeffs]; Int_t nPoints[gkNeffs]; Double_t nTotalEvents[gkNeffs]; for(Int_t iTrend=0; iTrendSetName(gkEffNames[iTrend][0]); trends[iTrend]->SetTitle(gkEffNames[iTrend][1]); weightedEffs[iTrend] = 0.0; weightedErrs[iTrend] = 0.0; nPoints[iTrend] = 0; nTotalEvents[iTrend] = 0; } TFile* file=0x0; TFile* normalizationFile=0x0; TNamed* object; while(input.good()) { Char_t readString[256]; input.getline(readString, 256, '\n'); // get a chunk TString runStr = readString; Int_t run = runStr.Atoi(); if(run<=0) continue; if(runCounter=offset+howMany) break; cout << "=================== run " << run << " ============================" << endl; TString periodStr; if(run<=117222) periodStr = "LHC10b.pass2"; if(run>117222 && run<=120829) periodStr = "LHC10c.pass2"; if(run>121000 && run<=126437) periodStr = "LHC10d.pass2"; Double_t nPhysicsEvents = 0; normalizationFile = TFile::Open(Form("/lustre/alice/train/V006.pp/2011-03-18_2242.6024/mergedRuns/pp/7TeV/%s/%d.ana/iarsene_normalization.root", periodStr.Data(), run)); cout << "# physics events = "; if(normalizationFile) { TObjArray *histos=(TObjArray*)normalizationFile->Get("iarsene_normalization"); TH1I* triggers=(TH1I*)histos->FindObject("TriggersHistogram"); nPhysicsEvents = triggers->GetBinContent(2); // PHYSICS events cout << nPhysicsEvents; normalizationFile->Close(); } else cout << " NOT FOUND"; cout << endl; ExtractEfficiencies(Form("%s/%s/Projections.root",pattern,readString), Form("%s/%s/Efficiencies.root",pattern,readString)); file = TFile::Open(Form("%s/%s/Efficiencies.root",pattern,readString)); if(file && !file->IsZombie()) { for(Int_t iTrend=0; iTrendGet(Form("%s_value",gkEffNames[iTrend][0])); if(!object) continue; Float_t eff = (TString(object->GetTitle())).Atof(); trends[iTrend]->SetPoint(nPoints[iTrend], run, eff); object = (TNamed*)file->Get(Form("%s_error",gkEffNames[iTrend][0])); if(!object) continue; Float_t err = (TString(object->GetTitle())).Atof(); trends[iTrend]->SetPointError(nPoints[iTrend], 0.0, err); weightedEffs[iTrend] += nPhysicsEvents*eff; weightedErrs[iTrend] += nPhysicsEvents*nPhysicsEvents*err*err; nTotalEvents[iTrend] += nPhysicsEvents; // cout << "trend " << iTrend << "; eff = " << eff << endl; nPoints[iTrend]+=1; } file->Close(); } if(normalizationFile) normalizationFile->Close(); runCounter++; } // write the efficiencies also in an ascii file ofstream asciiOut; asciiOut.open(outAscii); TFile *saveTrend = new TFile(Form("%s.trend.root", runList), "RECREATE"); TNamed *weightedFactors; TNamed *weightedErrors; TNamed *nEventsObject; for(Int_t iTrend=0; iTrendWrite(); weightedEffs[iTrend] /= nTotalEvents[iTrend]; weightedErrs[iTrend] = TMath::Sqrt(weightedErrs[gkNeffs])/nTotalEvents[iTrend]; weightedFactors = new TNamed(Form("%s_weighted", gkEffNames[iTrend][0]), Form("%f", weightedEffs[iTrend])); weightedErrors = new TNamed(Form("%s_weightedErr", gkEffNames[iTrend][0]), Form("%f", weightedErrs[iTrend])); weightedFactors->Write(); weightedErrors->Write(); nEventsObject = new TNamed(Form("TotalEvents_%s",gkEffNames[iTrend][0]), Form("%f",nTotalEvents[iTrend])); nEventsObject->Write(); // write a table into an ascii file --------------------------------- TString effNameStr(gkEffNames[iTrend][2]); // The array contains y,pt rapidity intervals for this efficiency, and/or other variables // Always, the first element of the array should be "any" or "first" TObjArray* array = effNameStr.Tokenize(","); if(array->GetEntries()<=1) continue; asciiOut << iTrend << "\t"; if(((TObjString*)array->At(0))->GetString()=="any") asciiOut << "1"; else if(((TObjString*)array->At(0))->GetString()=="first") asciiOut << "2"; for(Int_t iStr=1; iStrGetEntries(); iStr++) asciiOut << "\t" << ((TObjString*)array->At(iStr))->GetString().Data(); asciiOut << "\t " << weightedEffs[iTrend] << endl; } // At the end of the ascii file write the format and brief explanations asciiOut << endl; asciiOut << "# Format: efficiencyId SPD(1-any/2-first) yLow yHigh ptLow ptHigh efficiency" << endl; asciiOut << "# Efficiency descriptions (based on efficiencyId) : " << endl; for(Int_t iTrend=0; iTrendGetEntries()<=1) continue; asciiOut << "# " << iTrend << " - " << gkEffNames[iTrend][1] << endl; } saveTrend->Close(); } //_______________________________________________________________________________________ void ExtractEfficiencies(const Char_t* inputFilename, const Char_t* outfilename, const Char_t* numbersFile) { // // Main function to extract efficiencies // // Open the output file TFile *output = new TFile(outfilename, "RECREATE"); // --------------------------------------------------------------------------- // copy the current ExtractEfficiency macro in the same dir as the output file TString outStr = ""; outStr += outfilename; outStr.ReplaceAll(".root", "_ExtractEfficienciesMacro.C"); gSystem->Exec(Form("cp ExtractEfficiencies.C %s", outStr.Data())); // --------------------------------------------------------------------------- // open the input file and read out all the histograms TFile *file = TFile::Open(inputFilename); if(!file || file->IsZombie()) return; TObjArray *effArray = new TObjArray(); effArray->SetOwner(); TH1* nominator; TH1* denominator; TNamed* effValue; TNamed* effError; ofstream asciiOut; if(numbersFile[0]!='\0') { asciiOut.open(numbersFile); asciiOut << "#Format: Name | Value | Abs. Error" << endl; } for(Int_t iEff=0; iEffGet(Form("%s_%s_%s",gkStepNames[gkEffs[iEff][0]][0], gkCutSetNames[gkEffs[iEff][1]][0], gkHistoNames[gkEffs[iEff][2]][0]))); denominator = (TH1D*)(file->Get(Form("%s_%s_%s",gkStepNames[gkEffs[iEff][3]][0], gkCutSetNames[gkEffs[iEff][4]][0], gkHistoNames[gkEffs[iEff][5]][0]))); if(!nominator) continue; if(!denominator) continue; nominator->GetYaxis()->SetTitle("efficiency"); } if(gkDims[gkEffs[iEff][2]][0]==2) { // 2-dim histos nominator = (TH2D*)(file->Get(Form("%s_%s_%s",gkStepNames[gkEffs[iEff][0]][0], gkCutSetNames[gkEffs[iEff][1]][0], gkHistoNames[gkEffs[iEff][2]][0]))); denominator = (TH2D*)(file->Get(Form("%s_%s_%s",gkStepNames[gkEffs[iEff][3]][0], gkCutSetNames[gkEffs[iEff][4]][0], gkHistoNames[gkEffs[iEff][5]][0]))); if(!nominator) continue; if(!denominator) continue; nominator->GetZaxis()->SetTitle("efficiency"); } if(gkDims[gkEffs[iEff][2]][0]==3) { // 3-dim histos nominator = (TH3D*)(file->Get(Form("%s_%s_%s",gkStepNames[gkEffs[iEff][0]][0], gkCutSetNames[gkEffs[iEff][1]][0], gkHistoNames[gkEffs[iEff][2]][0]))); denominator = (TH3D*)(file->Get(Form("%s_%s_%s",gkStepNames[gkEffs[iEff][3]][0], gkCutSetNames[gkEffs[iEff][4]][0], gkHistoNames[gkEffs[iEff][5]][0]))); if(!nominator) continue; if(!denominator) continue; } Double_t nomIntegral = nominator->Integral(); Double_t denomIntegral = denominator->Integral(); Double_t eff = (denomIntegral>0 ? nomIntegral/denomIntegral : 0); // Error calculation: take into account that nominator and denominator are correlated. // The nominator is a subset of denominator Double_t error = eff; if(nomIntegral>0 && denomIntegral>0) error = eff*TMath::Sqrt(TMath::Abs(denomIntegral-nomIntegral)/nomIntegral/denomIntegral); //nominator->Divide(denominator); TH1* ratio = DivideHists(nominator, denominator, gkDims[gkEffs[iEff][2]][0]); // cout << "efficiency = " << nomIntegral << " / " << denomIntegral << " = " // << eff << " +/- " << error << endl; TString title = gkEffNames[iEff][1]; title += Form(", integrated eff. = %f #pm %f", eff, error); ratio->SetTitle(title.Data()); ratio->SetName(gkEffNames[iEff][0]); effArray->Add(ratio); if(numbersFile[0]!='\0') { asciiOut << gkEffNames[iEff][0] << "\t" << eff << "\t" << error << endl; } effValue = new TNamed(Form("%s_value", gkEffNames[iEff][0]), Form("%f", eff)); effArray->Add(effValue); effError = new TNamed(Form("%s_error", gkEffNames[iEff][0]), Form("%f", error)); effArray->Add(effError); } output->cd(); effArray->Write(); output->Close(); file->Close(); asciiOut.close(); } //________________________________________________________________________________________ void DefineHistograms(TObjArray* histoArray, Int_t iCutSet) { // // Define the histograms to be filled for every step and a given cut set // This function is called by the FillHistograms() if the firstTime flag is set for(Int_t iStep=0; iStep3) return; TH1* histo; if(ndim==1) { histo = new TH1D(name, title, nbinsx, binsx); histo->Sumw2(); histo->GetXaxis()->SetTitle(xLabel); } if(ndim==2) { histo = new TH2D(name, title, nbinsx, binsx, nbinsy, binsy); histo->Sumw2(); histo->GetXaxis()->SetTitle(xLabel); histo->GetYaxis()->SetTitle(yLabel); } if(ndim==3) { histo = new TH3D(name, title, nbinsx, binsx, nbinsy, binsy, nbinsz, binsz); histo->Sumw2(); histo->GetXaxis()->SetTitle(xLabel); histo->GetYaxis()->SetTitle(yLabel); histo->GetZaxis()->SetTitle(zLabel); } histoArray->Add(histo); } //__________________________________________________________________________________________ void FillHistograms(TObjArray* histosArray, AliCFContainer* cont, Int_t currentCutSet, Bool_t firstTime) { // // Fill the user defined histograms for a given cut set // // If the firstTime flag is on then update the bin limits and call DefineHistograms() if(firstTime) { GetBinLimits(cont); DefineHistograms(histosArray, currentCutSet); } TH1* histo; for(Int_t iStep=0; iStepFindObject(Form("%s_%s_%s",gkStepNames[iStep][0], gkCutSetNames[currentCutSet][0], gkHistoNames[iHisto][0])); //histo->Add(cont->Project(gkDims[iHisto][1],gkStepNumbers[iStep])); //cout << "Histo: " << Form("%s_%s_%s",gkStepNames[iStep][0],gkCutSetNames[currentCutSet][0],gkHistoNames[iHisto][0]) << endl; //cout << "bin lims x: "; //for(Int_t iBinx=1; iBinx<=histo->GetXaxis()->GetNbins(); iBinx++) // cout << histo->GetXaxis()->GetBinLowEdge(iBinx) << " "; //cout << histo->GetXaxis()->GetBinUpEdge(histo->GetXaxis()->GetNbins()) << endl; histo->Add(cont->Project(gkStepNumbers[iStep],gkDims[iHisto][1])); } // fill 2-dim histos if(gkDims[iHisto][0]==2) { histo = (TH2D*)histosArray->FindObject(Form("%s_%s_%s",gkStepNames[iStep][0], gkCutSetNames[currentCutSet][0], gkHistoNames[iHisto][0])); //histo->Add(cont->Project(gkDims[iHisto][1], gkDims[iHisto][2], gkStepNumbers[iStep])); //cout << "Histo: " << Form("%s_%s_%s",gkStepNames[iStep][0],gkCutSetNames[currentCutSet][0],gkHistoNames[iHisto][0]) << endl; //cout << "bin lims x: "; //for(Int_t iBinx=1; iBinx<=histo->GetXaxis()->GetNbins(); iBinx++) // cout << histo->GetXaxis()->GetBinLowEdge(iBinx) << " "; //cout << histo->GetXaxis()->GetBinUpEdge(histo->GetXaxis()->GetNbins()) << endl; //cout << "bin lims y: "; //for(Int_t iBiny=1; iBiny<=histo->GetYaxis()->GetNbins(); iBiny++) // cout << histo->GetYaxis()->GetBinLowEdge(iBiny) << " "; //cout << histo->GetYaxis()->GetBinUpEdge(histo->GetYaxis()->GetNbins()) << endl; histo->Add(cont->Project(gkStepNumbers[iStep], gkDims[iHisto][1], gkDims[iHisto][2])); } // fill 3-dim histos if(gkDims[iHisto][0]==3) { histo = (TH3D*)histosArray->FindObject(Form("%s_%s_%s",gkStepNames[iStep][0], gkCutSetNames[currentCutSet][0], gkHistoNames[iHisto][0])); //histo->Add(cont->Project(gkDims[iHisto][1], gkDims[iHisto][2], gkDims[iHisto][3], gkStepNumbers[iStep])); histo->Add(cont->Project(gkStepNumbers[iStep], gkDims[iHisto][1], gkDims[iHisto][2], gkDims[iHisto][3])); } } // end loop over histos } // end loop over steps } //____________________________________________________________________________________________ void GetBinLimits(AliCFContainer* cont) { // // Extract the bin limits from the CF container // cout << "********* New cut set ****************" << endl; for(Int_t iVar=0; iVarGetVarTitle(iVar) << " : " << gNbins[iVar]; cout << "; range = " << gBinLimits[iVar][0] << " --> " << gBinLimits[iVar][gNbins[iVar]] << endl; //cout << "bin limits = "; //for(Int_t iBin=0; iBin<=gNbins[iVar]; iBin++) // cout << gBinLimits[iVar][iBin] << " "; //cout << endl; } } //________________________________________________________________________________________ Double_t* GetBinning(AliCFContainer* cont, Int_t variable, Int_t& nBins) { // // Get the number of bins and the bin limits for the projection of a given variable // //TH1D* tempHist = cont->Project(variable, kPureMC); TH1* tempHist = cont->Project(kPureMC, variable); nBins = tempHist->GetXaxis()->GetNbins(); Double_t* binLimits = new Double_t[nBins+1]; for(Int_t i=1; i<=nBins; i++) binLimits[i-1]=tempHist->GetXaxis()->GetBinLowEdge(i); binLimits[nBins] = tempHist->GetXaxis()->GetBinLowEdge(nBins) + tempHist->GetXaxis()->GetBinWidth(nBins); return binLimits; } //________________________________________________________________________________________ TH1* DivideHists(TH1* nominator, TH1* denominator, Int_t dimension) { // // divide 2 histograms with error propagation // TH1* ratio; if(dimension==3) { Int_t nBinsXNom = nominator->GetXaxis()->GetNbins(); Int_t nBinsXDenom = denominator->GetXaxis()->GetNbins(); Int_t nBinsYNom = nominator->GetYaxis()->GetNbins(); Int_t nBinsYDenom = denominator->GetYaxis()->GetNbins(); Int_t nBinsZNom = nominator->GetZaxis()->GetNbins(); Int_t nBinsZDenom = denominator->GetZaxis()->GetNbins(); if(nBinsXNom!=nBinsXDenom || nBinsYNom!=nBinsYDenom || nBinsZNom!=nBinsZDenom) { cout << "Trying to divide histograms with different number of bins" << endl; return 0x0; } ratio = (TH3D*)nominator->Clone("ratio"); ratio->Reset(); for(Int_t iXbin=1; iXbin<=nBinsXNom; ++iXbin) { for(Int_t iYbin=1; iYbin<=nBinsYNom; ++iYbin) { for(Int_t iZbin=1; iZbin<=nBinsZNom; ++iZbin) { Double_t countsN = nominator->GetBinContent(iXbin, iYbin, iZbin); Double_t countsD = denominator->GetBinContent(iXbin, iYbin, iZbin); if(countsN<1 || countsD<1) continue; // zero entry bins Double_t eff = countsN/countsD; Double_t error = eff*TMath::Sqrt(TMath::Abs(countsD-countsN)/countsN/countsD); ratio->SetBinContent(iXbin, iYbin, iZbin, eff); ratio->SetBinError(iXbin, iYbin, iZbin, error); } } } return ratio; } if(dimension==2) { Int_t nBinsXNom = nominator->GetXaxis()->GetNbins(); Int_t nBinsXDenom = denominator->GetXaxis()->GetNbins(); Int_t nBinsYNom = nominator->GetYaxis()->GetNbins(); Int_t nBinsYDenom = denominator->GetYaxis()->GetNbins(); if(nBinsXNom!=nBinsXDenom || nBinsYNom!=nBinsYDenom) { cout << "Trying to divide histograms with different number of bins" << endl; return 0x0; } ratio = (TH2D*)nominator->Clone("ratio"); ratio->Reset(); for(Int_t iXbin=1; iXbin<=nBinsXNom; ++iXbin) { for(Int_t iYbin=1; iYbin<=nBinsYNom; ++iYbin) { Double_t countsN = nominator->GetBinContent(iXbin, iYbin); Double_t countsD = denominator->GetBinContent(iXbin, iYbin); if(countsN<1 || countsD<1) continue; // zero entry bins Double_t eff = countsN/countsD; Double_t error = eff*TMath::Sqrt(TMath::Abs(countsD-countsN)/countsN/countsD); ratio->SetBinContent(iXbin, iYbin, eff); ratio->SetBinError(iXbin, iYbin, error); } } return ratio; } if(dimension==1) { Int_t nBinsXNom = nominator->GetXaxis()->GetNbins(); Int_t nBinsXDenom = denominator->GetXaxis()->GetNbins(); if(nBinsXNom!=nBinsXDenom) { cout << "Trying to divide histograms with different number of bins" << endl; return 0x0; } ratio = (TH1D*)nominator->Clone("ratio"); ratio->Reset(); for(Int_t iXbin=1; iXbin<=nBinsXNom; ++iXbin) { Double_t countsN = nominator->GetBinContent(iXbin); Double_t countsD = denominator->GetBinContent(iXbin); if(countsN<1 || countsD<1) continue; // zero entry bins Double_t eff = countsN/countsD; Double_t error = eff*TMath::Sqrt(TMath::Abs(countsD-countsN)/countsN/countsD); ratio->SetBinContent(iXbin, eff); ratio->SetBinError(iXbin, error); } return ratio; } return 0x0; }