|
| 1 | +import ROOT |
| 2 | +import os |
| 3 | +import argparse |
| 4 | + |
| 5 | +ROOT.gROOT.SetBatch(True) |
| 6 | +ROOT.gErrorIgnoreLevel = ROOT.kError |
| 7 | + |
| 8 | +parser = argparse.ArgumentParser(description="Overlay efficiency graphs from two aggregated ROOT files.") |
| 9 | +parser.add_argument('--f1', required=True, help='First input ROOT file (e.g., aggregated_NGT.root)') |
| 10 | +parser.add_argument('--l1', required=True, help='Legend label for first file (e.g., "NGT")') |
| 11 | +parser.add_argument('--f2', required=True, help='Second input ROOT file (e.g., aggregated_HTS.root)') |
| 12 | +parser.add_argument('--l2', required=True, help='Legend label for second file (e.g., "HTS TestStand")') |
| 13 | +parser.add_argument('--outdir', default='plots_comparison', help='Directory to save overlaid plots') |
| 14 | +args = parser.parse_args() |
| 15 | + |
| 16 | +# List of expected variables based on your first script |
| 17 | +VARIABLES = ["eta", "ptEB", "ptEE", "phiEB", "phiEE"] |
| 18 | + |
| 19 | +def get_variable_from_name(gname): |
| 20 | + """Extracts the variable name from the graph name for the X-axis label.""" |
| 21 | + for var in VARIABLES: |
| 22 | + if f"_{var}_" in gname: |
| 23 | + return var |
| 24 | + return "Variable" |
| 25 | + |
| 26 | +def main(): |
| 27 | + os.makedirs(args.outdir, exist_ok=True) |
| 28 | + |
| 29 | + file1 = ROOT.TFile.Open(args.f1) |
| 30 | + file2 = ROOT.TFile.Open(args.f2) |
| 31 | + |
| 32 | + if not file1 or file1.IsZombie() or not file2 or file2.IsZombie(): |
| 33 | + raise SystemExit("Error: Could not open one or both input ROOT files.") |
| 34 | + |
| 35 | + keys = file1.GetListOfKeys() |
| 36 | + #graph_names = [k.GetName() for k in keys if k.ReadObj().InheritsFrom("TGraphAsymmErrors")] |
| 37 | + graph_names = [k.GetName() for k in keys if k.ReadObj().InheritsFrom("TGraphAsymmErrors") and "Total" in k.GetName()] |
| 38 | + |
| 39 | + if not graph_names: |
| 40 | + print(f"No TGraphAsymmErrors found in {args.f1}.") |
| 41 | + return |
| 42 | + |
| 43 | + for gname in graph_names: |
| 44 | + g1 = file1.Get(gname) |
| 45 | + g2 = file2.Get(gname) |
| 46 | + |
| 47 | + if not g1 or not g2: |
| 48 | + continue |
| 49 | + |
| 50 | + c = ROOT.TCanvas(f"c_{gname}", "", 800, 600) |
| 51 | + c.SetRightMargin(0.05) |
| 52 | + c.SetLeftMargin(0.12) |
| 53 | + c.SetBottomMargin(0.12) |
| 54 | + c.SetGridy() |
| 55 | + |
| 56 | + # Styling |
| 57 | + g1.SetLineColor(ROOT.kBlue + 1) |
| 58 | + g1.SetMarkerColor(ROOT.kBlue + 1) |
| 59 | + g1.SetMarkerStyle(20) |
| 60 | + g1.SetLineWidth(2) |
| 61 | + |
| 62 | + g2.SetLineColor(ROOT.kRed + 1) |
| 63 | + g2.SetMarkerColor(ROOT.kRed + 1) |
| 64 | + g2.SetMarkerStyle(21) |
| 65 | + g2.SetLineWidth(2) |
| 66 | + |
| 67 | + # Determine Y-axis range including error bars |
| 68 | + y_min, y_max = 1.0, 0.0 |
| 69 | + for g in [g1, g2]: |
| 70 | + for i in range(g.GetN()): |
| 71 | + y = g.GetY()[i] |
| 72 | + y_err_low = g.GetErrorYlow(i) |
| 73 | + y_err_high = g.GetErrorYhigh(i) |
| 74 | + |
| 75 | + if y > 0: # Ignore empty bins |
| 76 | + if (y - y_err_low) < y_min: y_min = y - y_err_low |
| 77 | + if (y + y_err_high) > y_max: y_max = y + y_err_high |
| 78 | + |
| 79 | + # Add slight padding to min/max |
| 80 | + g1.SetMaximum(min(1.05, y_max * 1.05)) |
| 81 | + g1.SetMinimum(max(0.0, y_min * 0.9)) |
| 82 | + |
| 83 | + # Clean up title based on Script 1's 'eff_' prefix |
| 84 | + clean_title = gname.replace("eff_", "Efficiency: ").replace("_", " ") |
| 85 | + g1.SetTitle(clean_title) |
| 86 | + |
| 87 | + # Dynamic axis labels |
| 88 | + g1.GetYaxis().SetTitle("Efficiency") |
| 89 | + g1.GetXaxis().SetTitle(get_variable_from_name(gname)) |
| 90 | + |
| 91 | + g1.Draw("AP") |
| 92 | + g2.Draw("P SAME") |
| 93 | + |
| 94 | + # Adjusted legend to avoid overlapping data in the bottom left |
| 95 | + leg = ROOT.TLegend(0.60, 0.20, 0.90, 0.35) |
| 96 | + leg.SetBorderSize(0) |
| 97 | + leg.SetFillStyle(0) |
| 98 | + leg.SetTextSize(0.035) |
| 99 | + leg.AddEntry(g1, args.l1, "lp") |
| 100 | + leg.AddEntry(g2, args.l2, "lp") |
| 101 | + leg.Draw() |
| 102 | + |
| 103 | + out_path = os.path.join(args.outdir, f"compare_{gname}.png") |
| 104 | + c.SaveAs(out_path) |
| 105 | + c.SaveAs(out_path.replace(".png", ".pdf")) |
| 106 | + |
| 107 | + # Cleanup memory for the canvas |
| 108 | + c.Close() |
| 109 | + |
| 110 | + print(f"Comparison plots saved to {args.outdir}/") |
| 111 | + |
| 112 | +if __name__ == "__main__": |
| 113 | + main() |
0 commit comments