Beispiel #1
0
def quad_pix_limits(quad):
    # q is an integer quadrant number, one of [1, 2, 3, 4]

    assert(quad in [1, 2, 3, 4])

    par = common.pc_params()

    half_x = par['nx'] // 2
    half_y = par['ny'] // 2

    if (quad == 1) or (quad == 4):
        xmin = half_x
        xmax = par['nx']
    else:
        xmin = 0
        xmax = half_x

    if (quad == 1) or (quad == 2):
        ymin = half_y
        ymax = par['ny']
    else:
        ymin = 0
        ymax = half_y

    result = {'xmin' : xmin, 'xmax' : xmax, 'ymin' : ymin, 'ymax' : ymax}

    return result
Beispiel #2
0
def calc_many_zps(cat, exp, one_aper=False, checkplot=True, nmp=None):

    print('Attempting to calculate zeropoints')

    par = common.pc_params()

    aper_radii = par['aper_phot_objrad'] if not one_aper else [par['aper_phot_objrad_best']]

    args = []
    for q in [0, 1, 2, 3, 4]:
        for aper_ind in range(len(aper_radii)):
            args.append((cat, aper_ind, exp.time_seconds, exp.fname_im, q, checkplot, one_aper))

    if nmp is not None:
        p = Pool(min(nmp, len(args)))
        results = p.starmap(calc_zp, args)
        p.close()
        p.join()
    else:
        results = [calc_zp(*_arg) for _arg in args]

    results = vstack(results)
    results['mjd_obs'] = exp.header['MJD-OBS']
    results['obs_night'] = exp.obs_night

    sind = np.argsort(1000*results['quadrant'] + results['aper_ind'])
    results = results[sind]

    return results
Beispiel #3
0
def get_g_prime(G, BP_RP):
    # right now this is pretty much trivial but in the future it
    # could become more complex

    par = common.pc_params()

    g_prime = G + par['bp_rp_coeff']*BP_RP

    return g_prime
Beispiel #4
0
def pc_gaia_cat(exp, mag_thresh=None, edge_pad_pix=0, nmp=None,
                max_n_stars=3000, pm_corr=False):

    print('Reading Gaia DR2 catalogs...')

    xgrid, ygrid = xy_subsamp_grid()

    wcs = exp.wcs

    # last arg is 0 rather than 1 because that's what agrees with IDL
    ra, dec = wcs.all_pix2world(xgrid, ygrid, 0)

    cat = read_gaia_cat(ra, dec, nmp=nmp)

    if mag_thresh is not None:
        keep = (cat['PHOT_G_MEAN_MAG'] <= mag_thresh)
        assert(np.sum(keep) > 0)
        cat = cat[keep]

    if pm_corr:
        gaia_pm_corr(cat, exp.header['MJD-OBS'])

    x_gaia_guess, y_gaia_guess = wcs.all_world2pix(cat['RA'], cat['DEC'], 0)

    par = common.pc_params()

    keep  = (x_gaia_guess > edge_pad_pix) & (y_gaia_guess > edge_pad_pix) & (x_gaia_guess < (par['nx'] - 1 - edge_pad_pix)) & (y_gaia_guess < (par['ny'] - 1 - edge_pad_pix))

    assert(np.sum(keep) > 0)

    cat = cat[keep]

    x_gaia_guess = x_gaia_guess[keep]
    y_gaia_guess = y_gaia_guess[keep]

    cat = Table(cat)
    cat['x_gaia_guess'] = x_gaia_guess
    cat['y_gaia_guess'] = y_gaia_guess

    if len(cat) > max_n_stars:
        # retain brightest max_n_stars
        # it'd be better to do this cut based on
        # 'G_PRIME', the color-corrected pointing
        # camera Gaia-based mag
        # in the future can evaluate trying to spread the
        # selected max_n_stars evenly across quadrants
        # (could imagine a pathological case with e.g., a
        # globular cluster in the FOV)
        print('Restricting to the brightest ' + str(max_n_stars) + \
              ' of ' + str(len(cat)) + ' stars')
        sind = np.argsort(cat['PHOT_G_MEAN_MAG'])
        cat = cat[sind[0:max_n_stars]]

    return cat
Beispiel #5
0
def load_static_badpix():
    par = common.pc_params()

    fname = os.path.join(os.environ[par['meta_env_var']],
                         par['static_mask_filename'])

    assert (os.path.exists(fname))

    mask = fits.getdata(fname)

    return mask
