Example #1
0
def combine_per_camera_catalogs(catalogs):
    # catalogs is the output of GFA_exposure's all_source_catalogs() method
    # which is a dictionary of astropy QTable's, with the keys
    # being the GFA camera extension names

    # want to add a column to each table giving the GFA camera name, then
    # append the all into one per-exposure table

    assert(type(catalogs).__name__ == 'dict')

    composite_list = []
    for extname, tab in catalogs.items():
        if tab is not None:
            tab['camera'] = extname
            tab['petal_loc'] = np.array([common.gfa_extname_to_gfa_number(extname) for extname in tab['camera']], dtype='uint8')
            composite_list.append(tab)

    # handle case of no sources in any image
    if len(composite_list) == 0:
        return None
    
    composite = vstack(composite_list)
    composite = strip_none_columns(composite)

    composite['extname'] = composite['camera']
    return composite
Example #2
0
    def psf_image_header(self, hdu):
        
         hdu.header['EXTNAME'] = self.extname
         hdu.header['PETALLOC'] = common.gfa_extname_to_gfa_number(self.extname)
         hdu.header['NSTARS'] = self.nstars
         hdu.header['FIBFRAC'] = self.fiber_fracflux if np.isfinite(self.fiber_fracflux) else 0.0 # ??
         hdu.header['EXPID'] = self.im_header['EXPID']
         hdu.header['CBOX'] = self.cbox
         hdu.header['CFAILED'] = self.psf_centroiding_failed

         if self.cube_index is not None:
             hdu.header['CUBE_IND'] = self.cube_index

         # guide*.fits.fz GUIDE? extensions apparently don't have NIGHT
         # or any other date-related information available
         if 'NIGHT' in self.im_header:
             hdu.header['NIGHT'] = self.im_header['NIGHT']
Example #3
0
    def to_hdu(self, primary=False, flavor=''):
        # convert this image to an HDU

        # currently expect flavor to be one of
        #     REDUCED - reduced image
        #     BITMASK - data quality bitmask
        #     INVVAR - inverse variance image
        #     DETMAP - detection significance map

        # if no flavor is specified then assume ".image" attribute is desired
        # data for this HDU

        f = (fits.PrimaryHDU if primary else fits.ImageHDU)

        if (flavor == '') or (flavor == 'REDUCED'):
            hdu = f(self.image.astype('float32'), header=self.header)
        elif (flavor == 'BITMASK'):
            hdu = f(self.bitmask.astype('int'), header=self.header)
            hdu.header = dq_mask.add_dq_bitmask_header_cards(hdu.header)
        elif (flavor == 'INVVAR'):
            hdu = f(self.ivar_adu.astype('float32'), header=self.header)
        elif (flavor == 'DETMAP'):
            assert(self.detmap is not None)
            hdu = f(self.detmap.astype('float32'), header=self.header)

        hdu.header['FLAVOR'] = flavor

        gain = common.gfa_camera_gain(self.extname)
        hdu.header['GAINA'] = (gain, '[e-/ADU] assumed gain')

        hdu.header['BUNIT'] = common.reduced_flavor_to_bunit(flavor)

        petal_loc = common.gfa_extname_to_gfa_number(self.extname)
        hdu.header['PETALLOC'] = (petal_loc, 'petal number')

        return hdu
