|
25 | 25 |
|
26 | 26 | import ROOT # pylint: disable=import-error |
27 | 27 |
|
28 | | -parser = argparse.ArgumentParser(description="A tool to calculate efficiency and upload it to CCDB") |
| 28 | + |
| 29 | +class CustomHelpFormatter(argparse.HelpFormatter): |
| 30 | + "Add default value to help format" |
| 31 | + |
| 32 | + def _get_help_string(self, action): |
| 33 | + help_str = action.help |
| 34 | + if help_str is not None and action.default not in [argparse.SUPPRESS, None]: |
| 35 | + help_str += f" (default: {action.default})" |
| 36 | + return help_str |
| 37 | + |
| 38 | + |
| 39 | +parser = argparse.ArgumentParser( |
| 40 | + description="A tool to calculate efficiency and upload it to CCDB", |
| 41 | + formatter_class=CustomHelpFormatter, |
| 42 | +) |
29 | 43 | parser.add_argument( |
30 | | - "run_dir", |
| 44 | + "--alien-path", |
31 | 45 | type=Path, |
32 | | - help="Path to run directory with analysis results", |
| 46 | + help="path to train run's directory in Alien with analysis results " |
| 47 | + "[example: /alice/cern.ch/user/a/alihyperloop/outputs/0033/332611/70301]", |
| 48 | +) |
| 49 | +parser.add_argument( |
| 50 | + "--mc-reco", |
| 51 | + type=str, |
| 52 | + nargs="+", |
| 53 | + help="paths to MC Reco histograms, separated by space [example: task/mcreco_one/hPt task/mcreco_two/hPt]", |
| 54 | + required=True, |
33 | 55 | ) |
34 | 56 | parser.add_argument( |
35 | | - "--task", |
36 | | - "-t", |
| 57 | + "--mc-truth", |
37 | 58 | type=str, |
38 | | - help="Task name to query histograms from", |
| 59 | + nargs="+", |
| 60 | + help="paths to MC Truth histograms, separated by space [example: task/mctruth_one/hPt task/mctruth_one/hPt]", |
39 | 61 | required=True, |
40 | 62 | ) |
41 | 63 | parser.add_argument( |
42 | 64 | "--ccdb-path", |
43 | | - "-P", |
44 | 65 | type=str, |
45 | | - help="Path where to save in CCDB", |
| 66 | + help="location in CCDB to where objects will be uploaded", |
46 | 67 | required=True, |
47 | 68 | ) |
48 | 69 | parser.add_argument( |
49 | 70 | "--ccdb-url", |
50 | | - "-U", |
51 | 71 | type=str, |
52 | | - help="Path where to save in CCDB", |
| 72 | + help="URL to CCDB", |
53 | 73 | default="http://ccdb-test.cern.ch:8080", |
54 | 74 | ) |
55 | 75 | parser.add_argument( |
56 | 76 | "--ccdb-labels", |
57 | | - "-L", |
58 | 77 | type=str, |
59 | 78 | nargs="+", |
60 | | - help="Labels for objects' metadata in CCDB", |
61 | | - default=[""] * 2, |
| 79 | + help="custom labels to add to objects' metadata in CCDB [example: label1 label2]", |
| 80 | + default=[], |
62 | 81 | ) |
63 | 82 | parser.add_argument( |
64 | 83 | "--ccdb-lifetime", |
65 | | - "-T", |
66 | 84 | type=int, |
67 | | - help="How long should the objects' validity in CCDB last (default: 1 year)", |
| 85 | + help="how long should objects in CCDB remain valid (milliseconds)", |
68 | 86 | default=365 * 24 * 60 * 60 * 1000, # one year |
69 | 87 | ) |
70 | 88 | args = parser.parse_args() |
71 | 89 |
|
| 90 | +if len(args.mc_reco) != len(args.mc_truth): |
| 91 | + print("[!] Provided number of histograms with MC Reco must match MC Truth", file=sys.stderr) |
| 92 | + sys.exit(1) |
| 93 | + |
| 94 | +if len(args.ccdb_labels) > 0 and len(args.ccdb_labels) != len(args.mc_reco): |
| 95 | + print("[!] You must provide labels for all particles", file=sys.stderr) |
| 96 | + sys.exit(1) |
| 97 | + |
| 98 | +if len(args.ccdb_labels) == 0: |
| 99 | + # if flag is not provided, fill with empty strings to match size |
| 100 | + args.ccdb_labels = [""] * len(args.mc_reco) |
| 101 | + |
72 | 102 | ANALYSIS_RESULTS = "AnalysisResults.root" |
73 | | -results_path = args.run_dir / ANALYSIS_RESULTS |
| 103 | +results_path = args.alien_path / ANALYSIS_RESULTS |
74 | 104 | job_id = results_path.parent.name |
75 | 105 | train_number = results_path.parent.parent.name |
76 | 106 |
|
|
81 | 111 |
|
82 | 112 | # get file from alien |
83 | 113 | if not res_dest.is_file(): |
84 | | - print(f"[↓] Downloading analysis results from Alien to {res_dest} ...", file=sys.stderr) |
| 114 | + print(f"[↓] Downloading analysis results from Alien to '{res_dest}' ...", file=sys.stderr) |
85 | 115 | ROOT.TGrid.Connect("alien://") |
86 | 116 | try: |
87 | 117 | subprocess.run( |
|
92 | 122 | print("[-] Download complete!", file=sys.stderr) |
93 | 123 | except subprocess.CalledProcessError as error: |
94 | 124 | print(f"[!] Error while downloading results file: {error.stderr}", file=sys.stderr) |
95 | | - sys.exit(0) |
| 125 | + sys.exit(1) |
96 | 126 | else: |
97 | 127 | print( |
98 | | - f"[-] Skipping download from Alien, since {res_dest} is already present", |
| 128 | + f"[-] Skipping download from Alien, since '{res_dest}' is already present", |
99 | 129 | file=sys.stderr, |
100 | 130 | ) |
101 | 131 |
|
102 | | -particles = {1: "one", 2: "two"} |
| 132 | +print() |
| 133 | + |
103 | 134 | histos_to_upload = [] |
104 | 135 |
|
105 | 136 | # get reco & truth histos |
106 | 137 | with ( |
107 | 138 | ROOT.TFile.Open(res_dest.as_uri()) as res_file, |
108 | 139 | ROOT.TFile.Open(eff_dest.as_uri(), "recreate") as eff_file, |
109 | 140 | ): |
110 | | - for idx, part_num in particles.items(): |
111 | | - reco = res_file.Get(f"{args.task}/Tracks_{part_num}_MC/hPt") |
112 | | - truth = res_file.Get(f"{args.task}/MCTruthTracks_{part_num}/hPt") |
113 | | - if not reco and not truth: |
114 | | - print( |
115 | | - f"[-] No MC Reco nor MC Truth histogram found for particle {part_num}", |
116 | | - file=sys.stderr, |
117 | | - ) |
118 | | - continue |
| 141 | + for idx, (mc_reco, mc_truth) in enumerate(zip(args.mc_reco, args.mc_truth)): |
| 142 | + hist_reco = res_file.Get(mc_reco) |
| 143 | + if not hist_reco: |
| 144 | + print(f"[!] Cannot find MC Reco histogram in '{mc_reco}', aborting", file=sys.stderr) |
| 145 | + sys.exit(1) |
119 | 146 |
|
120 | | - num_bins = reco.GetNbinsX() |
121 | | - x_max = reco.GetXaxis().GetBinLowEdge(num_bins) + reco.GetXaxis().GetBinWidth(num_bins) |
| 147 | + hist_truth = res_file.Get(mc_truth) |
| 148 | + if not hist_truth: |
| 149 | + print(f"[!] Cannot find MC Truth histogram in '{mc_truth}', aborting", file=sys.stderr) |
| 150 | + sys.exit(1) |
122 | 151 |
|
123 | | - hist_name = f"Efficiency_part{idx}" |
| 152 | + num_bins = hist_reco.GetNbinsX() |
| 153 | + x_max = hist_reco.GetXaxis().GetBinLowEdge(num_bins) |
| 154 | + x_max += hist_reco.GetXaxis().GetBinWidth(num_bins) |
| 155 | + |
| 156 | + hist_name = f"Efficiency_part{idx + 1}" |
124 | 157 |
|
125 | 158 | # calculate efficiency |
126 | 159 | eff = ROOT.TH1F(hist_name, "", num_bins, 0, x_max) |
127 | 160 | for bin_idx in range(len(eff)): |
128 | | - denom = truth.GetBinContent(bin_idx) |
129 | | - eff.SetBinContent(bin_idx, reco.GetBinContent(bin_idx) / denom if denom > 0 else 0) |
| 161 | + denom = hist_truth.GetBinContent(bin_idx) |
| 162 | + eff.SetBinContent(bin_idx, hist_reco.GetBinContent(bin_idx) / denom if denom > 0 else 0) |
130 | 163 |
|
131 | 164 | # save efficiency object to file |
132 | 165 | eff_file.WriteObject(eff, hist_name) |
133 | 166 | histos_to_upload.append(hist_name) |
134 | 167 |
|
135 | 168 | if len(histos_to_upload) == 0: |
136 | 169 | print("[-] Exiting, since there is nothing to upload", file=sys.stderr) |
137 | | - sys.exit(0) |
| 170 | + sys.exit(1) |
138 | 171 |
|
139 | 172 | # upload objects to ccdb |
140 | 173 | try: |
141 | 174 | for idx, key in enumerate(histos_to_upload): |
142 | 175 | timestamp_start = int(time.time() * 1000) |
143 | 176 | timestamp_end = timestamp_start + args.ccdb_lifetime |
144 | 177 |
|
145 | | - print(f"[↑] Uploading {key} to CCDB ... ", file=sys.stderr, end="") |
| 178 | + print(f"[↑] Uploading {key} to {args.ccdb_url} ... ", file=sys.stderr, end="") |
146 | 179 | upload_cmd = [ |
147 | 180 | "o2-ccdb-upload", |
148 | 181 | "--file", |
|
161 | 194 | f"trainNumber={train_number};label={args.ccdb_labels[idx]}", |
162 | 195 | ] |
163 | 196 | result = subprocess.run(upload_cmd, capture_output=True, check=True) |
| 197 | + |
| 198 | + if "html" in result.stdout.decode("utf-8"): |
| 199 | + print( |
| 200 | + f"\n[!] Something went wrong with upload request: {result.stdout.decode('utf-8')}", |
| 201 | + file=sys.stderr, |
| 202 | + ) |
| 203 | + sys.exit(1) |
| 204 | + |
164 | 205 | if result.stderr: |
165 | | - print(f"[!] Error while uploading: {result.stderr.decode('utf-8')}", file=sys.stderr) |
166 | | - sys.exit(0) |
| 206 | + print(f"\n[!] Error while uploading: {result.stderr.decode('utf-8')}", file=sys.stderr) |
| 207 | + sys.exit(1) |
167 | 208 |
|
168 | 209 | print("complete!", file=sys.stderr) |
169 | 210 |
|
170 | 211 | except subprocess.CalledProcessError as error: |
171 | | - print(f"[!] Error while uploading: {error.stderr.decode('utf-8')}", file=sys.stderr) |
172 | | - sys.exit(0) |
| 212 | + print(f"\n[!] Error while uploading: {error.stderr.decode('utf-8')}", file=sys.stderr) |
| 213 | + sys.exit(1) |
173 | 214 |
|
| 215 | +print() |
174 | 216 | print("[✓] Success!", file=sys.stderr) |
0 commit comments