File indexing completed on 2026-07-21 07:54:29
0001
0002 """Validate that simg4ox saves run-wide hit arrays for a multi-event run."""
0003
0004 import argparse
0005 import re
0006 from pathlib import Path
0007
0008 import numpy as np
0009
0010
0011 EVENT_PATTERNS = {
0012 "GPU": re.compile(r"Collected GPU hits:\s*(\d+)"),
0013 "G4": re.compile(r"Collected G4\s+hits:\s*(\d+)"),
0014 }
0015 TOTAL_PATTERNS = {
0016 "GPU": re.compile(r"Total GPU hits:\s*(\d+)"),
0017 "G4": re.compile(r"Total G4\s+hits:\s*(\d+)"),
0018 }
0019
0020
0021 def parse_counts(log_text, label, events):
0022 event_counts = [int(value) for value in EVENT_PATTERNS[label].findall(log_text)]
0023 total_matches = TOTAL_PATTERNS[label].findall(log_text)
0024
0025 if len(event_counts) != events:
0026 raise AssertionError(f"Expected {events} {label} event counts, found {len(event_counts)}")
0027 if len(total_matches) != 1:
0028 raise AssertionError(f"Expected one {label} run total, found {len(total_matches)}")
0029
0030 total = int(total_matches[0])
0031 if total != sum(event_counts):
0032 raise AssertionError(f"{label} run total {total} != per-event sum {sum(event_counts)}")
0033 if total == 0:
0034 raise AssertionError(f"Expected non-empty {label} hits")
0035
0036 return event_counts, total
0037
0038
0039 def check_array(path, expected_rows):
0040 if not path.is_file():
0041 raise FileNotFoundError(f"Missing run hit array: {path}")
0042
0043 hits = np.load(path)
0044 expected_shape = (expected_rows, 4, 4)
0045 if hits.shape != expected_shape:
0046 raise AssertionError(f"{path.name} shape {hits.shape} != {expected_shape}")
0047 if hits.dtype != np.float32:
0048 raise AssertionError(f"{path.name} dtype {hits.dtype} != float32")
0049
0050 return hits
0051
0052
0053 def main():
0054 parser = argparse.ArgumentParser(description=__doc__)
0055 parser.add_argument("--log", type=Path, required=True)
0056 parser.add_argument("--output-dir", type=Path, required=True)
0057 parser.add_argument("--events", type=int, default=5)
0058 args = parser.parse_args()
0059
0060 log_text = args.log.read_text()
0061 gpu_event_counts, gpu_total = parse_counts(log_text, "GPU", args.events)
0062 g4_event_counts, g4_total = parse_counts(log_text, "G4", args.events)
0063
0064 gpu_hits = check_array(args.output_dir / "s_hits.npy", gpu_total)
0065 g4_hits = check_array(args.output_dir / "g_hits.npy", g4_total)
0066
0067 print(f"GPU_EVENT_COUNTS={gpu_event_counts}")
0068 print(f"G4_EVENT_COUNTS={g4_event_counts}")
0069 print(f"S_HITS_SHAPE={gpu_hits.shape}")
0070 print(f"G_HITS_SHAPE={g4_hits.shape}")
0071
0072
0073 if __name__ == "__main__":
0074 main()