Skip to content

Commit 4beab51

Browse files
authored
[PWGCF/FemtoUniverse] Add more flags to efficiency calculator script + fix configurable for timestamps (#9798)
1 parent 40cc984 commit 4beab51

File tree

2 files changed

+84
-42
lines changed

2 files changed

+84
-42
lines changed

PWGCF/FemtoUniverse/Core/FemtoUniverseEfficiencyCalculator.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ struct EfficiencyConfigurableGroup : ConfigurableGroup {
4040
Configurable<bool> confEfficiencyApplyCorrections{"confEfficiencyApplyCorrections", false, "Should apply corrections from efficiency"};
4141
Configurable<std::vector<std::string>> confEfficiencyCCDBLabels{"confEfficiencyCCDBLabels", {}, "Custom labels for efficiency objects in CCDB"};
4242
Configurable<int> confCCDBTrainNumber{"confCCDBTrainNumber", -1, "Train number for which to query CCDB objects (set to -1 to ignore)"};
43-
ConfigurableAxis confEfficiencyCCDBTimestamps{"confEfficiencyCCDBTimestamps", {-1, -1}, "Timestamps in CCDB, to query for specific objects (default: -1 for both)"};
43+
Configurable<std::vector<std::string>> confEfficiencyCCDBTimestamps{"confEfficiencyCCDBTimestamps", {"-1", "-1"}, "Timestamps in CCDB, to query for specific objects (default: -1 for both, the latest valid object)"};
4444

4545
// NOTE: in the future we might move the below configurables to a separate struct, eg. CCDBConfigurableGroup
4646
Configurable<std::string> confCCDBUrl{"confCCDBUrl", "http://alice-ccdb.cern.ch", "CCDB URL to be used"};
@@ -119,7 +119,7 @@ class EfficiencyCalculator
119119
}
120120

121121
auto timestamp = partNo - 1 < config->confEfficiencyCCDBTimestamps->size()
122-
? static_cast<int64_t>(config->confEfficiencyCCDBTimestamps.value[partNo - 1])
122+
? std::stoll(config->confEfficiencyCCDBTimestamps.value[partNo - 1])
123123
: -1;
124124

125125
auto hEff = ccdb.getSpecific<TH1>(config->confCCDBPath, timestamp, metadata);

PWGCF/FemtoUniverse/Scripts/femto_universe_efficiency_calculator.py

Lines changed: 82 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -25,52 +25,82 @@
2525

2626
import ROOT # pylint: disable=import-error
2727

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+
)
2943
parser.add_argument(
30-
"run_dir",
44+
"--alien-path",
3145
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,
3355
)
3456
parser.add_argument(
35-
"--task",
36-
"-t",
57+
"--mc-truth",
3758
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]",
3961
required=True,
4062
)
4163
parser.add_argument(
4264
"--ccdb-path",
43-
"-P",
4465
type=str,
45-
help="Path where to save in CCDB",
66+
help="location in CCDB to where objects will be uploaded",
4667
required=True,
4768
)
4869
parser.add_argument(
4970
"--ccdb-url",
50-
"-U",
5171
type=str,
52-
help="Path where to save in CCDB",
72+
help="URL to CCDB",
5373
default="http://ccdb-test.cern.ch:8080",
5474
)
5575
parser.add_argument(
5676
"--ccdb-labels",
57-
"-L",
5877
type=str,
5978
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=[],
6281
)
6382
parser.add_argument(
6483
"--ccdb-lifetime",
65-
"-T",
6684
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)",
6886
default=365 * 24 * 60 * 60 * 1000, # one year
6987
)
7088
args = parser.parse_args()
7189

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+
72102
ANALYSIS_RESULTS = "AnalysisResults.root"
73-
results_path = args.run_dir / ANALYSIS_RESULTS
103+
results_path = args.alien_path / ANALYSIS_RESULTS
74104
job_id = results_path.parent.name
75105
train_number = results_path.parent.parent.name
76106

@@ -81,7 +111,7 @@
81111

82112
# get file from alien
83113
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)
85115
ROOT.TGrid.Connect("alien://")
86116
try:
87117
subprocess.run(
@@ -92,57 +122,60 @@
92122
print("[-] Download complete!", file=sys.stderr)
93123
except subprocess.CalledProcessError as error:
94124
print(f"[!] Error while downloading results file: {error.stderr}", file=sys.stderr)
95-
sys.exit(0)
125+
sys.exit(1)
96126
else:
97127
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",
99129
file=sys.stderr,
100130
)
101131

102-
particles = {1: "one", 2: "two"}
132+
print()
133+
103134
histos_to_upload = []
104135

105136
# get reco & truth histos
106137
with (
107138
ROOT.TFile.Open(res_dest.as_uri()) as res_file,
108139
ROOT.TFile.Open(eff_dest.as_uri(), "recreate") as eff_file,
109140
):
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)
119146

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)
122151

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}"
124157

125158
# calculate efficiency
126159
eff = ROOT.TH1F(hist_name, "", num_bins, 0, x_max)
127160
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)
130163

131164
# save efficiency object to file
132165
eff_file.WriteObject(eff, hist_name)
133166
histos_to_upload.append(hist_name)
134167

135168
if len(histos_to_upload) == 0:
136169
print("[-] Exiting, since there is nothing to upload", file=sys.stderr)
137-
sys.exit(0)
170+
sys.exit(1)
138171

139172
# upload objects to ccdb
140173
try:
141174
for idx, key in enumerate(histos_to_upload):
142175
timestamp_start = int(time.time() * 1000)
143176
timestamp_end = timestamp_start + args.ccdb_lifetime
144177

145-
print(f"[↑] Uploading {key} to CCDB ... ", file=sys.stderr, end="")
178+
print(f"[↑] Uploading {key} to {args.ccdb_url} ... ", file=sys.stderr, end="")
146179
upload_cmd = [
147180
"o2-ccdb-upload",
148181
"--file",
@@ -161,14 +194,23 @@
161194
f"trainNumber={train_number};label={args.ccdb_labels[idx]}",
162195
]
163196
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+
164205
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)
167208

168209
print("complete!", file=sys.stderr)
169210

170211
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)
173214

215+
print()
174216
print("[✓] Success!", file=sys.stderr)

0 commit comments

Comments
 (0)