/** * Process a single eta bin * * @param measured Input collection of measured data * @param corrections Input collection of correction data * @param method Unfolding method to use * @param regParam Regularisation parameter * @param out Output directory. * * @return Stack of histograms or null */ THStack* ProcessBin(TCollection* measured, TCollection* corrections, UInt_t method, Double_t regParam, TDirectory* out) { Printf(" Processing %s ...", measured->GetName()); // Try to get the data TH1* inRaw = GetH1(measured, "rawDist"); TH1* inTruth = GetH1(corrections, "truth"); TH1* inTruthA = GetH1(corrections, "truthAccepted"); TH1* inTrgVtx = GetH1(corrections, "triggerVertex"); TH2* inResp = GetH2(corrections, "response"); if (!inRaw || !inTruth || !inTruthA || !inTrgVtx || !inResp) return 0; // Make output directory TDirectory* dir = out->mkdir(measured->GetName()); dir->cd(); // Copy the input to the output TH1* outRaw = static_cast<TH1*>(inRaw ->Clone("measured")); TH1* outTruth = static_cast<TH1*>(inTruth ->Clone("truth")); TH1* outTruthA = static_cast<TH1*>(inTruthA ->Clone("truthAccepted")); TH1* outTrgVtx = static_cast<TH1*>(inTrgVtx ->Clone("triggerVertex")); TH2* outResp = static_cast<TH2*>(inResp ->Clone("response")); // Make our response matrix RooUnfoldResponse matrix(0, 0, inResp); // Store regularization parameter Double_t r = regParam; RooUnfold::Algorithm algo = (RooUnfold::Algorithm)method; RooUnfold* unfolder = RooUnfold::New(algo, &matrix, inRaw, r); unfolder->SetVerbose(0); // Do the unfolding and get the result TH1* res = unfolder->Hreco(); res->SetDirectory(0); // Make a copy to store on the output TH1* outUnfold = static_cast<TH1*>(res->Clone("unfolded")); TString tit(outUnfold->GetTitle()); tit.ReplaceAll("Unfold Reponse matrix", "Unfolded P(#it{N}_{ch})"); outUnfold->SetTitle(tit); // Clone the unfolded results and divide by the trigger/vertex // bias correction TH1* outCorr = static_cast<TH1*>(outUnfold->Clone("corrected")); outCorr->Divide(inTrgVtx); tit.ReplaceAll("Unfolded", "Corrected"); outCorr->SetTitle(tit); // Now normalize the output to integral=1 TH1* hists[] = { outRaw, outUnfold, outCorr, 0 }; TH1** phist = hists; while (*phist) { TH1* h = *phist; if (h) { Double_t intg = h->Integral(1, h->GetXaxis()->GetXmax()); h->Scale(1. / intg, "width"); } phist++; } // And make ratios TH1* ratioTrue = static_cast<TH1*>(outCorr->Clone("ratioCorrTruth")); tit = ratioTrue->GetTitle(); tit.ReplaceAll("Corrected", "Corrected/MC 'truth'"); ratioTrue->SetTitle(tit); ratioTrue->Divide(outTruth); ratioTrue->SetYTitle("P_{corrected}(#it{N}_{ch})/P_{truth}(#it{N}_{ch})"); TH1* ratioAcc = static_cast<TH1*>(outUnfold->Clone("ratioUnfAcc")); tit = ratioAcc->GetTitle(); tit.ReplaceAll("Unfolded", "Unfolded/MC selected"); ratioAcc->SetTitle(tit); ratioAcc->Divide(outTruthA); ratioAcc->SetYTitle("P_{unfolded}(#it{N}_{ch})/P_{MC}(#it{N}_{ch})"); // Make a stack tit = measured->GetName(); tit.ReplaceAll("m", "-"); tit.ReplaceAll("p", "+"); tit.ReplaceAll("d", "."); tit.ReplaceAll("_", "<#it{#eta}<"); THStack* stack = new THStack("all", tit); stack->Add(outTruth, "E2"); stack->Add(outTruthA, "E2"); stack->Add(outRaw, "E1"); stack->Add(outUnfold, "E1"); stack->Add(outCorr, "E1"); dir->Add(stack); // Rest of the function is devoted to making the output look nice outRaw ->SetDirectory(dir); outTruth ->SetDirectory(dir); outTruthA->SetDirectory(dir); outTrgVtx->SetDirectory(dir); outResp ->SetDirectory(dir); outUnfold->SetDirectory(dir); outCorr ->SetDirectory(dir); outRaw ->SetMarkerStyle(20); // Measured is closed outTruth ->SetMarkerStyle(24); // MC is open outTruthA->SetMarkerStyle(24); // MC is open outTrgVtx->SetMarkerStyle(20); // Derived is closed outUnfold->SetMarkerStyle(20); // Derived is closed outCorr ->SetMarkerStyle(20); // Derived is closed outRaw ->SetMarkerSize(0.9); outTruth ->SetMarkerSize(1.6); outTruthA->SetMarkerSize(1.4); outTrgVtx->SetMarkerSize(1.0); outUnfold->SetMarkerSize(0.9); outCorr ->SetMarkerSize(1.0); outRaw ->SetMarkerColor(kColorMeasured); outTruth ->SetMarkerColor(kColorTruth); outTruthA->SetMarkerColor(kColorAccepted); outTrgVtx->SetMarkerColor(kColorTrgVtx); outUnfold->SetMarkerColor(kColorUnfolded); outCorr ->SetMarkerColor(kColorCorrected); outRaw ->SetFillColor(kColorError); outTruth ->SetFillColor(kColorError); outTruthA->SetFillColor(kColorError); outTrgVtx->SetFillColor(kColorError); outUnfold->SetFillColor(kColorError); outCorr ->SetFillColor(kColorError); outRaw ->SetFillStyle(0); outTruth ->SetFillStyle(1001); outTruthA->SetFillStyle(1001); outTrgVtx->SetFillStyle(0); outUnfold->SetFillStyle(0); outCorr ->SetFillStyle(0); outRaw ->SetLineColor(kBlack); outTruth ->SetLineColor(kBlack); outTruthA->SetLineColor(kBlack); outTrgVtx->SetLineColor(kBlack); outUnfold->SetLineColor(kBlack); outCorr ->SetLineColor(kBlack); // Legend TLegend* l = StackLegend(stack); l->AddEntry(outRaw, "Raw", "lp"); l->AddEntry(outTruth, "MC 'truth'", "fp"); l->AddEntry(outTruthA, "MC 'truth' accepted", "fp"); l->AddEntry(outUnfold, "Unfolded", "lp"); l->AddEntry(outCorr, "Corrected", "lp"); return stack; }
/** * Process a single type - i.e., one of <i>symmetric</i>, * <i>positive</i>, <i>negative</i>, or <i>other</i> - by looping * over all contained objects and call ProcessBin for each found * bin. * * @param measured Input collection of measured data * @param corrections Input collection of correction data * @param method Unfolding method to use * @param regParam Regularisation parameter * @param out Output directory. * @param sys Collision system * @param sNN Collision energy */ void ProcessType(TCollection* measured, TCollection* corrections, UInt_t method, Double_t regParam, TDirectory* out, UShort_t sys, UShort_t sNN) { Printf(" Processing %s ...", measured->GetName()); TDirectory* dir = out->mkdir(measured->GetName()); // Make some summary stacks THStack* allMeasured = new THStack("measured", "Measured P(#it{N}_{ch})"); THStack* allTruth = new THStack("truth", "MC 'truth' P(#it{N}_{ch})"); THStack* allTruthA = new THStack("truthAccepted", "MC 'truth' accepted P(#it{N}_{ch})"); THStack* allUnfolded = new THStack("unfolded", "Unfolded P(#it{N}_{ch})"); THStack* allCorrected = new THStack("corrected", "Corrected P(#it{N}_{ch})"); THStack* allRatio = (sys != 1 ? 0 : new THStack("ratios", "Ratios to other")); TMultiGraph* allALICE = (sys != 1 ? 0 : new TMultiGraph("alice", "ALICE Published")); TMultiGraph* allCMS = (sys != 1 ? 0 : new TMultiGraph("cms", "CMS Published")); // Loop over the list of objects. static TRegexp regex("[pm][0-9]d[0-9]*_[pm][0-9]d[0-9]*"); TIter next(measured); TObject* o = 0; Int_t i = 0; Double_t r = regParam; while ((o = next())) { // Go back to where we where dir->cd(); // if not a collection, don't bother if (!o->IsA()->InheritsFrom(TCollection::Class())) continue; // If it doesn't match our regular expression, don't bother TString n(o->GetName()); if (n.Index(regex) == kNPOS) { // Warning("ScanType", "%s in %s doesn't match eta range regexp", // n.Data(), real->GetName()); continue; } TCollection* mBin = static_cast<TCollection*>(o); TCollection* cBin = GetCollection(corrections, n.Data()); if (!cBin) continue; THStack* binS = ProcessBin(mBin, cBin, method, r, dir); if (!binS) continue; TH1* result = 0; Bin2Stack(binS, i, allMeasured, allTruth, allTruthA, allUnfolded, allCorrected, result); TGraph* alice = 0; TGraph* cms = 0; Other2Stack(o->GetName(), i, sNN, allALICE, allCMS, alice, cms); Ratio2Stack(i, result, alice, cms, allRatio); i++; } dir->Add(allMeasured); dir->Add(allTruth); dir->Add(allTruthA); dir->Add(allUnfolded); dir->Add(allCorrected); if (allALICE && allALICE->GetListOfGraphs()) { if (allALICE->GetListOfGraphs()->GetEntries() > 0) dir->Add(allALICE); else delete allALICE; } if (allCMS && allCMS->GetListOfGraphs()) { if (allCMS->GetListOfGraphs()->GetEntries() > 0) dir->Add(allCMS); else delete allCMS; } if (allRatio && allRatio->GetHists()) { if (allRatio->GetHists()->GetEntries() > 0) dir->Add(allRatio); else delete allRatio; } }