Example #4
0
def assemble_ccds_table(tab, catalog, exp, outdir, proc_obj, cube_index=None,
                        ps1=None, det_sn_thresh=5.0, sky_mags=True,
                        minimal=False, mjdrange=None):

    nrows = len(tab)

    tab['extname'] = tab['camera']

    tab['contrast'] = [exp.images[extname].header['CONTRAST'] for extname in tab['camera']]

    if minimal:
        return tab

    if sky_mags:
        tab['sky_mag_ab'] = [exp.images[extname].sky_mag for extname in tab['camera']]
        tab['sky_mag_ab_subregion'] = [exp.images[extname].sky_mag_upper for extname in tab['camera']]

    amps = common.valid_amps_list()

    if sky_mags:
        sky_mag_ab_per_amp = np.zeros((nrows, len(amps)), dtype='float32') # 4 amps
        for i, extname in enumerate(tab['camera']):
            for j in range(len(amps)):
                _mag = np.nan if exp.images[extname].sky_mag_per_amp is None else exp.images[extname].sky_mag_per_amp[j]
                sky_mag_ab_per_amp[i, j] = _mag

        tab['sky_mag_ab_per_amp'] = sky_mag_ab_per_amp
    
    tab['petal_loc'] = np.array([common.gfa_extname_to_gfa_number(extname) for extname in tab['camera']], dtype='uint8')

    tab['expid'] = [exp.images[extname].header['EXPID'] for extname in tab['camera']]

    # should work except if early versions of guide cubes lacked
    # MJD information...
    tab['mjd'] = [exp.images[extname].try_retrieve_meta_keyword('MJD-OBS', placeholder=0.0) for extname in tab['camera']]

    eph = util.load_lst()
    tab['lst_deg'] = [util.interp_ephemeris(t['mjd'], eph=eph) for t in tab]
    tab['moon_illumination'] = [util.interp_ephemeris(t['mjd'], eph=eph, colname='MPHASE') for t in tab]

    tab['program'] = [str(exp.images[extname].try_retrieve_meta_keyword('PROGRAM', placeholder='')) for extname in tab['camera']]

    tab['skyra'] = [exp.images[extname].try_retrieve_meta_keyword('SKYRA', placeholder=np.nan) for extname in tab['camera']]

    tab['skydec'] = [exp.images[extname].try_retrieve_meta_keyword('SKYDEC', placeholder=np.nan) for extname in tab['camera']]
    
    # zenith distance using approximate center of the field given by SKYRA, SKYDEC

    tab['zenith_dist_deg'] = [util._zenith_distance(t['skyra'], t['skydec'], t['lst_deg']) for t in tab]
    
    tab['domshutl'] = np.array(nrows*[exp.try_retrieve_header_card('DOMSHUTL', placeholder='')], dtype='U8')
    tab['domshutu'] = np.array(nrows*[exp.try_retrieve_header_card('DOMSHUTU', placeholder='')], dtype='U8')
    tab['pmcover'] = exp.try_retrieve_header_card('PMCOVER', placeholder='')
    tab['moonra'] = exp.try_retrieve_header_card('MOONRA', placeholder=np.nan)
    tab['moondec'] = exp.try_retrieve_header_card('MOONDEC', placeholder=np.nan)

    if np.isnan(tab['moonra'][0]):
        tab['moonra'] = util.interp_ephemeris(tab['mjd'][0], eph=eph,
                                              colname='MOONRA')
    if np.isnan(tab['moondec'][0]):
        tab['moondec'] = util.interp_ephemeris(tab['mjd'][0], eph=eph,
                                               colname='MOONDEC')

    tab['moon_zd_deg'] = util._zenith_distance(tab['moonra'][0],
                                               tab['moondec'][0],
                                               tab['lst_deg'][0])
    
    tab['t_c_for_dark'] = [exp.images[extname].t_c_for_dark for extname in tab['camera']]
    tab['t_c_for_dark_is_guess'] = [int(exp.images[extname].t_c_for_dark_is_guess) for extname in tab['camera']]
    tab['time_s_for_dark'] = [exp.images[extname].time_s_for_dark for extname in tab['camera']]

    tab['night'] = exp.try_retrieve_header_card('NIGHT', placeholder='')

    tab['focus'] = exp.try_retrieve_header_card('FOCUS', placeholder='')

    tab['exptime'] = [exp.images[extname].try_retrieve_meta_keyword('EXPTIME', placeholder=np.nan) for extname in tab['camera']]

    # hack for acquisition images like guide-00074954-0000.fits.fz
    # to make sure their _ccds table ends up listing cube_index 0
    # rather than NaN

    is_0000_acq_file = proc_obj.fname_in.find('-0000.fits.fz') != -1

    if is_0000_acq_file:
        tab['cube_index'] = 0
    else:
        tab['cube_index'] = np.nan if cube_index is None else int(cube_index)

    if cube_index == -1:
        tab['coadd_index_start'] = [exp.images[extname].coadd_index_range[0] for extname in tab['camera']]
        tab['coadd_index_end'] = [exp.images[extname].coadd_index_range[1] for extname in tab['camera']]
        tab['coadd_mjdobs_min'] = [exp.bintables[extname]['MJD-OBS'][ind] for extname, ind in zip(tab['camera'], tab['coadd_index_start'])]
        tab['coadd_mjdobs_max'] =  [exp.bintables[extname]['MJD-OBS'][ind] for extname, ind in zip(tab['camera'], tab['coadd_index_end'])]
    
    tab['racen'] = np.zeros(len(tab), dtype=float)
    tab['deccen'] = np.zeros(len(tab), dtype=float)

    tab['fname_raw'] = proc_obj.fname_in
    tab['gitrev']  = proc_obj.gitrev

    tab['fiber_fracflux'] = [(exp.images[extname].psf.fiber_fracflux if exp.images[extname].psf is not None else np.nan) for extname in tab['camera']]

    tab['fiber_fracflux_elg'] = [(exp.images[extname].psf.fiber_fracflux_elg if exp.images[extname].psf is not None else np.nan) for extname in tab['camera']]

    tab['fiber_fracflux_bgs'] = [(exp.images[extname].psf.fiber_fracflux_bgs if exp.images[extname].psf is not None else np.nan) for extname in tab['camera']]

    tab['n_sources_for_psf'] = [(exp.images[extname].psf.nstars if exp.images[extname].psf is not None else 0) for extname in tab['camera']]
    
    # this pertains to aperture _3 which is 1.5 asec radius
    tab['aper_corr_fac'] = [(exp.images[extname].psf.aper_corr_fac if exp.images[extname].psf is not None else np.nan) for extname in tab['camera']]

    tab['xcentroid_psf'] = [(exp.images[extname].psf.xcen_flux_weighted if exp.images[extname].psf is not None else np.nan) for extname in tab['camera']]
    tab['ycentroid_psf'] = [(exp.images[extname].psf.ycen_flux_weighted if exp.images[extname].psf is not None else np.nan) for extname in tab['camera']]

    tab['psf_fwhm_pix'] =  [(exp.images[extname].psf.moffat_fwhm_pix if exp.images[extname].psf is not None else np.nan) for extname in tab['camera']]

    tab['psf_fwhm_asec'] = [(exp.images[extname].psf.moffat_fwhm_asec if exp.images[extname].psf is not None else np.nan) for extname in tab['camera']]

    tab['psf_centroid_cbox'] = [(float(exp.images[extname].psf.cbox) if exp.images[extname].psf is not None else np.nan) for extname in tab['camera']]

    tab['psf_centroid_failed'] =  [(exp.images[extname].psf.psf_centroiding_failed if exp.images[extname].psf is not None else 0) for extname in tab['camera']]

    tab['radprof_fwhm_asec'] =  [(exp.images[extname].psf.radprof_fwhm_asec if exp.images[extname].psf is not None else np.nan) for extname in tab['camera']]

    # is 0 the best placeholder value here when no PSF exists?
    tab['psf_centroiding_flag'] =  [(exp.images[extname].psf.psf_centroiding_flag if exp.images[extname].psf is not None else 0) for extname in tab['camera']]

    tab['psf_asymmetry_ratio'] = [(exp.images[extname].psf.psf_asymmetry_ratio if exp.images[extname].psf is not None else np.float32(np.nan)) for extname in tab['camera']]

    tab['psf_asymmetry_numerator'] = [(exp.images[extname].psf.psf_asymmetry_numerator if exp.images[extname].psf is not None else np.float32(np.nan)) for extname in tab['camera']]

    tab['psf_asymmetry_denominator'] =  [(exp.images[extname].psf.psf_asymmetry_denominator if exp.images[extname].psf is not None else np.float32(np.nan)) for extname in tab['camera']]

    tab['psf_total_flux'] =  [(exp.images[extname].psf.psf_total_flux if exp.images[extname].psf is not None else np.float32(np.nan)) for extname in tab['camera']]

    radprof_ccds_table(tab, exp)

    for i, extname in enumerate(tab['camera']):
        racen, deccen = ccd_center_radec(exp.images[extname].wcs)
        tab['racen'][i] = racen
        tab['deccen'][i] = deccen

    tab['mountha_header'] = exp.try_retrieve_header_card('MOUNTHA', placeholder=np.nan)
    tab['mountdec_header'] = exp.try_retrieve_header_card('MOUNTDEC', placeholder=np.nan)

    tab['ha_deg'] = [util._get_ha(t['skyra'], t['lst_deg'], t['mountdec_header']) for t in tab]

    tab['ha_deg_per_gfa'] = [util._get_ha(t['racen'], t['lst_deg'], t['mountdec_header']) for t in tab]
    
    tab['moon_sep_deg'] = util.moon_separation(tab['moonra'], tab['moondec'],
                                               tab['racen'], tab['deccen'])

    # per-camera zenith distance -- will only be accurate to the extent that
    # each camera's WCS recalibration succeeded
    tab['zd_deg_per_gfa'] = [util._zenith_distance(t['racen'], t['deccen'], t['lst_deg']) for t in tab]

    tab['header_airmass'] = exp.try_retrieve_header_card('AIRMASS', placeholder=np.nan)

    # this should make the airmass properly evolve
    # with time for guide cube outputs
    tab['airmass'] = 1.0/np.cos(tab['zenith_dist_deg']/(180.0/np.pi))

    # this per-camera version of airmass should also evolve
    # properly with time for guide cube outputs
    tab['airmass_per_gfa'] = 1.0/np.cos(tab['zd_deg_per_gfa']/(180.0/np.pi))
    
    tab['zp_adu_per_s'] = [exp.images[extname].compute_zeropoint(ps1) for extname in tab['camera']]

    tab['n_stars_for_zp'] = [(np.sum(ps1['use_for_zp'] & (ps1['extname'] == extname)).astype(int) if 'use_for_zp' in ps1.colnames else 0) for extname in tab['camera']]

    tab['transparency'] = [util.transparency_from_zeropoint(tab[i]['zp_adu_per_s'], tab[i]['airmass_per_gfa'], tab[i]['camera']) for i in range(len(tab))]

    par = common.gfa_misc_params()
    tab['kterm'] = np.float32(par['kterm'])
    tab['fracflux_nominal_pointsource'] = np.float32(par['fracflux_nominal_pointsource'])
    tab['fracflux_nominal_elg'] = np.float32(par['fracflux_nominal_elg'])
    tab['fracflux_nominal_bgs'] = np.float32(par['fracflux_nominal_bgs'])

    tab['det_sn_thresh'] = det_sn_thresh
    
    prescan_overscan_ccds_table(tab, exp)
    high_level_ccds_metrics(tab, catalog, exp)
    astrom_ccds_table(tab, exp)
    dark_current_ccds_table(tab, exp)

    if mjdrange is not None:
        tab['req_mjd_min'] = mjdrange[0]
        tab['req_mjd_max'] = mjdrange[1]

    return tab
