From 4471370f61c513485cee03d2fb9959acbff3b5e1 Mon Sep 17 00:00:00 2001 From: Robert Jedrzejewski Date: Fri, 21 Oct 2022 13:58:25 -0400 Subject: [PATCH 1/4] Add code to calculate COS S_REGION and put into keyword --- costools/add_cos_s_region.py | 107 +++++++++++++++++++++++++++++++++++ setup.py | 3 + 2 files changed, 110 insertions(+) create mode 100644 costools/add_cos_s_region.py diff --git a/costools/add_cos_s_region.py b/costools/add_cos_s_region.py new file mode 100644 index 0000000..43d47ed --- /dev/null +++ b/costools/add_cos_s_region.py @@ -0,0 +1,107 @@ +#! /usr/bin/env python + +# Add the S_REGION keyword to raw files +# +import glob +import argparse + +from calcos import cosutil +from astropy.io import fits + +__version__ = '0.1' +def main(dry_run=False): + """Add the S-region keyword to all COS FITS files in the current + directory that meet the following criteria: + + Filename ends with one of ['rawtag.fits', + 'rawtag_a.fits', + 'rawtag_b.fits', + 'rawaccum.fits', + 'rawaccum_a.fits', + 'rawaccum_b.fits', + 'rawacq.fits'] + + The S_REGION keyword will have the value + 'CIRCLE ra_aper dec_aper diameter' + where ra_aper and dec_aper are in decimal degrees and are read from + the extension 1 header, and diameter = 2.5/3600.0, which is the diameter + of the PSA and BOA in decimal degrees. + + The keyword will be added after the PA_APER keyword in the extension 1 + header + + """ + endings = ['rawtag.fits', + 'rawtag_a.fits', + 'rawtag_b.fits', + 'rawaccum.fits', + 'rawaccum_a.fits', + 'rawaccum_b.fits', + 'rawacq.fits'] + + fitsfiles = glob.glob('*.fits') + for file in fitsfiles: + for ending in endings: + if file.endswith(ending): + add_s_region(file, dry_run) + return + +def add_s_region(file, dry_run): + + open_mode = 'readonly' + if not dry_run: open_mode = 'update' + + with fits.open(file, mode=open_mode) as f1: + if (len(f1) < 2): + cosutil.printWarning("File {} has only {} extensions".format(file, len(f1))) + cosutil.printContinuation("Need at least 2") + return + prihdr = f1[0].header + if prihdr['INSTRUME'] != 'COS': + cosutil.printWarning("File {}: Instrument is not COS".format(file)) + return + + ext1hdr = f1[1].header + try: + ra_aper = ext1hdr['RA_APER'] + dec_aper = ext1hdr['DEC_APER'] + pa_aper = ext1hdr['PA_APER'] + except KeyError: + cosutil.printWarning('One or more of RA_APER, DEC_APER, PA_APER is not present') + cosutil.printContinuation('in extension 1 header of file {}'.format(file)) + return + diameter = 2.5 / 3600.0 + s_region = 'CIRCLE {0:.8f} {1:.7f} {2:.8f}'.format(ra_aper, dec_aper, diameter) + if not dry_run: + try: + existing_s_region = ext1hdr['S_REGION'] + ext1hdr['S_REGION'] = (s_region, 'Spatial extent of the observation') + cosutil.printMsg("Using existing S_REGION keyword in file {}".format(file)) + except KeyError: + ext1hdr.insert('PA_APER', ('S_REGION', s_region, 'S_region string'), after=True) + cosutil.printMsg('Added S_REGION keyword to {}'.format(file)) + cosutil.printMsg("Setting value to '{}'".format(s_region)) + else: + cosutil.printMsg("File {} has S_REGION = '{}'".format(file, s_region)) + cosutil.printMsg("Dry-run - no changes made to science header") + +if __name__ == '__main__': + + parser = argparse.ArgumentParser( + """Add S_REGION value to raw data headers""" + ) + + parser.add_argument( + '--dry_run', action='store_true', + help="Calculate S_REGION value, but don't write to data header[s]") + + parser.add_argument('-v', '--version', help='Print version info', action='version', + version = __version__) + + args = parser.parse_args() + + if '--version' in args: + print(__version__) + sys.exit(0) + + main(dry_run=args.dry_run) diff --git a/setup.py b/setup.py index 9b3e319..970acc3 100755 --- a/setup.py +++ b/setup.py @@ -38,6 +38,9 @@ 'timefilter = {0}.timefilter:main'.format(PACKAGENAME), ], }, + scripts=[ + 'costools/add_cos_s_region.py', + ], author='Warren Hack, Nadezhda Dencheva, Phil Hodge', author_email='help@stsci.edu', description='Tools for COS (Cosmic Origins Spectrograph)', From aaf0ed46bce97300ec72b8fc76962146fe9efb0c Mon Sep 17 00:00:00 2001 From: Robert Jedrzejewski Date: Mon, 14 Nov 2022 21:26:41 -0500 Subject: [PATCH 2/4] Made some changes in response to PR comments Process named extensions (SCI, EVENTS, ACQ) --- costools/add_cos_s_region.py | 77 ++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 42 deletions(-) diff --git a/costools/add_cos_s_region.py b/costools/add_cos_s_region.py index 43d47ed..0ac4118 100644 --- a/costools/add_cos_s_region.py +++ b/costools/add_cos_s_region.py @@ -8,7 +8,6 @@ from calcos import cosutil from astropy.io import fits -__version__ = '0.1' def main(dry_run=False): """Add the S-region keyword to all COS FITS files in the current directory that meet the following criteria: @@ -22,7 +21,7 @@ def main(dry_run=False): 'rawacq.fits'] The S_REGION keyword will have the value - 'CIRCLE ra_aper dec_aper diameter' + 'CIRCLE ICRS ra_aper dec_aper diameter' where ra_aper and dec_aper are in decimal degrees and are read from the extension 1 header, and diameter = 2.5/3600.0, which is the diameter of the PSA and BOA in decimal degrees. @@ -40,50 +39,51 @@ def main(dry_run=False): 'rawacq.fits'] fitsfiles = glob.glob('*.fits') - for file in fitsfiles: + for input_file in fitsfiles: for ending in endings: - if file.endswith(ending): - add_s_region(file, dry_run) + if input_file.endswith(ending): + add_s_region(input_file, dry_run) return -def add_s_region(file, dry_run): +def add_s_region(input_file, dry_run): open_mode = 'readonly' if not dry_run: open_mode = 'update' - with fits.open(file, mode=open_mode) as f1: - if (len(f1) < 2): - cosutil.printWarning("File {} has only {} extensions".format(file, len(f1))) - cosutil.printContinuation("Need at least 2") - return + with fits.open(input_file, mode=open_mode) as f1: prihdr = f1[0].header if prihdr['INSTRUME'] != 'COS': cosutil.printWarning("File {}: Instrument is not COS".format(file)) return - - ext1hdr = f1[1].header - try: - ra_aper = ext1hdr['RA_APER'] - dec_aper = ext1hdr['DEC_APER'] - pa_aper = ext1hdr['PA_APER'] - except KeyError: - cosutil.printWarning('One or more of RA_APER, DEC_APER, PA_APER is not present') - cosutil.printContinuation('in extension 1 header of file {}'.format(file)) - return - diameter = 2.5 / 3600.0 - s_region = 'CIRCLE {0:.8f} {1:.7f} {2:.8f}'.format(ra_aper, dec_aper, diameter) - if not dry_run: - try: - existing_s_region = ext1hdr['S_REGION'] - ext1hdr['S_REGION'] = (s_region, 'Spatial extent of the observation') - cosutil.printMsg("Using existing S_REGION keyword in file {}".format(file)) - except KeyError: - ext1hdr.insert('PA_APER', ('S_REGION', s_region, 'S_region string'), after=True) - cosutil.printMsg('Added S_REGION keyword to {}'.format(file)) - cosutil.printMsg("Setting value to '{}'".format(s_region)) - else: - cosutil.printMsg("File {} has S_REGION = '{}'".format(file, s_region)) - cosutil.printMsg("Dry-run - no changes made to science header") + success = False + for n_ext, extension in enumerate(f1[1:]): + exthdr = extension.header + if exthdr['extname'] in ['SCI', 'EVENTS', 'ACQ']: + try: + ra_aper = exthdr['RA_APER'] + dec_aper = exthdr['DEC_APER'] + pa_aper = exthdr['PA_APER'] + except KeyError: + cosutil.printWarning('One or more of RA_APER, DEC_APER, PA_APER is not present') + cosutil.printContinuation('in extension {} header of file {}'.format(n_ext, input_file)) + continue + diameter = 2.5 / 3600.0 + s_region = 'CIRCLE ICRS {0:.8f} {1:.7f} {2:.8f}'.format(ra_aper, dec_aper, diameter) + if not dry_run: + try: + existing_s_region = exthdr['S_REGION'] + exthdr['S_REGION'] = s_region + cosutil.printMsg("Using existing S_REGION keyword in file {}".format(input_file)) + except KeyError: + ext1hdr.insert('PA_APER', ('S_REGION', s_region, 'Spatial extent of the observation'), after=True) + cosutil.printMsg('Added S_REGION keyword to {}'.format(input_file)) + cosutil.printMsg("Setting value to '{}'".format(s_region)) + else: + cosutil.printMsg("S_REGION for file {} = '{}'".format(input_file, s_region)) + cosutil.printMsg("Dry-run - no changes made to science header") + success = True + if not success: + cosutil.printMsg('No S_REGION keyword added to file {}'.format(input_file)) if __name__ == '__main__': @@ -95,13 +95,6 @@ def add_s_region(file, dry_run): '--dry_run', action='store_true', help="Calculate S_REGION value, but don't write to data header[s]") - parser.add_argument('-v', '--version', help='Print version info', action='version', - version = __version__) - args = parser.parse_args() - if '--version' in args: - print(__version__) - sys.exit(0) - main(dry_run=args.dry_run) From 14a96ee0ef2929eb412185e3e95c76e85d5ba8f6 Mon Sep 17 00:00:00 2001 From: Robert Jedrzejewski Date: Wed, 30 Nov 2022 09:51:03 -0500 Subject: [PATCH 3/4] Add argparse processing of rootnames, some cleanup of code --- costools/add_cos_s_region.py | 69 +++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 24 deletions(-) diff --git a/costools/add_cos_s_region.py b/costools/add_cos_s_region.py index 0ac4118..e555863 100644 --- a/costools/add_cos_s_region.py +++ b/costools/add_cos_s_region.py @@ -8,17 +8,17 @@ from calcos import cosutil from astropy.io import fits -def main(dry_run=False): - """Add the S-region keyword to all COS FITS files in the current +def main(rootnames, dry_run=False): + """Add the S-region keyword to COS FITS files in the current directory that meet the following criteria: - Filename ends with one of ['rawtag.fits', - 'rawtag_a.fits', - 'rawtag_b.fits', - 'rawaccum.fits', - 'rawaccum_a.fits', - 'rawaccum_b.fits', - 'rawacq.fits'] + ['rootname_rawtag.fits', + 'rootname_rawtag_a.fits', + 'rootname_rawtag_b.fits', + 'rootname_rawaccum.fits', + 'rootname_rawaccum_a.fits', + 'rootname_rawaccum_b.fits', + 'rootname_rawacq.fits'] The S_REGION keyword will have the value 'CIRCLE ICRS ra_aper dec_aper diameter' @@ -30,6 +30,20 @@ def main(dry_run=False): header """ + if rootnames is None: + cosutil.printError("No rootnames specified") + return + + files_to_process = get_files_to_process(rootnames) + for input_file in files_to_process: + add_s_region(input_file, dry_run) + return + +def get_files_to_process(rootnames): + """Create a list of files to process from the list of rootnames + + """ + endings = ['rawtag.fits', 'rawtag_a.fits', 'rawtag_b.fits', @@ -37,15 +51,18 @@ def main(dry_run=False): 'rawaccum_a.fits', 'rawaccum_b.fits', 'rawacq.fits'] - - fitsfiles = glob.glob('*.fits') - for input_file in fitsfiles: - for ending in endings: - if input_file.endswith(ending): - add_s_region(input_file, dry_run) - return + file_list = [] + for rootname in rootnames: + fitslist = glob.glob(rootname.lower() + '*.fits') + for input_file in fitslist: + for ending in endings: + if input_file.endswith(ending): + file_list.append(input_file) + return file_list def add_s_region(input_file, dry_run): + """Add the computed S_REGION to the keyword + """ open_mode = 'readonly' if not dry_run: open_mode = 'update' @@ -58,14 +75,16 @@ def add_s_region(input_file, dry_run): success = False for n_ext, extension in enumerate(f1[1:]): exthdr = extension.header - if exthdr['extname'] in ['SCI', 'EVENTS', 'ACQ']: + extname = exthdr['EXTNAME'] + extver = exthdr['EXTVER'] + if extname in ['SCI', 'EVENTS', 'ACQ']: try: ra_aper = exthdr['RA_APER'] dec_aper = exthdr['DEC_APER'] pa_aper = exthdr['PA_APER'] except KeyError: cosutil.printWarning('One or more of RA_APER, DEC_APER, PA_APER is not present') - cosutil.printContinuation('in extension {} header of file {}'.format(n_ext, input_file)) + cosutil.printContinuation('in extension {} header of file {}'.format(n_ext+1, input_file)) continue diameter = 2.5 / 3600.0 s_region = 'CIRCLE ICRS {0:.8f} {1:.7f} {2:.8f}'.format(ra_aper, dec_aper, diameter) @@ -73,13 +92,13 @@ def add_s_region(input_file, dry_run): try: existing_s_region = exthdr['S_REGION'] exthdr['S_REGION'] = s_region - cosutil.printMsg("Using existing S_REGION keyword in file {}".format(input_file)) + cosutil.printMsg("Using existing S_REGION keyword in {}[{}, {}]".format(input_file, extname, extver)) except KeyError: - ext1hdr.insert('PA_APER', ('S_REGION', s_region, 'Spatial extent of the observation'), after=True) - cosutil.printMsg('Added S_REGION keyword to {}'.format(input_file)) + exthdr.insert('PA_APER', ('S_REGION', s_region, 'Spatial extent of the observation'), after=True) + cosutil.printMsg('Added S_REGION keyword to {}[{}, {}]'.format(input_file, extname, extver)) cosutil.printMsg("Setting value to '{}'".format(s_region)) else: - cosutil.printMsg("S_REGION for file {} = '{}'".format(input_file, s_region)) + cosutil.printMsg("S_REGION for {}[{}, {}] = '{}'".format(input_file, extname, extver, s_region)) cosutil.printMsg("Dry-run - no changes made to science header") success = True if not success: @@ -91,10 +110,12 @@ def add_s_region(input_file, dry_run): """Add S_REGION value to raw data headers""" ) + parser.add_argument('rootnames', nargs='+', + help='Rootnames to be processed') + parser.add_argument( '--dry_run', action='store_true', help="Calculate S_REGION value, but don't write to data header[s]") args = parser.parse_args() - - main(dry_run=args.dry_run) + main(args.rootnames, dry_run=args.dry_run) From 0b76d89f7eca8ee15bb5b60266e7111f5cfe942b Mon Sep 17 00:00:00 2001 From: Robert Jedrzejewski Date: Thu, 8 Dec 2022 22:33:04 -0500 Subject: [PATCH 4/4] Added entry_point for script, a few new explanatory messages for error/ warning conditions --- costools/add_cos_s_region.py | 14 ++++++++++++-- setup.py | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/costools/add_cos_s_region.py b/costools/add_cos_s_region.py index e555863..4411cb2 100644 --- a/costools/add_cos_s_region.py +++ b/costools/add_cos_s_region.py @@ -1,7 +1,8 @@ -#! /usr/bin/env python +#!/usr/bin/env python # Add the S_REGION keyword to raw files # +import os import glob import argparse @@ -53,11 +54,17 @@ def get_files_to_process(rootnames): 'rawacq.fits'] file_list = [] for rootname in rootnames: + if os.path.basename(rootname) != rootname: + cosutil.printWarning("{}: rootnames should refer to files in the working directory".format(rootname)) fitslist = glob.glob(rootname.lower() + '*.fits') + appended = False for input_file in fitslist: for ending in endings: if input_file.endswith(ending): + appended = True file_list.append(input_file) + if not appended: + cosutil.printWarning("{}: No files found for this rootname".format(rootname)) return file_list def add_s_region(input_file, dry_run): @@ -104,7 +111,7 @@ def add_s_region(input_file, dry_run): if not success: cosutil.printMsg('No S_REGION keyword added to file {}'.format(input_file)) -if __name__ == '__main__': +def call_main(): parser = argparse.ArgumentParser( """Add S_REGION value to raw data headers""" @@ -119,3 +126,6 @@ def add_s_region(input_file, dry_run): args = parser.parse_args() main(args.rootnames, dry_run=args.dry_run) + +if __name__ == "__main__": + call_main() diff --git a/setup.py b/setup.py index 970acc3..59a590c 100755 --- a/setup.py +++ b/setup.py @@ -36,6 +36,7 @@ entry_points={ 'console_scripts': [ 'timefilter = {0}.timefilter:main'.format(PACKAGENAME), + 'add_cos_s_region = {}.add_cos_s_region:call_main'.format(PACKAGENAME), ], }, scripts=[