Beispiel #6
0
def get_quadrant(im, q):
    assert(q in [1, 2, 3, 4])

    check_image_dimensions(im)

    par = common.pc_params()

    p = quad_pix_limits(q)

    quad = im[p['ymin']:p['ymax'], p['xmin']:p['xmax']]

    return quad
Beispiel #7
0
def min_edge_dist_pix(x, y):
    # minimum distance to any image edge
    # works for array-valued x, y

    min_edge_dist = 20000

    par = common.pc_params()

    min_edge_dist = np.minimum(x + 0.5, y + 0.5)
    min_edge_dist = np.minimum(min_edge_dist, par['nx'] - 0.5 - x)
    min_edge_dist = np.minimum(min_edge_dist, par['ny'] - 0.5 - y)

    return min_edge_dist
Beispiel #8
0
def check_image_dimensions(image):
    # check that image dimensions make sense
    # of particular relevance is not getting fooled by downbinned data

    print('Checking raw pointing camera image dimensions...')

    par = common.pc_params()

    sh = image.shape

    assert(sh[0] == par['ny'])
    assert(sh[1] == par['nx'])

    print('Raw pointing camera image has correct dimensions')
Beispiel #9
0
def subtract_quad_offs(im):
    par = common.pc_params()

    # just in case this hasn't already been taken care of...
    if im.dtype.name != 'float32':
        im = im.astype('float32')

    check_image_dimensions(im)

    for q in [1, 2, 3, 4]:
        p = quad_pix_limits(q)

        im[p['ymin']:p['ymax'], p['xmin']:p['xmax']] -= par['bias_med'][q-1]

    return im
Beispiel #10
0
def gaia_chunknames(ipix):
    # could add checks to make sure that all ipix values are
    # sane HEALPix pixel indices
    # RIGHT NOW THIS ASSUMES IPIX IS AN ARRAY !!
    # should eventually make this also work for scalar ipix

    par = common.pc_params()

    gaia_dir = os.environ[par['gaia_env_var']]

    flist = [
        os.path.join(gaia_dir, 'chunk-' + str(i).zfill(5) + '.fits')
        for i in ipix
    ]
    return flist
Beispiel #11
0
def pc_recentroid(im, cat):
    par = common.pc_params()

    im = im.astype(float)

    x_center = par['nx']/2 + 0.5
    y_center = par['ny']/2 + 0.5

    dist_pix = np.sqrt(np.power(cat['x_gaia_guess'] - x_center, 2) + \
                       np.power(cat['y_gaia_guess'] - y_center, 2))

    dist_max = np.sqrt(x_center**2 + y_center**2)

    slope = 2.0/dist_max

    cmaxshift = np.minimum(np.maximum(dist_pix*slope + 2.5, 2.5), 4.5)

    assert(np.sum(cmaxshift < 2.5) == 0)
    assert(np.sum(cmaxshift > 4.5) == 0)

    xcen = np.zeros(len(cat), dtype=float)
    ycen = np.zeros(len(cat), dtype=float)

    qmaxshift = np.zeros(len(cat), dtype=int)

    for i in range(len(cat)):
        _xcen, _ycen, q = djs_photcen(cat['x_gaia_guess'][i],
                                      cat['y_gaia_guess'][i], im, cbox=8,
                                      cmaxiter=10, cmaxshift=cmaxshift[i])
        xcen[i] = _xcen
        ycen[i] = _ycen
        qmaxshift[i] = q

    result = Table()

    result['xcentroid'] = xcen
    result['ycentroid'] = ycen
    result['x_shift'] = xcen - cat['x_gaia_guess']
    result['y_shift'] = ycen - cat['y_gaia_guess']
    result['cmaxshift'] = cmaxshift
    result['qmaxshift'] = qmaxshift

    result['centroid_shift_flag'] = (np.abs(result['x_shift']) > cmaxshift) | (np.abs(result['y_shift']) > cmaxshift) | (qmaxshift != 0)

    assert(len(result) == len(cat))
    cat = hstack([cat, result])

    return cat