Example #5
0
def assemble_ccds_table(tab,
                        catalog,
                        exp,
                        outdir,
                        proc_obj,
                        cube_index=None,
                        ps1=None,
                        det_sn_thresh=5.0,
                        sky_mags=True,
                        minimal=False):

    nrows = len(tab)

    tab['extname'] = tab['camera']

    tab['contrast'] = [
        exp.images[extname].header['CONTRAST'] for extname in tab['camera']
    ]

    if minimal:
        return tab

    if sky_mags:
        tab['sky_mag_ab'] = [
            exp.images[extname].sky_mag for extname in tab['camera']
        ]

    amps = common.valid_amps_list()

    if sky_mags:
        sky_mag_ab_per_amp = np.zeros((nrows, len(amps)),
                                      dtype='float32')  # 4 amps
        for i, extname in enumerate(tab['camera']):
            for j in range(len(amps)):
                _mag = np.nan if exp.images[
                    extname].sky_mag_per_amp is None else exp.images[
                        extname].sky_mag_per_amp[j]
                sky_mag_ab_per_amp[i, j] = _mag

        tab['sky_mag_ab_per_amp'] = sky_mag_ab_per_amp

    tab['petal_loc'] = np.array([
        common.gfa_extname_to_gfa_number(extname) for extname in tab['camera']
    ],
                                dtype='uint8')

    tab['expid'] = [
        exp.images[extname].header['EXPID'] for extname in tab['camera']
    ]

    # should work except if early versions of guide cubes lacked
    # MJD information...
    tab['mjd'] = [
        exp.images[extname].try_retrieve_meta_keyword('MJD-OBS',
                                                      placeholder=0.0)
        for extname in tab['camera']
    ]

    eph = util.load_lst()
    tab['lst_deg'] = [util.interp_lst(t['mjd'], eph=eph) for t in tab]

    tab['program'] = [
        str(exp.images[extname].try_retrieve_meta_keyword('PROGRAM',
                                                          placeholder=''))
        for extname in tab['camera']
    ]

    tab['skyra'] = [
        exp.images[extname].try_retrieve_meta_keyword('SKYRA',
                                                      placeholder=np.nan)
        for extname in tab['camera']
    ]

    tab['skydec'] = [
        exp.images[extname].try_retrieve_meta_keyword('SKYDEC',
                                                      placeholder=np.nan)
        for extname in tab['camera']
    ]

    # zenith distance using approximate center of the field given by SKYRA, SKYDEC

    tab['zenith_dist_deg'] = [
        util._zenith_distance(t['skyra'], t['skydec'], t['lst_deg'])
        for t in tab
    ]

    tab['domshutl'] = np.array(
        nrows * [exp.try_retrieve_header_card('DOMSHUTL', placeholder='')],
        dtype='U8')
    tab['domshutu'] = np.array(
        nrows * [exp.try_retrieve_header_card('DOMSHUTU', placeholder='')],
        dtype='U8')
    tab['pmcover'] = exp.try_retrieve_header_card('PMCOVER', placeholder='')
    tab['moonra'] = exp.try_retrieve_header_card('MOONRA', placeholder=np.nan)
    tab['moondec'] = exp.try_retrieve_header_card('MOONDEC',
                                                  placeholder=np.nan)

    tab['t_c_for_dark'] = [
        exp.images[extname].t_c_for_dark for extname in tab['camera']
    ]
    tab['t_c_for_dark_is_guess'] = [
        int(exp.images[extname].t_c_for_dark_is_guess)
        for extname in tab['camera']
    ]
    tab['time_s_for_dark'] = [
        exp.images[extname].time_s_for_dark for extname in tab['camera']
    ]

    tab['night'] = exp.try_retrieve_header_card('NIGHT', placeholder='')

    tab['focus'] = exp.try_retrieve_header_card('FOCUS', placeholder='')

    tab['exptime'] = [
        exp.images[extname].try_retrieve_meta_keyword('EXPTIME',
                                                      placeholder=np.nan)
        for extname in tab['camera']
    ]

    tab['cube_index'] = np.nan if cube_index is None else int(cube_index)

    if cube_index == -1:
        tab['coadd_index_start'] = [
            exp.images[extname].coadd_index_range[0]
            for extname in tab['camera']
        ]
        tab['coadd_index_end'] = [
            exp.images[extname].coadd_index_range[1]
            for extname in tab['camera']
        ]

    tab['racen'] = np.zeros(len(tab), dtype=float)
    tab['deccen'] = np.zeros(len(tab), dtype=float)

    tab['fname_raw'] = proc_obj.fname_in
    tab['gitrev'] = proc_obj.gitrev

    tab['fiber_fracflux'] = [(exp.images[extname].psf.fiber_fracflux if
                              exp.images[extname].psf is not None else np.nan)
                             for extname in tab['camera']]

    tab['n_sources_for_psf'] = [(exp.images[extname].psf.nstars
                                 if exp.images[extname].psf is not None else 0)
                                for extname in tab['camera']]

    # this pertains to aperture _3 which is 1.5 asec radius
    tab['aper_corr_fac'] = [(exp.images[extname].psf.aper_corr_fac if
                             exp.images[extname].psf is not None else np.nan)
                            for extname in tab['camera']]

    tab['xcentroid_psf'] = [(exp.images[extname].psf.xcen_flux_weighted if
                             exp.images[extname].psf is not None else np.nan)
                            for extname in tab['camera']]
    tab['ycentroid_psf'] = [(exp.images[extname].psf.ycen_flux_weighted if
                             exp.images[extname].psf is not None else np.nan)
                            for extname in tab['camera']]

    tab['psf_fwhm_pix'] = [(exp.images[extname].psf.moffat_fwhm_pix
                            if exp.images[extname].psf is not None else np.nan)
                           for extname in tab['camera']]

    tab['psf_fwhm_asec'] = [(exp.images[extname].psf.moffat_fwhm_asec if
                             exp.images[extname].psf is not None else np.nan)
                            for extname in tab['camera']]

    tab['psf_centroid_cbox'] = [
        (float(exp.images[extname].psf.cbox)
         if exp.images[extname].psf is not None else np.nan)
        for extname in tab['camera']
    ]

    tab['psf_centroid_failed'] = [
        (exp.images[extname].psf.psf_centroiding_failed
         if exp.images[extname].psf is not None else 0)
        for extname in tab['camera']
    ]

    for i, extname in enumerate(tab['camera']):
        racen, deccen = ccd_center_radec(exp.images[extname].wcs)
        tab['racen'][i] = racen
        tab['deccen'][i] = deccen

    tab['mountha_header'] = exp.try_retrieve_header_card('MOUNTHA',
                                                         placeholder=np.nan)
    tab['mountdec_header'] = exp.try_retrieve_header_card('MOUNTDEC',
                                                          placeholder=np.nan)

    tab['ha_deg'] = [
        util._get_ha(t['skyra'], t['lst_deg'], t['mountdec_header'])
        for t in tab
    ]

    tab['ha_deg_per_gfa'] = [
        util._get_ha(t['racen'], t['lst_deg'], t['mountdec_header'])
        for t in tab
    ]

    tab['moon_sep_deg'] = util.moon_separation(tab['moonra'], tab['moondec'],
                                               tab['racen'], tab['deccen'])

    # per-camera zenith distance -- will only be accurate to the extent that
    # each camera's WCS recalibration succeeded
    tab['zd_deg_per_gfa'] = [
        util._zenith_distance(t['racen'], t['deccen'], t['lst_deg'])
        for t in tab
    ]

    tab['header_airmass'] = exp.try_retrieve_header_card('AIRMASS',
                                                         placeholder=np.nan)

    # this should make the airmass properly evolve
    # with time for guide cube outputs
    tab['airmass'] = 1.0 / np.cos(tab['zenith_dist_deg'] / (180.0 / np.pi))

    # this per-camera version of airmass should also evolve
    # properly with time for guide cube outputs
    tab['airmass_per_gfa'] = 1.0 / np.cos(tab['zd_deg_per_gfa'] /
                                          (180.0 / np.pi))

    tab['zp_adu_per_s'] = [
        exp.images[extname].compute_zeropoint(ps1) for extname in tab['camera']
    ]

    tab['transparency'] = [
        util.transparency_from_zeropoint(tab[i]['zp_adu_per_s'],
                                         tab[i]['airmass_per_gfa'],
                                         tab[i]['camera'])
        for i in range(len(tab))
    ]

    tab['det_sn_thresh'] = det_sn_thresh

    prescan_overscan_ccds_table(tab, exp)
    high_level_ccds_metrics(tab, catalog, exp)
    astrom_ccds_table(tab, exp)
    dark_current_ccds_table(tab, exp)

    return tab