Python Examples¶
Writing and Reading a File¶
Create a HIPO file with particle data and read it back.
import hipopy
import numpy as np
# --- Write ---
schema = hipopy.Schema("REC::Particle", 300, 1)
schema.parse("pid/I,px/F,py/F,pz/F,charge/B")
d = hipopy.Dictionary()
d.add_schema(schema)
writer = hipopy.Writer()
writer.add_dictionary(d)
writer.open("particles.hipo")
np.random.seed(42)
for evt in range(100):
event = hipopy.Event()
n = np.random.randint(1, 6)
bank = hipopy.Bank(schema, n)
for i in range(n):
bank.put_int("pid", i, np.random.choice([11, -11, 2212, 211, -211]))
bank.put_float("px", i, np.random.normal(0, 1))
bank.put_float("py", i, np.random.normal(0, 1))
bank.put_float("pz", i, np.random.uniform(0.5, 5.0))
bank.put_byte("charge", i, -1 if i % 2 == 0 else 1)
event.add_structure(bank)
writer.add_event(event)
writer.close()
print("Wrote 100 events")
# --- Read ---
with hipopy.open("particles.hipo", banks=["REC::Particle"]) as f:
print(f"File has {f.entries} events")
for i, banks in enumerate(f):
bank = banks["REC::Particle"]
pid = bank["pid"]
px = bank["px"]
py = bank["py"]
pt = np.sqrt(px**2 + py**2)
if i < 3:
print(f" Event {i}: {len(pid)} particles, pids={pid}, max pT={pt.max():.3f}")
Output:
Wrote 100 events
File has 100 events
Event 0: 4 particles, pids=[ 11 2212 -211 211], max pT=1.234
Event 1: 3 particles, pids=[ -11 11 211], max pT=0.987
Event 2: 5 particles, pids=[2212 -11 -211 11 211], max pT=1.567
NumPy Batch Analysis¶
Read all data at once into flat NumPy arrays for fast analysis.
import hipopy
import numpy as np
# Read all particles from all events as flat arrays
data = hipopy.read_columns("particles.hipo", "REC::Particle",
columns=["pid", "px", "py", "pz"])
print(f"Total particles: {len(data['pid'])}")
# Compute derived quantities
pt = np.sqrt(data["px"]**2 + data["py"]**2)
p = np.sqrt(data["px"]**2 + data["py"]**2 + data["pz"]**2)
print(f"pT: mean={pt.mean():.3f}, max={pt.max():.3f}")
print(f"|p|: mean={p.mean():.3f}, max={p.max():.3f}")
# Filter by particle type
for name, pid_val in [("electrons", 11), ("protons", 2212), ("pions+", 211)]:
mask = np.abs(data["pid"]) == pid_val
n = mask.sum()
print(f"{name}: {n} ({100*n/len(data['pid']):.1f}%), "
f"mean pT={pt[mask].mean():.3f}")
Awkward Array Ragged Analysis¶
Preserve per-event structure for event-level operations.
import hipopy
import numpy as np
import awkward as ak
particles = hipopy.read_bank("particles.hipo", "REC::Particle",
columns=["pid", "px", "py", "pz"])
print(f"Type: {particles.type}")
print(f"Events: {len(particles)}")
# Particles per event
n_per_event = ak.num(particles.pid)
print(f"Particles/event: min={ak.min(n_per_event)}, "
f"max={ak.max(n_per_event)}, mean={ak.mean(n_per_event):.1f}")
# pT for all particles (vectorized, ragged-aware)
pt = np.sqrt(particles.px**2 + particles.py**2)
# Max pT per event
max_pt = ak.max(pt, axis=1)
print(f"Max pT per event: mean={ak.mean(max_pt):.3f}")
# Select electrons per event
is_electron = np.abs(particles.pid) == 11
electrons = particles[is_electron]
n_with_electron = ak.sum(ak.num(electrons.pid) > 0)
print(f"Events with electrons: {n_with_electron}/{len(particles)}")
# Read only first 10 events with column subset
subset = hipopy.read_bank("particles.hipo", "REC::Particle",
columns=["px", "py"], max_events=10)
print(f"Subset: {len(subset)} events, fields={subset.fields}")
Low-Level Read/Write¶
Direct C++ API style for maximum control.
import hipopy
# Define two bank types
part_schema = hipopy.Schema("event::particle", 100, 1)
part_schema.parse("pid/I,px/F,py/F,pz/F")
det_schema = hipopy.Schema("event::detector", 100, 2)
det_schema.parse("id/I,energy/F,time/F")
# Write file with two banks per event
d = hipopy.Dictionary()
d.add_schema(part_schema)
d.add_schema(det_schema)
writer = hipopy.Writer()
writer.add_dictionary(d)
writer.open("multi_bank.hipo")
for i in range(50):
event = hipopy.Event()
pbank = hipopy.Bank(part_schema, 3)
for row in range(3):
pbank.put_int("pid", row, 11 + row * 100)
pbank.put_float("px", row, 0.1 * (row + 1))
pbank.put_float("py", row, 0.2 * (row + 1))
pbank.put_float("pz", row, 1.0 + row)
event.add_structure(pbank)
dbank = hipopy.Bank(det_schema, 2)
for row in range(2):
dbank.put_int("id", row, 10 + row)
dbank.put_float("energy", row, 0.5 * (row + 1))
dbank.put_float("time", row, 100.0 + row * 10)
event.add_structure(dbank)
writer.add_event(event)
writer.close()
# Read back with low-level API
reader = hipopy.Reader("multi_bank.hipo")
d2 = hipopy.Dictionary()
reader.read_dictionary(d2)
print(f"Banks in file: {d2.get_schema_list()}")
print(f"Events: {reader.get_entries()}")
event = hipopy.Event()
pbank = hipopy.Bank(d2["event::particle"])
dbank = hipopy.Bank(d2["event::detector"])
reader.next()
reader.read(event)
event.read(pbank)
event.read(dbank)
print(f"\nFirst event:")
print(f" Particles: {pbank.get_rows()} rows")
for row in range(pbank.get_rows()):
print(f" pid={pbank.get_int('pid', row)}, "
f"px={pbank.get_float('px', row):.2f}, "
f"py={pbank.get_float('py', row):.2f}")
print(f" Detectors: {dbank.get_rows()} rows")
for row in range(dbank.get_rows()):
print(f" id={dbank.get_int('id', row)}, "
f"energy={dbank.get_float('energy', row):.2f}")
Expression Parsing¶
Use the built-in expression parser for calculations.
import hipopy
# Basic arithmetic
p = hipopy.Parser("2 * x + y")
p["x"] = 3.0
p["y"] = 1.0
print(f"2*x + y = {p.evaluate()}") # 7.0
# Physics: compute transverse momentum
pt_calc = hipopy.Parser("sqrt(px*px + py*py)")
pt_calc["px"] = 3.0
pt_calc["py"] = 4.0
print(f"pT = {pt_calc.evaluate()}") # 5.0
# Evaluate different expressions with same parser
p2 = hipopy.Parser("1")
print(f"sin(3.14159/2) = {p2.evaluate('sin(3.14159/2)'):.4f}") # ~1.0
print(f"exp(1) = {p2.evaluate('exp(1)'):.4f}") # ~2.7183
Source Files¶
The full example scripts are available in the repository at extensions/pybind/examples/:
write_read.py-- Create and read back a HIPO filenumpy_analysis.py-- NumPy-based particle analysisawkward_analysis.py-- Awkward Array ragged batch readingevent_filtering.py-- Row filtering with NumPy masks and Parsermulti_file.py-- Multi-file processing with InputSource, Fusion, and batch reading