Beispiel #12
0
def pc_aper_phot(im, cat, one_aper=False, bg_sigclip=False):

    im = im.astype(float)

    par = common.pc_params()

    positions = list(zip(cat['xcentroid'], cat['ycentroid']))

    radii = par['aper_phot_objrad'] if not one_aper else [par['aper_phot_objrad_best']]
    ann_radii = par['annulus_radii'] # should have 2 elements - inner and outer

    apertures = [CircularAperture(positions, r=r) for r in radii]
    annulus_apertures = CircularAnnulus(positions, r_in=ann_radii[0],
                                        r_out=ann_radii[1])
    annulus_masks = annulus_apertures.to_mask(method='center')

    bkg_median = []
    for mask in annulus_masks:
        annulus_data = mask.multiply(im)
        annulus_data_1d = annulus_data[mask.data > 0]
        if bg_sigclip:
            # this sigma_clipped_stats call is actually the slow part !!
            _, median_sigclip, std_bg = sigma_clipped_stats(annulus_data_1d)
            bkg_median.append(median_sigclip)
        else:
            bkg_median.append(np.median(annulus_data_1d))

    bkg_median = np.array(bkg_median)
    phot = aperture_photometry(im, apertures)

    for i, aperture in enumerate(apertures):
        aper_bkg_tot = bkg_median*_get_area_from_ap(aperture)
        cat['aper_sum_bkgsub_' + str(i)] = phot['aperture_sum_' + str(i)] - aper_bkg_tot

        cat['aper_bkg_' + str(i)] = aper_bkg_tot

    cat['sky_annulus_area_pix'] = _get_area_from_ap(annulus_apertures)
    cat['sky_annulus_median'] = bkg_median

    flux_adu = np.zeros((len(cat), len(radii)), dtype=float)

    for i in range(len(radii)):
        flux_adu[:, i] = cat['aper_sum_bkgsub_' + str(i)]

    cat['flux_adu'] = flux_adu

    return cat
Beispiel #13
0
def source_raw_pixel_metrics(cat, raw):

    par = common.pc_params()

    ixcen = np.round(cat['xcentroid']).astype(int)
    iycen = np.round(cat['ycentroid']).astype(int)

    ixcen = np.minimum(np.maximum(ixcen, 0), par['nx']-1)
    iycen = np.minimum(np.maximum(iycen, 0), par['ny']-1)

    centroid_pixel_vals = raw[iycen, ixcen] # ordering of indices !

    centroid_pixel_saturated = (centroid_pixel_vals == par['raw_satur_val']).astype(int)

    # modify the input catalog
    cat['centroid_raw_pixel_val'] = centroid_pixel_vals
    cat['centroid_pixel_saturated'] = centroid_pixel_saturated
Beispiel #14
0
def quadrant_from_xy(x, y):
    # works for array-valued x, y

    par = common.pc_params()

    half_x = par['nx']/2 - 0.5
    half_y = par['ny']/2 - 0.5

    quadrant = np.zeros(len(x), dtype=int)

    quadrant[(x <= half_x) & (y <= half_y)] = 3

    quadrant[(x <= half_x) & (y > half_y)] = 2

    quadrant[(x > half_x) & (y <= half_y)] = 4

    quadrant[(x > half_x) & (y > half_y)] = 1

    return quadrant
Beispiel #15
0
def subtract_dark_current(im, time_seconds):

    print('Subtracting dark current')

    assert(time_seconds < 30)

    par = common.pc_params()

    result = im.astype('float32')

    for q in [1, 2, 3, 4]:
        dark_adu = par['dark_adu_per_s_quad'][q-1]*time_seconds
        print('quadrant : ', q, ', dark counts/pix : ', '{:.3f}'.format(dark_adu))

        p = quad_pix_limits(q)

        result[p['ymin']:p['ymax'], p['xmin']:p['xmax']] -= dark_adu

    return result
