Source code for pypeit.scripts.obslog

"""
This script generates an "observing log" for a directory with a set of files
to be reduced by PypeIt.

.. include common links, assuming primary doc root is up one directory
.. include:: ../include/links.rst
"""
import time
import os

from IPython import embed

import numpy as np

from pypeit.spectrographs import available_spectrographs
from pypeit.scripts import scriptbase


[docs]class ObsLog(scriptbase.ScriptBase):
[docs] @classmethod def get_parser(cls, width=None): parser = super().get_parser(description='Construct an observing log for a set of files ' 'from the provided spectrograph using ' 'PypeItMetaData.', width=width) parser.add_argument('spec', type=str, help='A valid spectrograph identifier: {0}'.format( ', '.join(available_spectrographs))) parser.add_argument('-r', '--root', default='current working directory', type=str, help='Root to search for data files. You can provide the top-level ' 'directory (e.g., /data/Kast) or the search string up through ' 'the wildcard (.e.g, /data/Kast/b). Use the --extension option ' 'to set the types of files to search for.') parser.add_argument('-k', '--keys', default=False, action='store_true', help='Do not produce the log; simply list the pypeit-specific ' 'metadata keys available for this spectrograph and their ' 'associated header cards. Metadata keys with header cards that ' 'are None have no simple mapping between keyword and header ' 'card.') parser.add_argument('-c', '--columns', default='pypeit', type=str, help='A comma-separated list of columns to include in the output ' 'table. Each column must be a valid pypeit metadata keyword ' 'specific to this spectrograph (run pypeit_obslog with the -k ' 'argument to see the valid list). Additional valid keywords ' 'are directory, filename, frametype, framebit, setup, calib, ' 'and calibbit. If \'all\', all columns collected for the pypeit ' 'metadata table are included. If \'pypeit\', the columns are ' 'the same as those included in the pypeit file.') parser.add_argument('-b', '--bad_frames', default=False, action='store_true', help='Clean the output of bad frames that cannot be reduced by pypeit.') parser.add_argument('-t', '--bad_types', default='keep', type=str, help='Dictates how frames that could not be given a valid type should ' 'be treated. Options are: "keep" to include them in the output, ' '"rm" to remove them from the output, "only" to only include the ' 'frames with unknown types in the output (i.e, the frames with ' 'determined types are excluded).') parser.add_argument('-g', '--groupings', default=True, action='store_false', help='Use this option to only determine the frame type. By default, ' 'the script groups frames into expected configuration and ' 'calibration groups, and it adds the default combination groups.') parser.add_argument('-i', '--interact', default=False, action='store_true', help='Once the metadata table is created, start an embedded IPython ' 'session that you can use to interact with the table (an ' 'Astropy.Table called fitstbl) directly.') parser.add_argument('-s', '--sort', default='mjd', type=str, help='Metadata keyword (pypeit-specific) to use to sort the output ' 'table.') parser.add_argument('-e', '--extension', default='.fits', help='File extension; compression indicators (e.g. .gz) not required.') parser.add_argument('-d', '--output_path', default='current working directory', help='Path to top-level output directory.') parser.add_argument('-o', '--overwrite', default=False, action='store_true', help='Overwrite any existing files/directories') parser.add_argument('-f', '--file', default=None, type=str, help='Name for the ascii output file. Any leading directory path is ' 'stripped; use -d to set the output directory. If None, the ' 'table is just printed to stdout. If set to \'default\', the ' 'file is set to [spectrograph].obslog. Note the file will *not* ' 'be written if you also include the -i option to embed and ' 'interact with the table (you can write the table using the ' 'astropy.table.Table.write method in the embedded IPython ' 'session). The table is always written in ascii format using ' 'format=ascii.fixed_with for the call to ' 'Astropy.table.Table.write .') parser.add_argument('-G','--gui', default=False, action='store_true', help='View the obs log in a GUI') return parser
[docs] @staticmethod def main(args): from pypeit.spectrographs.util import load_spectrograph from pypeit.pypeitsetup import PypeItSetup # Check that input spectrograph is supported if args.spec not in available_spectrographs: raise ValueError('Instrument \'{0}\' unknown to PypeIt.\n'.format(args.spec) + '\tOptions are: {0}\n'.format(', '.join(available_spectrographs)) + '\tSelect an available instrument or consult the documentation ' + 'on how to add a new instrument.') if args.gui: from pypeit.scripts.setup_gui import SetupGUI gui_args = SetupGUI.parse_args(["-s", args.spec, "-r", args.root, "-e", args.extension]) SetupGUI.main(gui_args) if args.keys: # Only print the metadata to header card mapping load_spectrograph(args.spec).meta_key_map() return if args.bad_types not in ['keep', 'rm', 'only']: raise ValueError(f'{args.bad_types} is not a valid keyword for the --bad_types ' f'argument.') # Generate the metadata table ps = PypeItSetup.from_file_root(args.root, args.spec, extension=args.extension) ps.run(setup_only=True, # This allows for bad headers groupings=args.groupings, clean_config=args.bad_frames) # Check the file can be written (this is here because the spectrograph # needs to be defined first) _file = args.file if _file == 'default': _file = f'{ps.spectrograph.name}.obslog' if _file is not None: _odir, _file = os.path.split(_file) _file = os.path.join(args.output_path, _file) if not os.path.isdir(args.output_path): os.makedirs(args.output_path) if not args.interact and os.path.isfile(_file) and not args.overwrite: raise FileExistsError(f'{_file} already exists. Use -o to overwrite.') # Write/Print the data #'{0}'.format(time.strftime("%a %d %b %Y %H:%M:%S",time.localtime())), header = ['Auto-generated PypeIt Observing Log', '{0}'.format(time.strftime("%Y-%m-%d",time.localtime())), f'Root file string: {args.root}'] if args.bad_types == 'keep': nrows = len(ps.fitstbl) indx = np.ones(nrows, dtype=bool) elif args.bad_types == 'rm': indx = ps.fitstbl['frametype'] != 'None' elif args.bad_types == 'only': indx = ps.fitstbl['frametype'] == 'None' else: raise ValueError('CODING ERROR: Should never get here.') fitstbl = ps.fitstbl.write(output='table' if args.interact else _file, rows=indx, columns=args.columns, sort_col=args.sort, overwrite=args.overwrite, header=header) if args.interact: embed()