arXiv:2412.10665
ho22joshua's picture
making job submission and scripts more general, removing hard coded paths
9e4bc69
Raw
History Blame Contribute Delete
3.6 kB
import argparse
import glob
import os
import sys
from pathlib import Path
import awkward as ak
import uproot
REPO_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO_ROOT))
from root_gnn_base import utils
from root_gnn_base.dataset import selection_branches, check_selection, print_cutflow, init_cutflow
def get_branches(dataset_config):
args = dataset_config["args"]
branches = []
for feat in args.get("node_branch_names", []):
if isinstance(feat, list):
for branch in feat:
if isinstance(branch, str) and branch != "CALC_E":
branches.append(branch)
for feat in args.get("global_features", []):
if isinstance(feat, str):
branches.append(feat)
for feat in args.get("tracking_info", []):
if isinstance(feat, str):
branches.append(feat)
for selection in dataset_config.get("selections", []):
branches.extend(selection_branches(selection))
return sorted(set(branches))
def load_arrays(dataset_config):
args = dataset_config["args"]
raw_dir = args["raw_dir"]
file_names = args["file_names"]
tree_name = args.get("tree_name", "nominal_Loose")
files = []
if isinstance(file_names, str):
files = glob.glob(os.path.join(raw_dir, file_names))
else:
for file_name in file_names:
files.extend(glob.glob(os.path.join(raw_dir, file_name)))
branches = get_branches(dataset_config)
arrays = []
for file in files:
with uproot.open(file) as f:
arrays.append(f[tree_name].arrays(branches, library="ak"))
if not arrays:
raise FileNotFoundError(f"No files found in {os.path.join(raw_dir, str(file_names))}")
return ak.concatenate(arrays, axis=0), branches
def vectorized_cutflow(data, selections):
cutflow = init_cutflow(selections)
first_field = data.fields[0] if len(data.fields) > 0 else None
cutflow["total"] = len(data[first_field]) if first_field is not None else 0
mask = ak.ones_like(data[first_field], dtype=bool) if first_field is not None else None
for i, selection in enumerate(selections):
if isinstance(selection, str):
current_mask = eval(selection, {"__builtins__": {}}, data)
else:
current_mask = check_selection(data, selection)
current_mask = ak.to_numpy(current_mask)
if mask is None:
mask = current_mask
else:
mask = mask & current_mask
cutflow["counts"][i] = int(ak.sum(mask))
return cutflow
def main():
parser = argparse.ArgumentParser(description="Fast selection tester and cutflow printer")
parser.add_argument("--config", required=True, help="Path to YAML config file")
args = parser.parse_args()
config = utils.load_config(args.config)
for dataset_name, dataset_config in config["Datasets"].items():
selections = dataset_config.get("selections", [])
print(f"\n== Dataset: {dataset_name} ==")
data, branches = load_arrays(dataset_config)
for selection in selections:
try:
_ = eval(selection, {"__builtins__": {}}, data) if isinstance(selection, str) else check_selection({b: data[b] for b in branches}, selection)
print(f"OK: {selection}")
except Exception:
print(f"FAILED: {selection}")
raise
cutflow = vectorized_cutflow(data, selections)
print_cutflow(cutflow, title=f"Cutflow for {dataset_name}")
if __name__ == "__main__":
main()