Source code for astwro.tools.grepfitshdr

#! /usr/bin/env python
# coding=utf-8
""" Grep-like tool for FITS headers

    Call commandline: ``grepfitshdr --help`` for parameters info.
"""
from __future__ import print_function, division

import astropy.io.fits as pyfits
import re
from os.path import isfile
from sys import exit
from sys import stdout
from glob import glob

import astwro.tools.__commons as commons


def headers(filenames):
    for fname in filenames:
        if isfile(fname):
            huds = pyfits.open(fname)
            huds[0].verify('silentfix')
            h = huds[0].header
            huds.close()
            yield h, fname

def printmatch(output, filename, line, withfile, fileonly):
    if not fileonly:
        if withfile:
            print (filename + ': ', end='', file=output)
        print (line, file=output)

[docs]def iter_fields(hdr, onlyvalues=False, fields=None): """ splits header into lines if onlyvalues does not return field names if fields returns only specified fields (forces onlyvalues)""" if fields: for key in hdr: if key in fields: yield hdr[key] elif onlyvalues: for val in hdr.values(): if val: yield str(val) else: for line in repr(hdr).strip().splitlines(): yield line
def grep(pattern, filenames, output=stdout, invert=False, withfile=False, fileonly=False, fields=None, onlyvalues=False, ignorecase=True): if fields is not None and fields[0] == '*': fields = None onlyvalues = True if isinstance(filenames, str): filenames = glob(filenames) regexp = re.compile(pattern, flags=re.IGNORECASE if ignorecase else 0) globmatched = 0 for h, f in headers(filenames): matched = scanned = 0 # rep = repr(h).strip() # for line in rep.splitlines(): for line in iter_fields(h, onlyvalues=onlyvalues, fields=fields): match = regexp.search(str(line)) if invert: match = not match scanned += 1 if match: matched += 1 printmatch(output, f, line, withfile, fileonly) if fileonly and not invert: break globmatched += matched if fileonly: if (not invert and matched > 0) or (invert and matched == scanned): print (f, file=output) return globmatched def __do(arg): return grep(arg.pattern, arg.file, invert=arg.v, withfile=arg.H, fileonly=arg.l, fields=arg.f, ignorecase=arg.i) def __arg_parser(): import argparse parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, fromfile_prefix_chars='@', epilog='exit code:\n' ' 0 if any header matched pattern\n' ' 1 if no match found\n\n' + commons.version_string(), description='grep-like utility for fits (main) headers\n ' 'until -f specified, searches in keys, values and comments') parser.add_argument('pattern', type=str, help='reg-exp, use single dot . to dump all header fields') parser.add_argument('file', type=str, nargs='+', help='FITS file(s), catalog file containing file names prefixed by @ can be provided') parser.add_argument('-i', action='store_true', help='ignore case') parser.add_argument('-v', action='store_true', help='invert match') parser.add_argument('-H', action='store_true', help='add filename to each found line') parser.add_argument('-l', action='store_true', help='print filenames with matches only') parser.add_argument('-f', action='append', metavar='FIELD', help='matches only specified FIELD\'s value; can be provided multiple ' 'times to match several fields; -f* limits search to values but searches ' 'in all fields') return parser
[docs]def main(pattern, file, **kwargs): """Entry point for python script calls. Parameters identical to command line""" # Extract default arguments from command line parser and apply kwargs parameters args = commons.bunch_kwargs(__arg_parser(), positional=[pattern, file], **kwargs) # call main routine - common form command line and python calls return __do(args)
[docs]def info(): """Prints commandline help message""" commons.info(__arg_parser())
def commandline_entry(): # Entry point for command line __args = __arg_parser().parse_args() # parse command line arguments n = __do(__args) # call main routine - common form command line and python calls return 0 if n > 0 else 1 if __name__ == '__main__': code = commandline_entry() exit(code)