File indexing completed on 2026-01-10 09:18:03
0001
0002 """Command-line interface for HepMC3 file normalization.
0003
0004 This module can be invoked as:
0005 python -m acts.examples.hepmc3 [options]
0006 """
0007
0008 import argparse
0009 import json
0010 import sys
0011 from pathlib import Path
0012
0013 from . import (
0014 Compression,
0015 Format,
0016 availableCompressionModes,
0017 availableFormats,
0018 normalizeFiles,
0019 )
0020
0021
0022 def main(prog: str):
0023
0024 parser = argparse.ArgumentParser(
0025 prog=prog,
0026 description="HepMC3 File Normalizer - Normalize and chunk HepMC files",
0027 formatter_class=argparse.RawDescriptionHelpFormatter,
0028 epilog="""
0029 Examples:
0030 # Multi-file mode with chunking
0031 %(prog)s -i input1.hepmc3.gz input2.hepmc3 -n 1000 -c zstd -l 9
0032 %(prog)s -i file.root -o normalized/ -p events -n 5000
0033
0034 # Single output mode (format/compression auto-detected)
0035 %(prog)s -i input1.hepmc3.gz input2.hepmc3 -S combined.hepmc3.zst
0036 %(prog)s -i input.hepmc3.gz -S output/events.hepmc3.gz
0037 """,
0038 )
0039
0040 parser.add_argument(
0041 "-i",
0042 "--input",
0043 nargs="+",
0044 required=True,
0045 metavar="FILE",
0046 help="Input HepMC files",
0047 )
0048
0049 parser.add_argument(
0050 "-S",
0051 "--single-output",
0052 metavar="FILE",
0053 help="Write all events to a single output file. Format and compression are detected from filename.",
0054 )
0055
0056 parser.add_argument(
0057 "-o",
0058 "--output-dir",
0059 default=".",
0060 metavar="DIR",
0061 help="Output directory (ignored with --single-output) [default: .]",
0062 )
0063
0064 parser.add_argument(
0065 "-p",
0066 "--output-prefix",
0067 default="events",
0068 metavar="PREFIX",
0069 help="Output file prefix [default: events]",
0070 )
0071
0072 parser.add_argument(
0073 "-n",
0074 "--events-per-file",
0075 type=int,
0076 default=10000,
0077 metavar="N",
0078 help="Number of events per output file (ignored with --single-output) [default: 10000]",
0079 )
0080
0081 parser.add_argument(
0082 "-m",
0083 "--max-events",
0084 type=int,
0085 default=0,
0086 metavar="N",
0087 help="Maximum number of events to read (0 = all events) [default: 0]",
0088 )
0089
0090 parser.add_argument(
0091 "-c",
0092 "--compression",
0093 choices=["none", "zlib", "lzma", "bzip2", "zstd"],
0094 default="none",
0095 help="Compression type (ignored with --single-output) [default: none]",
0096 )
0097
0098 parser.add_argument(
0099 "-l",
0100 "--compression-level",
0101 type=int,
0102 default=6,
0103 metavar="LEVEL",
0104 help="Compression level (0-19, higher = more compression) [default: 6]",
0105 )
0106
0107 parser.add_argument(
0108 "-f",
0109 "--format",
0110 choices=["ascii", "root"],
0111 default="ascii",
0112 help="Output format (ignored with --single-output) [default: ascii]",
0113 )
0114
0115 parser.add_argument(
0116 "-j",
0117 "--json",
0118 action="store_true",
0119 help="Write JSON output with list of created files to stdout",
0120 )
0121
0122 parser.add_argument("-v", "--verbose", action="store_true", help="Verbose output")
0123
0124 parser.add_argument(
0125 "--list-compressions",
0126 action="store_true",
0127 help="List available compression modes and exit",
0128 )
0129
0130 args = parser.parse_args()
0131
0132
0133 if args.list_compressions:
0134 print("Available compression modes:")
0135 for comp in availableCompressionModes():
0136 print(f" {comp}")
0137 print("\nAvailable formats:")
0138 for fmt in availableFormats():
0139 print(f" {fmt}")
0140 return 0
0141
0142
0143 compression_map = {
0144 "none": Compression.none,
0145 "zlib": Compression.zlib,
0146 "lzma": Compression.lzma,
0147 "bzip2": Compression.bzip2,
0148 "zstd": Compression.zstd,
0149 }
0150
0151
0152 format_map = {
0153 "ascii": Format.ascii,
0154 "root": Format.root,
0155 }
0156
0157 try:
0158
0159 input_files = [Path(f) for f in args.input]
0160 single_output = Path(args.single_output) if args.single_output else None
0161
0162
0163 result = normalizeFiles(
0164 inputFiles=input_files,
0165 singleOutputPath=single_output,
0166 outputDir=Path(args.output_dir),
0167 outputPrefix=args.output_prefix,
0168 eventsPerFile=args.events_per_file,
0169 maxEvents=args.max_events,
0170 format=format_map.get(args.format),
0171 compression=compression_map.get(args.compression),
0172 compressionLevel=args.compression_level,
0173 verbose=args.verbose,
0174 )
0175
0176
0177 if args.json:
0178 output = {
0179 "num_events": result.numEvents,
0180 "num_files": len(result.outputFiles),
0181 "files": [
0182 {
0183 "path": str(Path(f).absolute()),
0184 "size": Path(f).stat().st_size if Path(f).exists() else None,
0185 }
0186 for f in result.outputFiles
0187 ],
0188 }
0189 print(json.dumps(output, indent=2))
0190
0191 return 0
0192
0193 except Exception as e:
0194 print(f"ERROR: {e}", file=sys.stderr)
0195 return 1
0196
0197
0198 if __name__ == "__main__":
0199 sys.exit(main(prog="acts.examples.hepmc3"))