def __init__(self, offline=False): """Instantiate DarkPrep object. Parameters ---------- offline : bool If True, the check for the existence of the MIRAGE_DATA directory is skipped. This is primarily for Travis testing """ self.offline = offline # Locate the module files, so that we know where to look # for config subdirectory self.modpath = pkg_resources.resource_filename('mirage', '') # Get the location of the MIRAGE_DATA environment # variable, so we know where to look for darks, CR, # PSF files, etc later self.env_var = 'MIRAGE_DATA' datadir = utils.expand_environment_variable(self.env_var, offline=offline) # Check that CRDS-related environment variables are set correctly self.crds_datadir = crds_tools.env_variables()
def confirm_gridded_properties(filename, instrument, detector, filtername, pupilname, wavefront_error_type, wavefront_error_group, file_path, extname='PRIMARY'): """Examine the header of the gridded PSF model file to confirm that the properties of the data match those expected. Parameters ---------- filename : str Base name of the PSF library file to be checked instrument : str Name of instrument the PSFs are from detector : str Name of the detector within ```instrument``` filtername : str Name of filter used for PSF library creation pupilname : str Name of pupil wheel element used for PSF library creation wavefront_error_type : str Wavefront error. Can be 'predicted' or 'requirements' wavefront_error_group : int Wavefront error realization group. Must be an integer from 0 - 9. file_path : str Path pointing to the location of the PSF library extname : str Name of the extension within ``filename`` to check Returns ------- full_filename : str Full path and filename if the file properties are as expected. None if the properties do not match. """ # Determine if the PSF path is default or not mirage_dir = expand_environment_variable('MIRAGE_DATA') default_psf = file_path == os.path.join( mirage_dir, '{}/gridded_psf_library'.format(instrument.lower())) full_filename = os.path.join(file_path, filename) with fits.open(full_filename) as hdulist: header = hdulist[extname.upper()].header inst = header['INSTRUME'] try: det = header['DETECTOR'] except KeyError: det = header['DET_NAME'] filt = header['FILTER'] try: pupil = header['PUPIL'] except KeyError: # If no pupil mask value is present, then assume the CLEAR is # being used if instrument.upper() == 'NIRCAM': pupil = 'CLEAR' elif instrument.upper() == 'NIRISS': pupil = 'CLEARP' # NIRISS has many filters in the pupil wheel. WebbPSF does # not make a distinction, but Mirage does. Adjust the info # to match Mirage's expectations if inst.upper() == 'NIRISS' and filt in NIRISS_PUPIL_WHEEL_FILTERS: save_filt = copy(filt) if pupil == 'CLEARP': filt = 'CLEAR' else: raise ValueError(('Pupil value is something other than ' 'CLEARP, but the filter being used is ' 'in the pupil wheel.')) pupil = save_filt # Same for NIRCam if inst.upper() == 'NIRCAM' and filt in NIRCAM_PUPIL_WHEEL_FILTERS: save_filt = copy(filt) if pupil == 'CLEAR': if save_filt[0:2] == 'F4': filt = 'F444W' elif save_filt[0:2] == 'F3': filt = 'F322W2' elif save_filt[0:2] == 'F1': filt = 'F150W2' else: raise ValueError(('Pupil value is something other than ' 'CLEAR, but the filter being used is ' 'in the pupil wheel.')) pupil = save_filt opd_file = header['OPD_FILE'] if default_psf: if 'predicted' in opd_file: wfe_type = 'predicted' elif 'requirements' in opd_file: wfe_type = 'requirements' realization = header['OPDSLICE'] # make the check below pass for FGS if instrument.lower() == 'fgs': pupil = 'N/A' pupilname = 'N/A' filt = 'N/A' filtername = 'N/A' match = inst.lower() == instrument.lower() and \ det.lower() == detector.lower() and \ filt.lower() == filtername.lower() and \ pupil.lower() == pupilname.lower() if match and not default_psf: return full_filename elif match and wfe_type == wavefront_error_type.lower() and \ realization == wavefront_error_group: return full_filename else: return None
def get_library_file(instrument, detector, filt, pupil, wfe, wfe_group, library_path, wings=False, segment_id=None): """Given an instrument and filter name along with the path of the PSF library, find the appropriate library file to load. Parameters ----------- instrument : str Name of instrument the PSFs are from detector : str Name of the detector within ```instrument``` filt : str Name of filter used for PSF library creation pupil : str Name of pupil wheel element used for PSF library creation wfe : str Wavefront error. Can be 'predicted' or 'requirements' wfe_group : int Wavefront error realization group. Must be an integer from 0 - 9. library_path : str Path pointing to the location of the PSF library wings : bool, optional Must the library file contain PSF wings or PSF cores? Default is False. segment_id : int or None, optional If specified, returns a segment PSF library file and denotes the ID of the mirror segment Returns -------- matches : str Name of the PSF library file for the instrument and filter name """ logger = logging.getLogger('mirage.psf.psf_selection.get_library_file') psf_files = glob(os.path.join(library_path, '*.fits')) # Determine if the PSF path is default or not mirage_dir = expand_environment_variable('MIRAGE_DATA') gridded_dir = os.path.join( mirage_dir, '{}/gridded_psf_library'.format(instrument.lower())) if wings: gridded_dir = os.path.join(gridded_dir, 'psf_wings') default_psf = library_path == gridded_dir # Create a dictionary of header information for all PSF library files matches = [] instrument = instrument.upper() detector = detector.upper() filt = filt.upper() pupil = pupil.upper() wfe = wfe.lower() # set default file_wfe = '' # handle the NIRISS NRM case if pupil == 'NRM': pupil = 'MASK_NRM' # Handle the DHS for Coarse Phasing - this is a workaround for webbpsf not # implementing this. We're going to load an ITM image in any case in this mode # so the PSF is entirely unused, but we need to load something or else MIRAGE errors. if pupil == 'GDHS0' or pupil == 'GDHS60': pupil = 'CLEAR' for filename in psf_files: try: header = fits.getheader(filename) # Determine if it is an ITM file itm_sim = header.get('ORIGIN', '') == 'ITM' # Compare the header entries to the user input file_inst = header['INSTRUME'].upper() try: file_det = header['DETECTOR'].upper() except KeyError: file_det = header['DET_NAME'].upper() file_filt = header['FILTER'].upper() try: file_pupil = header['PUPIL'].upper() except KeyError: # If no pupil mask value is present, then assume the CLEAR is # being used if file_inst.upper() == 'NIRCAM': file_pupil = 'CLEAR' elif file_inst.upper() == 'NIRISS': try: file_pupil = header['PUPIL'].upper( ) # can be 'MASK_NRM' except KeyError: file_pupil = 'CLEARP' # NIRISS has many filters in the pupil wheel. WebbPSF does # not make a distinction, but Mirage does. Adjust the info # to match Mirage's expectations if file_inst.upper( ) == 'NIRISS' and file_filt in NIRISS_PUPIL_WHEEL_FILTERS: save_filt = copy(file_filt) if file_pupil == 'CLEARP': file_filt = 'CLEAR' else: raise ValueError(('Pupil value is something other than ' 'CLEARP, but the filter being used is ' 'in the pupil wheel.')) file_pupil = save_filt # Same for NIRCam if file_inst.upper( ) == 'NIRCAM' and file_filt in NIRCAM_PUPIL_WHEEL_FILTERS: save_filt = copy(file_filt) if file_pupil == 'CLEAR': if save_filt[0:2] == 'F4': file_filt = 'F444W' elif save_filt[0:2] == 'F3': file_filt = 'F322W2' elif save_filt[0:2] == 'F1': file_filt = 'F150W2' else: raise ValueError(('Pupil value is something other than ' 'CLEAR, but the filter being used is ' 'in the pupil wheel.')) file_pupil = save_filt if segment_id is None and not itm_sim: opd = header['OPD_FILE'] if 'requirements' in opd: file_wfe = 'requirements' elif 'predicted' in opd: file_wfe = 'predicted' file_wfe_grp = header['OPDSLICE'] if segment_id is not None: segment_id = int(segment_id) file_segment_id = int(header['SEGID']) if segment_id is None and itm_sim: # If we have an ITM library, then wfe is # meaningless, so force it to match file_wfe = 'predicted' wfe = 'predicted' # allow check below to pass for FGS if instrument.lower() == 'fgs': file_filt = 'N/A' filt = 'N/A' file_pupil = 'N/A' pupil = 'N/A' # Evaluate if the file matches the given parameters match = (file_inst == instrument and file_det == detector and file_filt == filt and file_pupil == pupil and file_wfe == wfe) if not wings and segment_id is None and not itm_sim and default_psf: match = match and file_wfe_grp == wfe_group if segment_id is not None: match = match and file_segment_id == segment_id elif not itm_sim and default_psf: match = match and file_wfe == wfe # If so, add to the list of all matches if match: matches.append(filename) except KeyError as e: warnings.warn( 'While searching for PSF file, error raised when examining {}:\n{}\nContinuing.' .format(os.path.basename(filename), e)) continue # Find files matching the requested inputs if len(matches) == 1: return matches[0] elif len(matches) == 0: logger.info( 'Requested parameters:\ninstrument {}\ndetector {}\nfilt {}\npupil {}\nwfe {}\n' 'wfe_group {}\nlibrary_path {}\n'.format(instrument, detector, filt, pupil, wfe, wfe_group, library_path)) raise ValueError( "No PSF library file found matching requested parameters.") elif len(matches) > 1: raise ValueError( "More than one PSF library file matches requested parameters: {}". format(matches))
#! /usr/bin/env python """Create test RA, Dec data to be used in test_ra_dec_to_x_y.py. Travis does not have access to the reference files, so this must be done manually, and the results placed into test_ra_dec_to_x_y.py. """ import asdf import glob import os import numpy as np import pysiaf from mirage.seed_image import catalog_seed_image from mirage.utils import siaf_interface from mirage.utils.utils import expand_environment_variable data_dir = expand_environment_variable('MIRAGE_DATA', offline=False) instruments = ['nircam', 'niriss', 'fgs'] xyvals = {} # Create list of points at which to calculate x, y pointing_ra = 12.0 pointing_dec = 12.0 rotation = 0.0 ra_list = [] dec_list = [] delta_pix = np.array([0, 10, 20, 40, 75, 180, 500, 1000]) delta_deg = delta_pix * 0.031 / 3600. for delta in delta_deg: ra_entry = pointing_ra + delta dec_entry = pointing_dec + delta ra_list.append(ra_entry)
def get_library_file(instrument, detector, filt, pupil, wfe, wfe_group, library_path, wings=False, segment_id=None): """Given an instrument and filter name along with the path of the PSF library, find the appropriate library file to load. Parameters ----------- instrument : str Name of instrument the PSFs are from detector : str Name of the detector within ```instrument``` filt : str Name of filter used for PSF library creation pupil : str Name of pupil wheel element used for PSF library creation wfe : str Wavefront error. Can be 'predicted' or 'requirements' wfe_group : int Wavefront error realization group. Must be an integer from 0 - 9. library_path : str Path pointing to the location of the PSF library wings : bool, optional Must the library file contain PSF wings or PSF cores? Default is False. segment_id : int or None, optional If specified, returns a segment PSF library file and denotes the ID of the mirror segment Returns -------- matches : str Name of the PSF library file for the instrument and filter name """ psf_files = glob(os.path.join(library_path, '*.fits')) # Determine if the PSF path is default or not mirage_dir = expand_environment_variable('MIRAGE_DATA') default_psf = library_path == os.path.join( mirage_dir, '{}/gridded_psf_library'.format(instrument.lower())) # Create a dictionary of header information for all PSF library files matches = [] instrument = instrument.upper() detector = detector.upper() filt = filt.upper() pupil = pupil.upper() wfe = wfe.lower() # handle the NIRISS NRM case if pupil == 'NRM': pupil = 'MASK_NRM' for filename in psf_files: try: header = fits.getheader(filename) # Determine if it is an ITM file itm_sim = header.get('ORIGIN', '') == 'ITM' # Compare the header entries to the user input file_inst = header['INSTRUME'].upper() file_det = header['DETECTOR'].upper() file_filt = header['FILTER'].upper() try: file_pupil = header['PUPIL_MASK'].upper() except KeyError: # If no pupil mask value is present, then assume the CLEAR is # being used if file_inst.upper() == 'NIRCAM': file_pupil = 'CLEAR' elif file_inst.upper() == 'NIRISS': try: file_pupil = header['PUPIL'].upper( ) # can be 'MASK_NRM' except KeyError: file_pupil = 'CLEARP' # NIRISS has many filters in the pupil wheel. WebbPSF does # not make a distinction, but Mirage does. Adjust the info # to match Mirage's expectations if file_inst.upper( ) == 'NIRISS' and file_filt in NIRISS_PUPIL_WHEEL_FILTERS: save_filt = copy(file_filt) if file_pupil == 'CLEARP': file_filt = 'CLEAR' else: raise ValueError(('Pupil value is something other than ' 'CLEARP, but the filter being used is ' 'in the pupil wheel.')) file_pupil = save_filt if segment_id is None and not itm_sim: opd = header['OPD_FILE'] if 'requirements' in opd: file_wfe = 'requirements' elif 'predicted' in opd: file_wfe = 'predicted' file_wfe_grp = header['OPDSLICE'] if segment_id is not None: segment_id = int(segment_id) file_segment_id = int(header['SEGID']) # allow check below to pass for FGS if instrument.lower() == 'fgs': file_filt = 'N/A' filt = 'N/A' file_pupil = 'N/A' pupil = 'N/A' # Evaluate if the file matches the given parameters match = (file_inst == instrument and file_det == detector and file_filt == filt and file_pupil == pupil) if not wings and segment_id is None and not itm_sim and default_psf: match = match and file_wfe_grp == wfe_group if segment_id is not None: match = match and file_segment_id == segment_id elif not itm_sim and default_psf: match = match and file_wfe == wfe # If so, add to the list of all matches if match: matches.append(filename) except KeyError: continue # Find files matching the requested inputs if len(matches) == 1: return matches[0] elif len(matches) == 0: raise ValueError( "No PSF library file found matching requested parameters.") elif len(matches) > 1: raise ValueError( "More than one PSF library file matches requested parameters: {}". format(matches))