File indexing completed on 2026-10-15 08:17:26
0001 #ifndef FINALIZEQA_H
0002 #define FINALIZEQA_H
0003
0004
0005
0006
0007
0008 #include <TCanvas.h>
0009 #include <TPad.h>
0010 #include <TLatex.h>
0011 #include <TLegend.h>
0012 #include <TLine.h>
0013 #include <TBox.h>
0014 #include <TGraph.h>
0015 #include <TH1D.h>
0016 #include <TH2D.h>
0017 #include <TKey.h>
0018 #include <TNamed.h>
0019 #include <TParameter.h>
0020 #include <TTree.h>
0021 #include <TDatime.h>
0022 #include <TObjString.h>
0023 #include <TObjArray.h>
0024 #include <TSystem.h>
0025 #include <TFile.h>
0026 #include <TH1F.h>
0027 #include <functional>
0028 #include <map>
0029 #include <vector>
0030 #include <set>
0031
0032 namespace FinQA {
0033
0034
0035
0036 struct Info {
0037 int nchunks = 0, nwith = 0;
0038 TString runstring, settings, code, segveto, listdir;
0039 std::vector<TString> mismatch;
0040 std::map<TString,double> counts, cuts;
0041 bool have() const { return nwith>0; }
0042 double cut(const char* k, double def) const { auto it = cuts.find(k); return it==cuts.end() ? def : it->second; }
0043 double count(const char* k) const { auto it = counts.find(k); return it==counts.end() ? -1. : it->second; }
0044 };
0045
0046 inline Info ReadChunkInfo(const std::vector<TFile*> &fch){
0047 Info I; I.nchunks = fch.size();
0048 int nold = 0;
0049 for (size_t ic=0;ic<fch.size();ic++){
0050 TDirectory *d = fch[ic]->GetDirectory("info");
0051 if (!d){ ++nold; continue; }
0052 auto txt = [&](const char* n){ TNamed *o = (TNamed*)d->Get(n); TString t = o ? o->GetTitle() : ""; delete o; return t; };
0053 TString rs = txt("runstring"), st = txt("settings"), cd = txt("code"), sv = txt("segveto"), ls = gSystem->DirName(txt("list"));
0054 if (I.nwith==0){ I.runstring = rs; I.settings = st; I.code = cd; I.segveto = sv; I.listdir = ls; }
0055 else {
0056 TString w;
0057 if (rs!=I.runstring) w += " run string";
0058 if (st!=I.settings) w += " settings";
0059 if (cd!=I.code) w += " code";
0060 if (sv!=I.segveto) w += " segveto";
0061 if (w!="" && I.mismatch.size()<8) I.mismatch.push_back(Form("chunk %02zu differs from the first in:%s",ic,w.Data()));
0062 }
0063 TIter next(d->GetListOfKeys()); TKey *k;
0064 while ((k = (TKey*)next())){
0065 TString n = k->GetName();
0066 if (!n.BeginsWith("count_") && !n.BeginsWith("cut_")) continue;
0067 TParameter<double> *p = (TParameter<double>*)k->ReadObj(); if (!p) continue;
0068 if (n.BeginsWith("count_")) I.counts[n(6,n.Length())] += p->GetVal();
0069 else if (!I.cuts.count(n(4,n.Length()))) I.cuts[n(4,n.Length())] = p->GetVal();
0070 delete p;
0071 }
0072 ++I.nwith;
0073 }
0074 if (nold>0) I.mismatch.insert(I.mismatch.begin(),Form("%d of %d chunks have no info/ (made before 2026-10-12)",nold,I.nchunks));
0075 return I;
0076 }
0077
0078
0079 inline TH1* Sum(const std::vector<TFile*> &fch, const char* name){
0080 TH1 *s = 0;
0081 for (TFile *f : fch){
0082 TH1 *h = (TH1*)f->Get(name); if (!h) continue;
0083 if (!s){ s = (TH1*)h->Clone(Form("%s_fin",name)); s->SetDirectory(0); } else s->Add(h);
0084 delete h;
0085 }
0086 return s;
0087 }
0088
0089
0090 inline TLine* VLine(double x, int col, int style=2){
0091 gPad->Update();
0092 double y0 = gPad->GetUymin(), y1 = gPad->GetUymax();
0093 if (gPad->GetLogy()){ y0 = pow(10,y0); y1 = pow(10,y1); }
0094 TLine *l = new TLine(x,y0,x,y1); l->SetLineColor(col); l->SetLineStyle(style); l->SetLineWidth(2); l->Draw(); return l;
0095 }
0096 inline TBox* XBand(double x0, double x1, int col, double alpha=0.25){
0097 gPad->Update();
0098 double y0 = gPad->GetUymin(), y1 = gPad->GetUymax();
0099 if (gPad->GetLogy()){ y0 = pow(10,y0); y1 = pow(10,y1); }
0100 TBox *b = new TBox(x0,y0,x1,y1); b->SetFillColorAlpha(col,alpha); b->SetLineWidth(0); b->Draw(); return b;
0101 }
0102 inline TLegend* Leg(double x0=0.50, double y0=0.72, double x1=0.89, double y1=0.89){
0103 TLegend *l = new TLegend(x0,y0,x1,y1); l->SetBorderSize(0); l->SetFillColorAlpha(kWhite,0.85); l->SetTextSize(0.040); return l;
0104 }
0105
0106 inline void Pair(TH1 *h0, TH1 *h1, const char* title, const char* l0, const char* l1, bool logy, TLegend *lg){
0107 if (!h0 && !h1) return;
0108 TH1 *f = h0 ? h0 : h1;
0109 gPad->SetLogy(logy);
0110 f->SetTitle(title); f->SetStats(0);
0111 for (TH1 *h : {h0,h1}) if (h){ h->SetFillStyle(0); h->SetLineWidth(1); }
0112 if (h0){ h0->SetLineColor(kBlack); if (h1) h0->SetMaximum((logy ? 3. : 1.15)*std::max(h0->GetMaximum(),h1->GetMaximum())); h0->Draw("hist"); lg->AddEntry(h0,l0,"l"); }
0113 if (h1){ h1->SetLineColor(kRed); h1->Draw(h0 ? "hist same" : "hist"); lg->AddEntry(h1,l1,"l"); }
0114 }
0115
0116
0117 inline void TitlePage(TCanvas *c, const TString &set, const Info &I, const TString &finRunString, double fz, const char* finCode,
0118 const std::vector<int> &runs, double nevtPhys, const std::vector<TString> &pairNames, bool haveRef){
0119 c->Clear(); c->cd();
0120 TLatex t; t.SetNDC(); t.SetTextFont(42); t.SetTextAlign(13);
0121 double y = 0.965;
0122 auto line = [&](const TString &s, double sz, int col=kBlack, double dy=0.){ t.SetTextSize(sz); t.SetTextColor(col); t.DrawLatex(0.025,y,s.Data()); y -= (dy>0 ? dy : 1.45*sz); };
0123 TDatime now;
0124 line(Form("Corral Finalize: %s",set.Data()),0.034);
0125 line(Form("%s; Finalize run string \"%s\": physics |z_{vtx}| < %.0f cm; Finalize code %s",now.AsSQLString(),finRunString.Data(),fz,finCode),0.0145);
0126 TString rl; for (int r : runs) rl += Form(" %d",r);
0127 line(Form("%d chunks (%s), runs:%s",I.nchunks,I.listdir!="" ? I.listdir.Data() : Form("lists/%s",set.Data()),rl.Data()),0.0145);
0128 if (!I.have()){
0129 line("the chunks carry no info/ (made before 2026-10-12): run string, settings and code not recorded",0.0145,kRed+1);
0130 } else {
0131 line(Form("chunk run string \"%s\"; chunk code %s",I.runstring.Data(),I.code.Data()),0.0145);
0132 line(Form("segment veto: %s",I.segveto.Data()),0.0145);
0133 y -= 0.006;
0134 line("Events",0.018);
0135 auto cnt = [&](const char* k){ double v = I.count(k); return v<0 ? TString("?") : TString(Form("%.4g",v)); };
0136 line(Form(" rows read (vertices in the trees) %s; skipped: overlapping-TF copies %s, segment veto %s, isolated-vertex %s",
0137 cnt("rows_read").Data(),cnt("rows_skipped_tfdup").Data(),cnt("rows_skipped_segveto").Data(),cnt("rows_skipped_isovtx").Data()),0.0145);
0138 line(Form(" outside the crossing selection %s; events reaching the track loop (|z_{vtx}| < %.0f cm) %s",
0139 cnt("events_skipped_crossing").Data(),I.cut("vzmax",16.),cnt("events_tracks").Data()),0.0145);
0140 line(Form(" events in CalcRm with |z_{vtx}| < %.0f cm (the physics) %.4g",fz,nevtPhys),0.0145);
0141 y -= 0.006;
0142 line("Settings in force (identical in every chunk unless listed in red below)",0.018);
0143 TObjArray *a = I.settings.Tokenize("\n");
0144 for (int i=0;i<a->GetEntries();i++) line(TString(" ")+((TObjString*)a->At(i))->GetName(),0.0135);
0145 delete a;
0146 }
0147 if (!I.mismatch.empty()){ y -= 0.006; for (auto &m : I.mismatch) line(m,0.0145,kRed+1); }
0148 else if (I.have()) line(Form("all %d chunks agree on run string, settings and code",I.nchunks),0.0145,kGreen+3);
0149
0150 const double xr = 0.645;
0151 TLine *sep = new TLine(xr-0.012,0.03,xr-0.012,0.97); sep->SetNDC(); sep->SetLineColor(kGray); sep->Draw();
0152 t.SetTextColor(kBlack); t.SetTextSize(0.020); t.DrawLatex(xr,0.965,"Contents");
0153 const char* sec[] = {
0154 "Title page (this page)",
0155 "Events and vertices (summed over the chunks, cuts drawn)",
0156 "Tracks: kinematics, ntpc, DCA, acceptance",
0157 "dE/dx PID: KFP gates and the identified species",
0158 "V0 candidates: mass peaks (pair window shaded), p_{T}",
0159 "Versus DST segment (time order): events, vertices,",
0160 " tracks, DCA, TPC live fraction (segveto shaded)",
0161 "Versus DST segment: identified particles and V0s per event",
0162 "Per pair type, in the order below: overview, C(Q),",
0163 " resonance CF C(Q,p_{T}), crossing page",
0164 "Crossing-correction summary",
0165 haveRef ? "Pages vs the whole-dataset reference" : "(no whole-dataset reference: no reference pages)",
0166 "Crossing-loss (step 1b) pages per pair type, summaries",
0167 "N_{valid} maps" };
0168 double yr = 0.93; t.SetTextSize(0.0135);
0169 for (const char* s : sec){ t.DrawLatex(xr,yr,s); yr -= 0.021; }
0170 yr -= 0.010; t.SetTextSize(0.016); t.DrawLatex(xr,yr,Form("Pair types (%zu)",pairNames.size())); yr -= 0.026;
0171 const int ncol = 3, nrow = (pairNames.size()+ncol-1)/ncol;
0172 t.SetTextSize(0.0125);
0173 for (size_t k=0;k<pairNames.size();k++){
0174 int col = k/nrow, row = k%nrow;
0175 t.DrawLatex(xr+col*0.118, yr-row*0.0175, Form("%zu %s",k,pairNames[k].Data()));
0176 }
0177 }
0178
0179
0180
0181 inline void QAPages(TCanvas *c, const char* pdf, const std::vector<TFile*> &fch, const Info &I, double fz, std::vector<TH1*> &out){
0182 const double ptmin = I.cut("ptmin",0.1), ntpcc = I.cut("ntpc",18), dxy = I.cut("dcaxy",1.5), dz = I.cut("dcaz",1.5);
0183 const double vz = I.cut("vzmax",16), vxy = I.cut("vxymax",0.5);
0184 const int xsel = (int)I.cut("xingsel",3), nmask = (int)I.cut("siphimask",NSIPHIMASK_MAIN);
0185 std::map<TString,TH1*> got;
0186 auto S = [&](const char* n){ if (got.count(n)) return got[n]; TH1 *h = Sum(fch,n); if (h){ out.push_back(h); if (h->GetDimension()==1) h->SetFillStyle(0); } got[n] = h; return h; };
0187 const TString cutsrc = I.have() ? "" : " (default cuts: the chunks record none)";
0188
0189 c->Clear(); c->Divide(3,3,0.0001,0.0001);
0190 {
0191 TLegend *lg;
0192 const char* xyz[3] = {"x","y","z"};
0193 for (int k=0;k<3;k++){
0194 c->cd(1+k); lg = Leg();
0195 TH1 *h0 = S(Form("hvtx%s0",xyz[k])), *h1 = S(Form("hvtx%s",xyz[k]));
0196 Pair(h0,h1,Form("vertex %s%s;vertex %s (cm);events",xyz[k],cutsrc.Data(),xyz[k]),"all rows","accepted events",true,lg);
0197 if (k<2){ VLine(-vxy,kBlue); TLine *l = VLine(vxy,kBlue); lg->AddEntry(l,Form("|%s| < %.1f cm",xyz[k],vxy),"l"); }
0198 else { VLine(-vz,kBlue); TLine *l = VLine(vz,kBlue); lg->AddEntry(l,Form("|z| < %.0f cm (jobs)",vz),"l");
0199 TBox *b = XBand(-fz,fz,kGreen+1); lg->AddEntry(b,Form("|z| < %.0f cm (physics)",fz),"f"); }
0200 lg->Draw();
0201 }
0202 c->cd(4); lg = Leg();
0203 Pair(S("hntrk0"),S("hntrk"),"tracks per event;n tracks;events","all tracks (rows)","accepted tracks",true,lg); lg->Draw();
0204 c->cd(5); lg = Leg(0.40,0.72,0.89,0.89);
0205 { TH1 *h = S("hxing"); if (h){ gPad->SetLogy(1); h->SetTitle("crossing of the vertex, all rows;crossing;rows"); h->SetStats(0); h->SetLineColor(kBlack); h->Draw("hist");
0206 if (xsel==3){ TBox *b = XBand(corral::ZB_LO-0.5,corral::ZB_HI+0.5,kGreen+1); TBox *n = XBand(corral::XNEAR_LO-0.5,corral::XNEAR_HI+0.5,kWhite,1.);
0207 h->Draw("hist same"); lg->AddEntry(b,Form("ZB %d..%d (kept)",corral::ZB_LO,corral::ZB_HI),"f"); lg->AddEntry(n,Form("NearX0 %d..%d (out)",corral::XNEAR_LO,corral::XNEAR_HI),"f"); (void)n; }
0208 else lg->AddEntry((TObject*)0,xsel==0?"all crossings kept":xsel==1?"crossing 0 only":"NearX0 only","");
0209 lg->Draw(); } }
0210 c->cd(6); lg = Leg();
0211 { TH2 *h2 = (TH2*)S("hnvtxCR"); if (h2){ TH1D *p = h2->ProjectionY("hnvtxCR_py_fin",h2->GetXaxis()->FindBin(-fz+1e-6),h2->GetXaxis()->FindBin(fz-1e-6)); p->SetDirectory(0);
0212 gPad->SetLogy(1); p->SetTitle(Form("vertices per TF (events in CalcRm, |z| < %.0f cm);vertices per TF;events",fz)); p->SetStats(0); p->SetLineColor(kBlack);
0213 p->GetXaxis()->SetRangeUser(0.,std::min(199.,p->GetMean()*4+10)); p->Draw("hist"); lg->AddEntry(p,Form("mean %.2f",p->GetMean()),"l"); lg->Draw(); } }
0214 c->cd(7); gPad->SetRightMargin(0.13);
0215 { TH2 *h = (TH2*)S("hetazvtx"); if (h){ gPad->SetLogz(1); h->SetTitle("accepted tracks: #eta vs z_{vtx};z_{vtx} (cm);#eta"); h->SetStats(0); h->Draw("colz");
0216 VLine(-fz,kGreen+2,1); VLine(fz,kGreen+2,1); } }
0217 c->cd(8); lg = Leg(0.30,0.15,0.70,0.25);
0218 { TH2 *h2 = (TH2*)S("hnvtxCR"); if (h2){ TH1D *p = h2->ProjectionX("hnvtxCR_px_fin"); p->SetDirectory(0); p->SetTitle("z_{vtx} of the events reaching CalcRm;z_{vtx} (cm);events"); p->SetStats(0); p->SetLineColor(kBlack); p->SetMinimum(0); p->SetMaximum(1.15*p->GetMaximum()); p->Draw("hist");
0219 TBox *b = XBand(-fz,fz,kGreen+1); p->Draw("hist same"); lg->AddEntry(b,Form("physics |z| < %.0f cm",fz),"f"); lg->Draw(); } }
0220 c->cd(9);
0221 { TLatex t; t.SetNDC(); t.SetTextFont(42); t.SetTextSize(0.055); t.SetTextAlign(13); double y = 0.92;
0222 auto L = [&](const TString &s){ t.DrawLatex(0.05,y,s.Data()); y -= 0.075; };
0223 auto v = [&](const char* k){ double x = I.count(k); return x<0 ? TString("?") : TString(Form("%.4g",x)); };
0224 L("#bf{Event flow} (summed over the chunks)");
0225 L(Form("rows read: %s",v("rows_read").Data()));
0226 L(Form(" - overlapping-TF copies: %s",v("rows_skipped_tfdup").Data()));
0227 L(Form(" - segment veto: %s",v("rows_skipped_segveto").Data()));
0228 L(Form(" - isolated-vertex selection: %s",v("rows_skipped_isovtx").Data()));
0229 L(Form(" - crossing selection: %s",v("events_skipped_crossing").Data()));
0230 L(Form(" - vertex x, y, z cuts (rest)"));
0231 L(Form("events reaching the track loop: %s",v("events_tracks").Data()));
0232 TH2 *h2 = (TH2*)S("hnvtxCR");
0233 if (h2) L(Form("events in CalcRm, |z| < %.0f cm: %.4g",fz,h2->Integral(h2->GetXaxis()->FindBin(-fz+1e-6),h2->GetXaxis()->FindBin(fz-1e-6),0,-1))); }
0234 }
0235 c->cd(); c->Print(pdf);
0236
0237 c->Clear(); c->Divide(3,3,0.0001,0.0001);
0238 {
0239 TLegend *lg;
0240 c->cd(1); lg = Leg(); Pair(S("hpt0"),S("hpt"),"p_{T};p_{T} (GeV/c);tracks","all tracks","accepted",true,lg);
0241 { TLine *l = VLine(ptmin,kBlue); lg->AddEntry(l,Form("p_{T} > %.2f GeV/c",ptmin),"l"); } lg->Draw();
0242 c->cd(2); lg = Leg(0.35,0.15,0.75,0.32); Pair(S("heta0"),S("heta"),"#eta;#eta;tracks","all tracks","accepted",false,lg); lg->Draw();
0243 c->cd(3); lg = Leg(0.35,0.15,0.75,0.32); Pair(S("hphi0"),S("hphi"),"#phi at the vertex;#phi (rad);tracks","all tracks","accepted",false,lg);
0244 if (nmask>0){ TBox *b = 0; for (int k=0;k<nmask;k++) b = XBand(SIPHIMASK_LO[k]*M_PI/180.,SIPHIMASK_HI[k]*M_PI/180.,kGray+1,0.35); lg->AddEntry(b,"SiPhiMask (out)","f"); }
0245 lg->Draw();
0246 c->cd(4); lg = Leg(0.15,0.72,0.55,0.89); Pair(S("hntpc0"),S("hntpc"),"TPC clusters;ntpc;tracks","all tracks","accepted",false,lg);
0247 { TLine *l = VLine(ntpcc-0.5,kBlue); lg->AddEntry(l,Form("ntpc #geq %.0f",ntpcc),"l"); } lg->Draw();
0248 c->cd(5); lg = Leg(); Pair(S("hdcaxy0"),S("hdcaxy"),"DCA_{xy};dca_{xy} (cm);tracks","all tracks","accepted",true,lg);
0249 { VLine(-dxy,kBlue); TLine *l = VLine(dxy,kBlue); lg->AddEntry(l,Form("|dca_{xy}| < %.2f cm",dxy),"l"); } lg->Draw();
0250 c->cd(6); lg = Leg(); Pair(S("hdcaz0"),S("hdcaz"),"DCA_{z};dca_{z} (cm);tracks","all tracks","accepted",true,lg);
0251 { VLine(-dz,kBlue); TLine *l = VLine(dz,kBlue); lg->AddEntry(l,Form("|dca_{z}| < %.2f cm",dz),"l"); } lg->Draw();
0252 c->cd(7); lg = Leg(); Pair(S("hnmvtx0"),S("hnmvtx"),"MVTX clusters;nmvtx;tracks","all tracks","accepted",false,lg); lg->Draw();
0253 c->cd(8); gPad->SetRightMargin(0.13);
0254 { TH2 *h = (TH2*)S("hphieta"); if (h){ h->SetTitle("accepted tracks: #phi vs #eta;#eta;#phi (rad)"); h->SetStats(0); h->Draw("colz");
0255 if (nmask>0) for (int k=0;k<nmask;k++) for (double x : {SIPHIMASK_LO[k],SIPHIMASK_HI[k]}){ TLine *l = new TLine(-1.5,x*M_PI/180.,1.5,x*M_PI/180.); l->SetLineColor(kGray+2); l->SetLineStyle(2); l->Draw(); } } }
0256 c->cd(9); lg = Leg(0.15,0.72,0.55,0.89); Pair(S("hnintt0"),S("hnintt"),"INTT clusters;nintt;tracks","all tracks","accepted",false,lg); lg->Draw();
0257 }
0258 c->cd(); c->Print(pdf);
0259
0260 c->Clear(); c->Divide(2,2,0.0001,0.0001);
0261 {
0262 const char* sp[4] = {"pi","K","p","d"}; const int gcol[4] = {kBlue,kGreen+2,kRed,kGray+2};
0263 std::vector<TGraph*> g;
0264 TFile *fg = TFile::Open((CorralDir()+"dedxGates_KFP.root").Data());
0265 if (fg && !fg->IsZombie()) for (int i=0;i<4;i++) for (const char* s : {"lo","hi"}){
0266 TGraph *x = (TGraph*)fg->Get(Form("g_%s_%s",sp[i],s)); if (!x) continue; x = (TGraph*)x->Clone(); x->SetLineColor(gcol[i]); x->SetLineStyle(2); x->SetLineWidth(2); g.push_back(x); }
0267 if (fg) fg->Close();
0268 const char* nm[4] = {"hdedxKFPp","hdedxKFPp_id0","hdedxKFPp_id1","hdedxKFPp_id2"};
0269 const char* tt[4] = {"all accepted tracks","PID #pi","PID K","PID p"};
0270 for (int k=0;k<4;k++){
0271 c->cd(1+k); gPad->SetLogz(1); gPad->SetRightMargin(0.13);
0272 TH1 *h = S(nm[k]); if (!h) continue;
0273 h->SetTitle(Form("dE/dx (KFP) vs p, %s;p (GeV/c);dE/dx (KFP)",tt[k])); h->SetStats(0); h->Draw("colz");
0274 for (TGraph *x : g) x->Draw("L same");
0275 if (k==0){ TLegend *lg = Leg(0.55,0.65,0.86,0.89); for (int i=0;i<4;i++){ TLine *l = new TLine(); l->SetLineColor(gcol[i]); l->SetLineStyle(2); l->SetLineWidth(2); lg->AddEntry(l,Form("%s gate",sp[i]),"l"); } lg->Draw(); }
0276 }
0277 }
0278 c->cd(); c->Print(pdf);
0279
0280 c->Clear(); c->Divide(3,2,0.0001,0.0001);
0281 {
0282 const char* mn[3] = {"hKSmass","hLAmass","hALmass"}, *pn[3] = {"hKSpt","hLApt","hALpt"};
0283 const char* vn[3] = {"K^{0}_{S}","#Lambda","#bar{#Lambda}"};
0284 for (int k=0;k<3;k++){
0285 c->cd(1+k); TLegend *lg = Leg(0.55,0.72,0.89,0.89);
0286 TH1 *h = S(mn[k]); if (!h) continue;
0287 h->SetTitle(Form("%s candidates;mass (GeV/c^{2});candidates",vn[k])); h->SetStats(0); h->SetLineColor(kBlack); h->SetMinimum(0); h->Draw("hist");
0288 TBox *b = XBand(V0PEAK_MU[k]-V0PEAK_NSIG*V0PEAK_SIG[k],V0PEAK_MU[k]+V0PEAK_NSIG*V0PEAK_SIG[k],kGreen+1); h->Draw("hist same");
0289 lg->AddEntry(h,Form("%.4g candidates",h->Integral()),"l"); lg->AddEntry(b,Form("in pairs: #pm%.0f#sigma",V0PEAK_NSIG),"f");
0290 if (k>0){ TH1 *hc = S(Form("%s_clean",mn[k])); if (hc){ hc->SetLineColor(kRed); hc->Draw("hist same"); lg->AddEntry(hc,"worse-dau. DCA cut","l"); } }
0291 lg->Draw();
0292 c->cd(4+k); gPad->SetLogy(1);
0293 TH1 *p = S(pn[k]); if (p){ p->SetTitle(Form("%s candidates, all masses;p_{T} (GeV/c);candidates",vn[k])); p->SetStats(0); p->SetLineColor(kBlack); p->Draw("hist"); }
0294 }
0295 }
0296 c->cd(); c->Print(pdf);
0297 }
0298
0299
0300
0301 inline TTree* SegmentPages(TCanvas *c, const char* pdf, const std::vector<TFile*> &fch){
0302 struct Seg { int run, seg, chunk, veto, nraw, nevt, ntrk; float vtx, pt, ntpc, dxy, dz, live[3], nid[6], nv0[3]; };
0303 std::vector<Seg> v;
0304 bool haveQA = false;
0305 for (size_t ic=0;ic<fch.size();ic++){
0306 TTree *t = (TTree*)fch[ic]->Get("segCells"); if (!t) continue;
0307 const bool qa = t->GetBranch("nraw")!=0; haveQA |= qa;
0308 t->SetBranchStatus("*",0);
0309 Int_t run, seg, nevt, ntrk, nraw=0, veto=0, nid[6]={0}, nv0[3]={0}; Float_t nvtx=0, spt=0, sntpc=0, sxy=0, sz=0;
0310 for (const char* b : {"run","segment","nevt","ntrk"}) t->SetBranchStatus(b,1);
0311 t->SetBranchAddress("run",&run); t->SetBranchAddress("segment",&seg); t->SetBranchAddress("nevt",&nevt); t->SetBranchAddress("ntrk",&ntrk);
0312 if (qa){
0313 for (const char* b : {"nraw","veto","nvtx","sumpt","sumntpc","sumadcaxy","sumadcaz","nid","nv0"}) t->SetBranchStatus(b,1);
0314 t->SetBranchAddress("nraw",&nraw); t->SetBranchAddress("veto",&veto); t->SetBranchAddress("nvtx",&nvtx); t->SetBranchAddress("sumpt",&spt);
0315 t->SetBranchAddress("sumntpc",&sntpc); t->SetBranchAddress("sumadcaxy",&sxy); t->SetBranchAddress("sumadcaz",&sz);
0316 t->SetBranchAddress("nid",nid); t->SetBranchAddress("nv0",nv0);
0317 }
0318 for (Long64_t e=0;e<t->GetEntries();e++){
0319 t->GetEntry(e);
0320 Seg s; s.run = run; s.seg = seg; s.chunk = ic; s.veto = veto; s.nraw = qa ? nraw : -1; s.nevt = nevt; s.ntrk = ntrk;
0321 const double ne = nevt>0 ? nevt : 1, nt = ntrk>0 ? ntrk : 1;
0322 s.vtx = qa ? nvtx/ne : -1; s.pt = qa ? spt/nt : -1; s.ntpc = qa ? sntpc/nt : -1; s.dxy = qa ? sxy/nt : -1; s.dz = qa ? sz/nt : -1;
0323 for (int i=0;i<6;i++) s.nid[i] = qa ? nid[i]/ne : -1;
0324 for (int i=0;i<3;i++) s.nv0[i] = qa ? nv0[i]/ne : -1;
0325 for (int i=0;i<3;i++) s.live[i] = -1;
0326 v.push_back(s);
0327 }
0328 delete t;
0329 }
0330 if (v.empty()){ cout<<"corral::Finalize -- no segCells in the chunks: no vs-segment pages"<<endl; return 0; }
0331 {
0332 std::vector<TString> files; for (TFile *f : fch) files.push_back(f->GetName());
0333 SegLiveResult L = SegLiveFractions(files);
0334 for (auto &s : v){ auto it = L.live.find({s.run,s.seg}); if (it!=L.live.end()) for (int i=0;i<3;i++) s.live[i] = it->second[i]; }
0335 cout<<"corral::Finalize -- vs-segment pages: "<<v.size()<<" segments, live fraction for "<<L.live.size()<<" ("<<(L.feeMode?"FEE":"generic")<<" cells)"<<endl;
0336 }
0337 const int N = v.size();
0338
0339 auto panel = [&](std::vector<std::function<double(const Seg&)>> fs, std::vector<int> cols, std::vector<const char*> labs, const char* title, bool needEvt = true){
0340 std::vector<double> all;
0341 std::vector<TGraph*> g;
0342 for (size_t q=0;q<fs.size();q++){
0343 TGraph *x = new TGraph(); x->SetMarkerStyle(1); x->SetMarkerColor(cols[q]);
0344 for (int i=0;i<N;i++){ const Seg &s = v[i]; if (needEvt && s.nevt<=0) continue; double y = fs[q](s); if (y<0) continue; x->SetPoint(x->GetN(),i,y); all.push_back(y); }
0345 g.push_back(x);
0346 }
0347 if (all.empty()){ gPad->DrawFrame(0.,0.,1.,1.,""); TLatex t; t.SetNDC(); t.SetTextSize(0.06); t.DrawLatex(0.1,0.5,Form("%s: not in these chunks",title)); return; }
0348 std::sort(all.begin(),all.end());
0349 double lo = all[(size_t)(0.005*(all.size()-1))], hi = all[(size_t)(0.995*(all.size()-1))], d = hi-lo; if (d<=0) d = fabs(hi)*0.1+1e-6;
0350 lo -= 0.15*d; hi += 0.30*d;
0351 TH1F *fr = gPad->DrawFrame(-0.5,lo,N-0.5,hi,Form("%s;DST segment index (time order);",title));
0352 fr->GetXaxis()->SetLabelSize(0.045); fr->GetYaxis()->SetLabelSize(0.045);
0353
0354 TH1D *hv = new TH1D(Form("hveto_%p",(void*)fr),"",N,-0.5,N-0.5); hv->SetDirectory(0);
0355 int nv = 0; for (int i=0;i<N;i++){ hv->SetBinContent(i+1,lo); if (v[i].veto){ hv->SetBinContent(i+1,lo+0.08*(hi-lo)); ++nv; } }
0356 if (nv){ hv->SetFillColorAlpha(kGray+1,0.6); hv->SetLineWidth(0); hv->SetMinimum(lo); hv->Draw("hist same"); }
0357 for (int i=1;i<N;i++) if (v[i].run!=v[i-1].run){ TLine *l = new TLine(i-0.5,lo,i-0.5,hi); l->SetLineColor(kGray+2); l->SetLineStyle(2); l->Draw(); }
0358 for (auto x : g) x->Draw("P");
0359 TLegend *lg = Leg(0.12,0.80,0.89,0.89); lg->SetNColumns(std::min<int>(6,labs.size()+(nv?1:0)));
0360 for (size_t q=0;q<labs.size();q++){ TGraph *m = new TGraph(); m->SetMarkerStyle(20); m->SetMarkerColor(cols[q]); lg->AddEntry(m,labs[q],"p"); }
0361 if (nv){ lg->AddEntry(hv,Form("segveto (%d)",nv),"f"); }
0362 lg->Draw();
0363 };
0364 auto runLabels = [&](){ TLatex t; t.SetTextSize(0.035); t.SetTextColor(kGray+2); t.SetTextAlign(13); gPad->Update();
0365 int i0 = 0; for (int i=1;i<=N;i++) if (i==N || v[i].run!=v[i-1].run){ t.DrawLatex(i0+0.01*N,gPad->GetUymin()+0.20*(gPad->GetUymax()-gPad->GetUymin()),Form("%d",v[i0].run)); i0 = i; } };
0366
0367 c->Clear(); c->Divide(3,3,0.0001,0.0001);
0368 c->cd(1); panel({[](const Seg &s){ return s.nraw>0 ? (double)s.nevt/s.nraw : -1.; }},{kBlack},{"events / rows"},"events reaching the track loop / rows read"); runLabels();
0369 c->cd(2); panel({[](const Seg &s){ return (double)s.vtx; }},{kBlack},{"#LTvertices per TF#GT"},"vertices in the trigger frame (occupancy)");
0370 c->cd(3); panel({[](const Seg &s){ return s.nevt>0 ? (double)s.ntrk/s.nevt : -1.; }},{kBlack},{"#LTn accepted tracks#GT"},"accepted tracks per event");
0371 c->cd(4); panel({[](const Seg &s){ return s.ntrk>0 ? (double)s.pt : -1.; }},{kBlack},{"#LTp_{T}#GT"},"#LTp_{T}#GT of accepted tracks (GeV/c)");
0372 c->cd(5); panel({[](const Seg &s){ return s.ntrk>0 ? (double)s.ntpc : -1.; }},{kBlack},{"#LTntpc#GT"},"#LTntpc#GT of accepted tracks");
0373 c->cd(6); panel({[](const Seg &s){ return s.ntrk>0 ? (double)s.dxy : -1.; }},{kBlack},{"#LT|dca_{xy}|#GT"},"#LT|dca_{xy}|#GT of accepted tracks (cm)");
0374 c->cd(7); panel({[](const Seg &s){ return s.ntrk>0 ? (double)s.dz : -1.; }},{kBlack},{"#LT|dca_{z}|#GT"},"#LT|dca_{z}|#GT of accepted tracks (cm)");
0375 c->cd(8); panel({[](const Seg &s){ return (double)s.live[0]; }},{kBlack},{"all"},"TPC live fraction (FEE cells, segveto rule)");
0376 c->cd(9); panel({[](const Seg &s){ return (double)s.live[1]; },[](const Seg &s){ return (double)s.live[2]; }},{kBlue,kRed},{"South","North"},"TPC live fraction, South and North");
0377 c->cd(); c->Print(pdf);
0378
0379 c->Clear(); c->Divide(2,3,0.0001,0.0001);
0380 c->cd(1); panel({[](const Seg &s){ return (double)s.nid[0]; },[](const Seg &s){ return (double)s.nid[1]; }},{kRed,kBlue},{"#pi^{+}","#pi^{-}"},"identified pions per event"); runLabels();
0381 c->cd(2); panel({[](const Seg &s){ return (double)s.nid[2]; },[](const Seg &s){ return (double)s.nid[3]; }},{kRed,kBlue},{"K^{+}","K^{-}"},"identified kaons per event");
0382 c->cd(3); panel({[](const Seg &s){ return (double)s.nid[4]; },[](const Seg &s){ return (double)s.nid[5]; }},{kRed,kBlue},{"p","#bar{p}"},"identified (anti)protons per event");
0383 c->cd(4); panel({[](const Seg &s){ return (double)s.nv0[0]; }},{kBlack},{"K^{0}_{S}"},"K^{0}_{S} in the mass window per event");
0384 c->cd(5); panel({[](const Seg &s){ return (double)s.nv0[1]; },[](const Seg &s){ return (double)s.nv0[2]; }},{kRed,kBlue},{"#Lambda","#bar{#Lambda}"},"#Lambda, #bar{#Lambda} in the mass window per event");
0385 c->cd(6); panel({[](const Seg &s){ return (double)s.nevt; }},{kBlack},{"events"},"events per segment");
0386 c->cd(); c->Print(pdf);
0387
0388 TTree *t = new TTree("segQA","per DST segment, time order: QA means from the chunks' segCells (Finalize, README.md)");
0389 Seg s;
0390 t->Branch("run",&s.run,"run/I"); t->Branch("segment",&s.seg,"segment/I"); t->Branch("chunk",&s.chunk,"chunk/I"); t->Branch("veto",&s.veto,"veto/I");
0391 t->Branch("nraw",&s.nraw,"nraw/I"); t->Branch("nevt",&s.nevt,"nevt/I"); t->Branch("ntrk",&s.ntrk,"ntrk/I");
0392 t->Branch("vtx",&s.vtx,"vtx/F"); t->Branch("pt",&s.pt,"pt/F"); t->Branch("ntpc",&s.ntpc,"ntpc/F"); t->Branch("adcaxy",&s.dxy,"adcaxy/F"); t->Branch("adcaz",&s.dz,"adcaz/F");
0393 t->Branch("live",s.live,"live[3]/F"); t->Branch("nid",s.nid,"nid[6]/F"); t->Branch("nv0",s.nv0,"nv0[3]/F");
0394 for (auto &x : v){ s = x; t->Fill(); }
0395 t->SetDirectory(0);
0396 if (!haveQA) cout<<"corral::Finalize -- segCells without the QA branches (chunks made before 2026-10-12): events, tracks and live fraction only"<<endl;
0397 return t;
0398 }
0399
0400 }
0401 #endif