#!/usr/bin/env python from __future__ import print_function from __future__ import absolute_import from __future__ import division import sys import re import argparse import ROOT ROOT.PyConfig.IgnoreCommandLineOptions = True from rat import ROOT class SmartFormatter(argparse.HelpFormatter): ''' Sneaky little argparse formatter to make help output for an argument with a fixed set of options to look nice. ''' def _split_lines(self, text, width): if text.startswith('R|'): return text[2:].splitlines() # this is the RawTextHelpFormatter._split_lines return argparse.HelpFormatter._split_lines(self, text, width) def dump_metadata(meta): ''' Function to get a variety of metadata from the specified file. ''' npass = meta.GetPassCount() if npass > 0: for ipass in range(0, npass): print('Pass {}:'.format(ipass)) print(' Host {} ({})'.format(meta.GetHostNames()[ipass], meta.GetHostSystems()[ipass])) print(' RAT version {}'.format(meta.GetVersions()[ipass])) print(' RAT revision {}'.format(meta.GetRevisions()[ipass])) print(' ROOT version {}'.format(meta.GetRootVersions()[ipass])) print(' GEANT4 version {}'.format(meta.GetGeant4Versions()[ipass].strip())) print(' Contains MC {}'.format(meta.GetContainsMCFlags()[ipass])) print(' Contains Data {}'.format(meta.GetContainsDataFlags()[ipass])) print(' Events Generated {}'.format(meta.GetEventsGeneratedCounts()[ipass])) print(' Events Stored {}'.format(meta.GetEventsStoredCounts()[ipass])) db = meta.GetMetaDB(ipass) for ioc in range(0, db.GetOverrideCommandCount()): oc = db.GetOverrideCommand(ioc) print(' {:<19} {}'.format(oc.first.strip(), oc.second.strip())) for iof in range(0, db.GetFileCount()): print(' File {}'.format(db.GetFile(iof))) else: sys.exit("No metadata for any passes in ROOT file.") def compare_metadata(meta, fname): ''' Function to compare metadata. Compares metadata to the specified file. ''' g = ROOT.TFile.Open(fname) if not g: return '0' if g.IsZombie(): return '0' gmeta = g.Get('meta') if gmeta: npass = meta.GetPassCount() if npass != gmeta.GetPassCount(): return '-' for ipass in range(0, npass): if meta.GetVersions()[ipass] != gmeta.GetVersions()[ipass]: return '-' if meta.GetRevisions()[ipass] != gmeta.GetRevisions()[ipass]: return '-' if meta.GetRootVersions()[ipass] != gmeta.GetRootVersions()[ipass]: return '-' if meta.GetGeant4Versions()[ipass] != gmeta.GetGeant4Versions()[ipass]: return '-' if meta.GetContainsMCFlags()[ipass] != gmeta.GetContainsMCFlags()[ipass]: return '-' if meta.GetContainsDataFlags()[ipass] != gmeta.GetContainsDataFlags()[ipass]: return '-' if meta.GetEventsStoredCounts()[ipass] != gmeta.GetEventsStoredCounts()[ipass]: return '-' if meta.GetEventsGeneratedCounts()[ipass] != gmeta.GetEventsGeneratedCounts()[ipass]: return '-' db = meta.GetMetaDB(ipass) gdb = gmeta.GetMetaDB(ipass) if db.GetOverrideCommandCount() != gdb.GetOverrideCommandCount(): return '-' if db.GetFileCount() != gdb.GetFileCount(): return '-' for ioc in range(0, db.GetOverrideCommandCount()): oc = db.GetOverrideCommand(ioc) match = False for i in range(0, gdb.GetOverrideCommandCount()): goc = gdb.GetOverrideCommand(i) if oc.first == goc.first: if oc.second == goc.second: match = True break return '-' if not match: return '-' for iof in range(0, db.GetFileCount()): of = db.GetFile(iof) match = False for i in range(0, gdb.GetFileCount()): if of == gdb.GetFile(i): match = True break if not match: return '-' else: return '-' return '+' def main(): ''' Main ratinfo function to call; handles argument parsing. ''' parser = argparse.ArgumentParser(description='''Executable used to obtain information related to a given RAT file.''' , formatter_class=SmartFormatter) parser.add_argument('command', metavar='command', type=str, choices=['log', 'macro', 'meta', 'dbkeys', 'db'], help=('R|Type of information to obtain about file.\n' 'Allowed commands are:\n' '\n' 'log Print log from RAT run which generated first file.\n' 'macro Print RAT macro which generated first file.\n' 'meta Print metadata (versions, overrides) for first file.\n' ' If more files listed, compare metadata with the first file,\n' ' listing matches with a +, and mismatches with a -.\n' 'dbkeys List keys in db TMap in first file.\n' 'db Print tables in db TMap, with regular expressions to\n' ' match keys as further arguments.\n')) parser.add_argument('file_path', type=str, help="Path to RAT file.") parser.add_argument('extra_info', type=str, nargs="*", help="For 'meta' and 'db' options, extra info can be provided here.") args = parser.parse_args() # we will detect and report errors ourselves ROOT.gErrorIgnoreLevel = ROOT.kFatal # For almost all commands, only care about one file. if len(args.extra_info) > 0 and args.command != 'meta' and args.command != 'db': print('ERROR: only input additional information if using the "meta" or "db" commands.') sys.exit(2) # Open file; do sanity checks f = ROOT.TFile.Open(args.file_path) if not f: sys.exit("No such file {}.".format(args.file_path)) if f.IsZombie(): sys.exit("Failed to open file {}.".format(args.file_path)) # Run relevant command as chosen by user if args.command == 'log': log = f.Get("log") if log: print(log.GetString()) else: sys.exit("No log present in ROOT file.") elif args.command == 'macro': macro = f.Get('macro') if macro: print(macro.GetString()) else: sys.exit("No macro present in ROOT file.") elif args.command == 'dbkeys': db = f.Get('db') if db: idb = db.MakeIterator() while idb.Next(): print(idb.Key()) else: sys.exit("No db present in ROOT file.") elif args.command == 'db': db = f.Get('db') if db: idb = db.MakeIterator() for re_arg in args.extra_info: p = re.compile(re_arg) idb.Reset() while idb.Next(): if p.match(idb.Key().GetName()): print('{} = {}'.format(idb.Key(), idb.Value())) else: sys.exit("No db present in ROOT file.") elif args.command == 'meta': meta = f.Get('meta') if meta: dump_metadata(meta) if len(args.extra_info) > 0: print('+ {}'.format(args.file_path)) for arg in args.extra_info: c = compare_metadata(meta, arg) print('{} {}'.format(c, arg)) else: sys.exit("No metadata present in ROOT file.") else: sys.exit("Invalid command: {}".format(args.command)) if __name__ == '__main__': main()