Skip to content

Commit 5f28dcb

Browse files
zchochulZuzanna
andauthored
[PWGCF] FemtoUniverse -- change in naming of configurables for p-phi analysis (#10208)
Co-authored-by: Zuzanna <01150674@pw.edu.pl>
1 parent 47812ae commit 5f28dcb

File tree

2 files changed

+315
-102
lines changed

2 files changed

+315
-102
lines changed
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
#!/usr/bin/env python3
2+
3+
# Copyright 2019-2020 CERN and copyright holders of ALICE O2.
4+
# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
5+
# All rights not expressly granted are reserved.
6+
#
7+
# This software is distributed under the terms of the GNU General Public
8+
# License v3 (GPL Version 3), copied verbatim in the file "COPYING".
9+
#
10+
# In applying this license CERN does not waive the privileges and immunities
11+
# granted to it by virtue of its status as an Intergovernmental Organization
12+
# or submit itself to any jurisdiction.
13+
14+
"""
15+
A tool to calculate efficiency and upload it to CCDB.
16+
Author: Dawid Karpiński (dawid.karpinski@cern.ch)
17+
Modified by: Zuzanna Chochulska (zchochul@cern.ch)
18+
"""
19+
20+
import argparse
21+
import subprocess
22+
import sys
23+
import tempfile
24+
import time
25+
from pathlib import Path
26+
27+
import ROOT # pylint: disable=import-error
28+
29+
30+
class CustomHelpFormatter(argparse.HelpFormatter):
31+
"Add default value to help format"
32+
33+
def _get_help_string(self, action):
34+
help_str = action.help
35+
if help_str is not None and action.default not in [argparse.SUPPRESS, None]:
36+
help_str += f" (default: {action.default})"
37+
return help_str
38+
39+
40+
parser = argparse.ArgumentParser(
41+
description="A tool to calculate efficiency and upload it to CCDB",
42+
formatter_class=CustomHelpFormatter,
43+
)
44+
parser.add_argument(
45+
"--alien-path",
46+
type=Path,
47+
help="path to train run's directory in Alien with analysis results "
48+
"[example: /alice/cern.ch/user/a/alihyperloop/outputs/0033/332611/70301]",
49+
)
50+
parser.add_argument(
51+
"--mc-reco",
52+
type=str,
53+
nargs="+",
54+
help="paths to MC Reco histograms, separated by space [example: task/mcreco_one/hPt task/mcreco_two/hPt]",
55+
required=True,
56+
)
57+
parser.add_argument(
58+
"--mc-truth",
59+
type=str,
60+
nargs="+",
61+
help="paths to MC Truth histograms, separated by space [example: task/mctruth_one/hPt task/mctruth_one/hPt]",
62+
required=True,
63+
)
64+
parser.add_argument(
65+
"--ccdb-path",
66+
type=str,
67+
help="location in CCDB to where objects will be uploaded",
68+
required=True,
69+
)
70+
parser.add_argument(
71+
"--ccdb-url",
72+
type=str,
73+
help="URL to CCDB",
74+
default="http://ccdb-test.cern.ch:8080",
75+
)
76+
parser.add_argument(
77+
"--ccdb-labels",
78+
type=str,
79+
nargs="+",
80+
help="custom labels to add to objects' metadata in CCDB [example: label1 label2]",
81+
default=[],
82+
)
83+
parser.add_argument(
84+
"--ccdb-lifetime",
85+
type=int,
86+
help="how long should objects in CCDB remain valid (milliseconds)",
87+
default=365 * 24 * 60 * 60 * 1000, # one year
88+
)
89+
args = parser.parse_args()
90+
91+
if len(args.mc_reco) != len(args.mc_truth):
92+
print("[!] Provided number of histograms with MC Reco must match MC Truth", file=sys.stderr)
93+
sys.exit(1)
94+
95+
if len(args.ccdb_labels) > 0 and len(args.ccdb_labels) != len(args.mc_reco):
96+
print("[!] You must provide labels for all particles", file=sys.stderr)
97+
sys.exit(1)
98+
99+
if len(args.ccdb_labels) == 0:
100+
# if flag is not provided, fill with empty strings to match size
101+
args.ccdb_labels = [""] * len(args.mc_reco)
102+
103+
ANALYSIS_RESULTS = "AnalysisResults.root"
104+
results_path = args.alien_path / ANALYSIS_RESULTS
105+
job_id = results_path.parent.name
106+
train_number = results_path.parent.parent.name
107+
108+
tmp_dir = Path(tempfile.gettempdir())
109+
110+
res_dest = tmp_dir / f"{train_number}-{job_id}-{ANALYSIS_RESULTS}"
111+
eff_dest = tmp_dir / f"{train_number}-{job_id}-Efficiency.root"
112+
113+
# get file from alien
114+
if not res_dest.is_file():
115+
print(f"[↓] Downloading analysis results from Alien to '{res_dest}' ...", file=sys.stderr)
116+
ROOT.TGrid.Connect("alien://")
117+
try:
118+
subprocess.run(
119+
["alien_cp", results_path, "file://" + str(res_dest)],
120+
capture_output=True,
121+
check=True,
122+
)
123+
print("[-] Download complete!", file=sys.stderr)
124+
except subprocess.CalledProcessError as error:
125+
print(f"[!] Error while downloading results file: {error.stderr}", file=sys.stderr)
126+
sys.exit(1)
127+
else:
128+
print(
129+
f"[-] Skipping download from Alien, since '{res_dest}' is already present",
130+
file=sys.stderr,
131+
)
132+
133+
print()
134+
135+
histos_to_upload = []
136+
137+
# get reco & truth histos
138+
with (
139+
ROOT.TFile.Open(res_dest.as_uri()) as res_file,
140+
ROOT.TFile.Open(eff_dest.as_uri(), "recreate") as eff_file,
141+
):
142+
143+
for idx, (mc_reco, mc_truth) in enumerate(zip(args.mc_reco, args.mc_truth)):
144+
hist_reco = res_file.Get(mc_reco)
145+
if not hist_reco:
146+
print(f"[!] Cannot find MC Reco histogram in '{mc_reco}', aborting", file=sys.stderr)
147+
sys.exit(1)
148+
149+
hist_truth = res_file.Get(mc_truth)
150+
if not hist_truth:
151+
print(f"[!] Cannot find MC Truth histogram in '{mc_truth}', aborting", file=sys.stderr)
152+
sys.exit(1)
153+
154+
hist_reco.Rebin(4)
155+
hist_truth.Rebin(4)
156+
157+
num_bins = hist_reco.GetNbinsX()
158+
x_max = hist_reco.GetXaxis().GetBinLowEdge(num_bins)
159+
x_max += hist_reco.GetXaxis().GetBinWidth(num_bins)
160+
161+
hist_name = f"Efficiency_part{idx + 1}"
162+
163+
# calculate efficiency
164+
eff = ROOT.TH1F(hist_name, "", num_bins, 0, x_max)
165+
for bin_idx in range(1, num_bins + 1): # Bins start at 1 in ROOT
166+
denom = hist_truth.GetBinContent(bin_idx)
167+
if idx == 0:
168+
denom *= 0.489
169+
eff.SetBinContent(bin_idx, hist_reco.GetBinContent(bin_idx) / denom if denom > 0 else 0)
170+
171+
# save efficiency object to file
172+
eff_file.WriteObject(eff, hist_name)
173+
histos_to_upload.append(hist_name)
174+
175+
if len(histos_to_upload) == 0:
176+
print("[-] Exiting, since there is nothing to upload", file=sys.stderr)
177+
sys.exit(1)
178+
179+
# upload objects to ccdb
180+
try:
181+
for idx, key in enumerate(histos_to_upload):
182+
timestamp_start = int(time.time() * 1000)
183+
timestamp_end = timestamp_start + args.ccdb_lifetime
184+
185+
print(f"[↑] Uploading {key} to {args.ccdb_url} ... ", file=sys.stderr, end="")
186+
upload_cmd = [
187+
"o2-ccdb-upload",
188+
"--file",
189+
eff_dest.as_uri(),
190+
"--host",
191+
args.ccdb_url,
192+
"--key",
193+
key,
194+
"--path",
195+
args.ccdb_path,
196+
"--starttimestamp",
197+
str(timestamp_start),
198+
"--endtimestamp",
199+
str(timestamp_end),
200+
"--meta",
201+
f"trainNumber={train_number};label={args.ccdb_labels[idx]}",
202+
]
203+
result = subprocess.run(upload_cmd, capture_output=True, check=True)
204+
205+
if "html" in result.stdout.decode("utf-8"):
206+
print(
207+
f"\n[!] Something went wrong with upload request: {result.stdout.decode('utf-8')}",
208+
file=sys.stderr,
209+
)
210+
sys.exit(1)
211+
212+
if result.stderr:
213+
print(f"\n[!] Error while uploading: {result.stderr.decode('utf-8')}", file=sys.stderr)
214+
sys.exit(1)
215+
216+
print("complete!", file=sys.stderr)
217+
218+
except subprocess.CalledProcessError as error:
219+
print(f"\n[!] Error while uploading: {error.stderr.decode('utf-8')}", file=sys.stderr)
220+
sys.exit(1)
221+
222+
print()
223+
print("[✓] Success!", file=sys.stderr)

0 commit comments

Comments
 (0)