def test_fgs_cal_frametime(): """These tests apply to the FGS CAL apertures only. ACQ1, ACQ2, ID, TRK, and FG are not yet supported """ fgs_full = calc_frame_time('fgs', 'FGS_', 2048, 2048, 4) assert np.isclose(fgs_full, 10.73677, rtol=0., atol=1e-5) fgs_128 = calc_frame_time('fgs', 'FGS_', 128, 128, 1) assert np.isclose(fgs_128, 0.1820, rtol=0., atol=1e-5) fgs_32 = calc_frame_time('fgs', 'FGS_', 32, 32, 1) assert np.isclose(fgs_32, 0.01254, rtol=0., atol=1e-5) fgs_8 = calc_frame_time('fgs', 'FGS_', 8, 8, 1) assert np.isclose(fgs_8, 0.00126, rtol=0., atol=1e-5)
def calculate_exposure_time(self): """Calculate the total exposure time of the observation being simulated. Include time for resets between integrations Returns ------- exposure_time : float Exposure time for the total exposuure, including reset frames, in seconds """ self.frametime = utils.calc_frame_time(self.instrument, self.aperture, self.seed_dimensions[1], self.seed_dimensions[0], self.namps) return self.frametime * self.total_frames
def test_niriss_frametime(): """Test NIRISS exposure times """ nis_full = calc_frame_time('niriss', 'NIS_CEN', 2048, 2048, 4) assert np.isclose(nis_full, 10.73677, rtol=0., atol=1e-5) nis_80 = calc_frame_time('niriss', 'NIS_SUB80', 80, 80, 1) assert np.isclose(nis_80, 0.07544, rtol=0., atol=1e-5) nis_64 = calc_frame_time('niriss', 'NIS_SUBTAAMI', 64, 64, 1) assert np.isclose(nis_64, 0.05016, rtol=0., atol=1e-5) nis_wfss64r = calc_frame_time('niriss', 'NIS_WFSS64R', 64, 2048, 4) assert np.isclose(nis_wfss64r, 0.34061, rtol=0., atol=1e-5) nis_wfss64c = calc_frame_time('niriss', 'NIS_WFSS64C', 2048, 64, 1) assert np.isclose(nis_wfss64c, 1.55800, rtol=0., atol=1e-5) nis_wfss128r = calc_frame_time('niriss', 'NIS_WFSS128R', 128, 2048, 4) assert np.isclose(nis_wfss128r, 0.67597, rtol=0., atol=1e-5) nis_wfss128c = calc_frame_time('niriss', 'NIS_WFSS128C', 2048, 128, 1) assert np.isclose(nis_wfss128c, 2.87000, rtol=0., atol=1e-5)
def test_nircam_frametime(): """Test NIRCam exposure times """ nrc_full = calc_frame_time('nircam', 'NRCA1_FULL', 2048, 2048, 4) assert np.isclose(nrc_full, 10.73677, rtol=0., atol=1e-5) nrc_640 = calc_frame_time('nircam', 'NRCA1_SUB640', 640, 640, 1) assert np.isclose(nrc_640, 4.18584, rtol=0., atol=1e-5) nrc_320 = calc_frame_time('nircam', 'NRCA1_SUB320', 320, 320, 1) assert np.isclose(nrc_320, 1.06904, rtol=0., atol=1e-5) nrc_160 = calc_frame_time('nircam', 'NRCA1_SUB160', 160, 160, 1) assert np.isclose(nrc_160, 0.27864, rtol=0., atol=1e-5) nrc_64 = calc_frame_time('nircam', 'NRCB4_SUB64P', 64, 64, 1) assert np.isclose(nrc_64, 0.05016, rtol=0., atol=1e-5) nrc_32 = calc_frame_time('nircam', 'NRC_SUB32TATS', 32, 32, 1) assert np.isclose(nrc_32, 0.01496, rtol=0., atol=1e-5) nrc_subgrism256_1 = calc_frame_time('nircam', 'NRC_SUBGRISM256', 2048, 256, 1) print(nrc_subgrism256_1, 5.31480) #assert np.isclose(nrc_subgrism256_1, 5.29420, rtol=0., atol=1e-5) nrc_subgrism256_4 = calc_frame_time('nircam', 'NRC_SUBGRISM256', 2048, 256, 4) print(nrc_subgrism256_4, 1.34669) #assert np.isclose(nrc_subgrism256_4, 1.34669, rtol=0., atol=1e-5) nrc_subgrism128_1 = calc_frame_time('nircam', 'NRC_SUBGRISM128', 2048, 128, 1) print(nrc_subgrism128_1, 2.67800) #assert np.isclose(nrc_subgrism128_1, 2.6574, rtol=0., atol=1e-5) nrc_subgrism128_4 = calc_frame_time('nircam', 'NRC_SUBGRISM128', 2048, 128, 4) assert np.isclose(nrc_subgrism128_4, 0.67597, rtol=0., atol=1e-5) nrc_subgrism64_1 = calc_frame_time('nircam', 'NRC_SUBGRISM64', 2048, 64, 1) assert np.isclose(nrc_subgrism64_1, 1.35960, rtol=0., atol=1e-5) nrc_subgrism64_4 = calc_frame_time('nircam', 'NRC_SUBGRISM64', 2048, 64, 4) assert np.isclose(nrc_subgrism64_4, 0.34061, rtol=0., atol=1e-5)
def validate(xml_file, output_dir, gseg_uncal_files): """MAIN FUNCTION""" pointing_file = xml_file.replace('.xml', '.pointing') gseg_rate_files = [f.replace('uncal', 'rate') for f in gseg_uncal_files] catalogs = {'nircam': {'sw': 'nothing.cat', 'lw': 'nothing.cat'}} observation_list_file = os.path.join(output_dir, 'observation_list.yaml') apt_xml_dict = get_observation_dict(xml_file, observation_list_file, catalogs, verbose=True) observation_list = set(apt_xml_dict['ObservationID']) int_obs = sorted([int(o) for o in observation_list]) str_obs_list = [str(o).zfill(3) for o in int_obs] for observation_to_check in str_obs_list: print('') print('') print('OBSERVATION: {}'.format(observation_to_check)) print('') good = np.where( np.array(apt_xml_dict['ObservationID']) == observation_to_check) try: total_expected_files = calculate_total_files( apt_xml_dict, good[0][0]) print('Total number of expected files: {}'.format( total_expected_files)) except IndexError: print("No files found.") continue # The complication here is that the table created by Mirage does not have a filename # attached to each entry. So we need a way to connect an actual filename # to each entry subdir_start = 'jw' + apt_xml_dict['ProposalID'][ good[0][0]] + observation_to_check.zfill(3) matching_uncal_files = sorted([ filename for filename in gseg_uncal_files if subdir_start in filename ]) matching_rate_files = sorted([ filename for filename in gseg_rate_files if subdir_start in filename ]) print('Found uncal files:') for i in range(len(matching_uncal_files)): print(matching_uncal_files[i]) print('') print('Found rate files:') for i in range(len(matching_rate_files)): print(matching_rate_files[i]) print('') # Check to see if any files are missing if len(matching_uncal_files) != total_expected_files: print( "WARNING: Missing uncal files for observation {}. Expected {} files, found {}." .format(observation_to_check, total_expected_files, len(matching_uncal_files))) if len(matching_rate_files) != total_expected_files: print( "WARNING: Missing rate files for observation {}. Expected {} files, found {}." .format(observation_to_check, total_expected_files, len(matching_rate_files))) # Deal with the case of matching_uncal_files and matching_rate_files having # different lengths here. In order to loop over them they must have the same length if len(matching_uncal_files) != len(matching_rate_files): (matching_uncal_files, matching_rate_files) = equalize_file_lists( matching_uncal_files, matching_rate_files) print('Equalized file lists (should have a 1:1 correspondence):') for idx in range(len(matching_uncal_files)): print(matching_uncal_files[idx], matching_rate_files[idx]) # Create siaf instance for later calculations siaf = pysiaf.Siaf('NIRCam') for uncal, rate in zip(matching_uncal_files, matching_rate_files): good_uncal = uncal != None good_rate = rate != None if good_uncal: print("Checking {}".format(os.path.split(uncal)[1])) print('-----------------------------------------------') elif good_rate: print("Checking {}".format(os.path.split(rate)[1])) print('-----------------------------------------------') if good_uncal: data, header, sci_header = get_data(uncal) detector_from_filename = uncal.split('_')[-2].upper() header_detector = header['DETECTOR'] if 'LONG' in header_detector: header_detector = header_detector.replace('LONG', '5') if header_detector not in header['APERNAME']: print(( "WARNING: Detector name and aperture name in file header appear to be incompatible: {}, {}" .format(header['DETECTOR'], header['APERNAME']))) print("Detector listed in filename: {}".format( detector_from_filename)) print( 'If the aperture is incorrect then the calculated subarray location from pysiaf will also be incorrect.' ) data_shape = data.shape # Get info from header to be compared header_vals = uncal_header_keywords(header) # Get matching data from the exposure table table_vals = uncal_table_info(apt_xml_dict, good[0][0]) # Make some adjustments to the exposure table info # Calucate the exposure time aperture = header[ 'APERNAME'] # could also try APERNAME, PPS_APER print('Aperture listed in header is: {}'.format(aperture)) num_amps = 1 frametime = calc_frame_time('NIRCam', aperture, data_shape[-1], data_shape[-2], num_amps) table_vals['EFFEXPTM'] = frametime * int(table_vals['NGROUPS']) # NAXIS table_vals['NAXIS'] = len(data.shape) header_vals['NAXIS'] = sci_header['NAXIS'] # Use pysiaf to calculate subarray locations try: xc, yc = sci_subarray_corners('NIRCam', aperture, siaf=siaf) table_vals['SUBSTRT1'] = xc[0] + 1 table_vals['SUBSTRT2'] = yc[0] + 1 table_vals['SUBSIZE1'] = siaf[aperture].XSciSize table_vals['SUBSIZE2'] = siaf[aperture].YSciSize except KeyError: print( "ERROR: Aperture {} is not a valid aperture in pysiaf". format(aperture)) xc = [-2, -2] yc = [-2, -2] table_vals['SUBSTRT1'] = xc[0] + 1 table_vals['SUBSTRT2'] = yc[0] + 1 table_vals['SUBSIZE1'] = 9999 table_vals['SUBSIZE2'] = 9999 # Create FASTAXIS and SLOWAXIS values based on the detector name fast, slow = find_fastaxis(header_vals['DETECTOR']) table_vals['FASTAXIS'] = fast table_vals['SLOWAXIS'] = slow # Remove whitespace from observing template in file header_vals['TEMPLATE'] = header_vals['TEMPLATE'].replace( ' ', '').lower() table_vals['TEMPLATE'] = table_vals['TEMPLATE'].lower() # Adjust prime/parallel boolean from table to be a string if not table_vals['EXPRIPAR']: table_vals['EXPRIPAR'] = 'PRIME' else: table_vals['EXPRIPAR'] = 'PARALLEL' # Change exposure type from table to match up with # types of strings in the file table_vals['EXP_TYPE'] = adjust_exptype(table_vals['EXP_TYPE']) # Set the DETECTOR field to be identical. This info is not in the # exposure table, so we can't actually check it table_vals['DETECTOR'] = header_vals['DETECTOR'] # Compare the actual data shape to the shape given in the header header_shape = (header_vals['NINTS'], header_vals['NGROUPS'], header_vals['SUBSIZE2'], header_vals['SUBSIZE1']) if header_shape != data_shape: print( "WARNING: Shape of data in the file does not match that specified in the header." ) print('Data shape: {}'.format(data_shape)) print('Header shape: {}'.format(header_shape)) # Now compare the data in the dictionary from the file versus that # from the exposure table created from the APT file err = False for key in header_vals: if header_vals[key] != table_vals[key]: if key not in FLOAT_KEYWORDS and key not in FILTER_KEYWORDS: err = True print( 'MISMATCH: {}, in exp table: {}, in file: {}'. format(key, table_vals[key], header_vals[key])) elif key in FLOAT_KEYWORDS: if not np.isclose(header_vals[key], table_vals[key], rtol=0.01, atol=0.): err = True print( 'MISMATCH: {}, in exp table: {}, in file: {}' .format(key, table_vals[key], header_vals[key])) if key in ['LONGFILTER', 'LONGPUPIL' ] and 'LONG' in header_vals['DETECTOR']: err = True print( 'MISMATCH: {}, in exp table: {}, in file: {}'. format(key, table_vals[key], header_vals[key])) if key in ['SHORTFILTER', 'SHORTPUPIL' ] and 'LONG' not in header_vals['DETECTOR']: err = True print( 'MISMATCH: {}, in exp table: {}, in file: {}'. format(key, table_vals[key], header_vals[key])) if not err: print('No inconsistencies. File header info correct.') print('') print('')