Beispiel #16
0
def calc_zp(_cat, aper_ind, time_seconds, fname_im, quadrant=0,
            one_aper=False, checkplot=True):
    # quadrant = 0 means whole image (all quadrants combined)

    print('Computing zeropoint for quadrant : ', quadrant, ' , aper ', aper_ind)

    assert(time_seconds > 0)
    assert(quadrant in [0, 1, 2, 3, 4]) # note the 0 option here...

    par = common.pc_params()

    n_aper = len(par['aper_phot_objrad'])

    aper_ind = int(aper_ind)
    assert(aper_ind in np.arange(n_aper))

    cat = copy.deepcopy(_cat)

    good = np.logical_not(cat['centroid_pixel_saturated']) & \
           (cat['centroid_raw_pixel_val'] < 15300) & \
           np.logical_not(cat['centroid_shift_flag']) & \
           np.logical_not(cat['wrong_source_centroid']) & \
           np.isfinite(cat['PHOT_BP_MEAN_MAG']) & \
           np.isfinite(cat['PHOT_RP_MEAN_MAG']) & \
           np.isfinite(cat['PHOT_G_MEAN_MAG'])

    if quadrant != 0:
        good = good & (cat['quadrant'] == quadrant)

    if np.sum(good) == 0:
        return None

    cat = cat[good]
    n = len(cat)

    m_inst = cat['m_inst'][:, aper_ind]

    diff = cat['G_PRIME'] - m_inst
    nf = np.sum(np.isfinite(diff))

    zp = np.nanmedian(diff)

    resid = diff - zp

    # now calculate robust sigma about the median zeropoint offset

    # at first glance argsort appears to put NaN's at end of sorted array
    sind = np.argsort(resid) # should look into what exactly happens with NaN's

    ind_l = max(int(round(0.16*nf)), 0)
    ind_u = min(int(round(0.84*nf)), n-1)

    resid_l = resid[sind[ind_l]]
    resid_u = resid[sind[ind_u]]

    sig_robust = (np.abs(resid_l) + np.abs(resid_u))/2.0

    result = Table()

    result['quadrant'] = [quadrant]
    result['aper_ind'] = [aper_ind]
    result['zp_adu_per_s'] = [zp]
    result['n_sources_for_zp'] = [n]
    result['time_seconds'] = [time_seconds]
    result['bp_rp_median'] = [np.nanmedian(cat['BP_RP'])]
    result['gaia_g_median'] = [np.nanmedian(cat['PHOT_G_MEAN_MAG'])]
    result['robust_sigma_mag'] = [sig_robust]
    result['fname_raw'] = [fname_im]

    # checkplot (eventually make this optional)

    best_aper_ind = 1 if not one_aper else 0

    if checkplot and (quadrant == 0) and (aper_ind == best_aper_ind):
        plt.cla()
        plt.figure(1)
        xtitle = 'G + 0.25*(BP-RP)'
        ytitle = '-2.5' + r'$\times$' + 'log' + r'$_{10}$' + '(ADU/sec)'
        title = fname_im.split('/')[-1]
        title = title.replace('.fits', '')
        title += '; aper' + str(best_aper_ind) + '; all quads'

        plt.scatter(cat['G_PRIME'], m_inst, s=20, edgecolor='none',
                    facecolor='k')

        xmin = np.nanmin(cat['G_PRIME'])
        xmax = np.nanmax(cat['G_PRIME'])
        ymin = np.nanmin(m_inst)
        ymax = np.nanmax(m_inst)

        xsamp = np.array([xmin, xmax])
        ysamp = xsamp - zp

        plt.plot(xsamp, ysamp, linewidth=2, c='r')

        ax = plt.gca()

        xlim = ax.get_xlim()
        ylim = ax.get_ylim()

        xtext = xlim[0] + (xlim[1] - xlim[0])*0.125
        ytext = ylim[0] + (ylim[1] - ylim[0])*0.875

        # this shouldn't crash for NaN zeropoint value...
        plt.text(xtext, ytext, 'ZP = ' + '{:.2f}'.format(zp), color='r')

        plt.title(title)
        plt.xlabel(xtitle)
        plt.ylabel(ytitle)

    return result
Beispiel #17
0
def _check_bitpix(h_im):
    par = common.pc_params()

    print('Checking raw image BITPIX value')

    assert(h_im['BITPIX'] == par['bitpix'])
Beispiel #18
0
        '--max_n_stars',
        default=3000,
        type=int,
        help="limit analysis to brightest max_n_stars Gaia stars")

    parser.add_argument(
        '--pm_corr',
        default=False,
        action='store_true',
        help="make Gaia proper motion corrections based on MJD")

    args = parser.parse_args()

    # basic checks on requested number of multiprocessing threads
    if args.multiproc is not None:
        par = common.pc_params()
        assert (args.multiproc > 1)
        assert (args.multiproc <= par['ncpus'])

    pc_proc(args.fname_in[0],
            outdir=args.outdir,
            dont_write_detrended=args.dont_write_detrended,
            skip_checkplot=args.skip_checkplot,
            nightly_subdir=args.nightly_subdir,
            send_redis=args.send_redis,
            one_aper=args.one_aper,
            bg_sigclip=args.bg_sigclip,
            nmp=args.multiproc,
            max_n_stars=args.max_n_stars,
            pm_corr=args.pm_corr)