Beispiel #1
0
def get_ps1_chip_image(filename, offset=(0, 0), npix=None):
    filename_base = filename[:-5]
    im = pyfits.getdata(filename_base + '.fits')
    wt = pyfits.getdata(filename_base + '.wt.fits')
    mk = pyfits.getdata(filename_base + '.mk.fits')

    psffile = filename_base[:-3] + '.psf'
    psffp = tempfile.NamedTemporaryFile()
    psffp.close()
    subprocess.call([
        "dannyVizPSF",
        str(im.shape[0]),
        str(im.shape[1]),
        str(im.shape[0] / 2),
        str(im.shape[1] / 2), "51", "51", psffile, psffp.name
    ])
    psfstamp = pyfits.getdata(psffp.name)

    smffn = get_smf_filename(os.path.basename(filename_base)[:11])
    im[mk != 0] = 0
    wt[mk != 0] = 0
    if npix is None:
        npix = im.shape
    im = im[offset[0]:offset[0] + npix[0], offset[1]:offset[1] + npix[1]]
    wt = wt[offset[0]:offset[0] + npix[0], offset[1]:offset[1] + npix[1]]
    mk = mk[offset[0]:offset[0] + npix[0], offset[1]:offset[1] + npix[1]]
    invvar = (1. / (wt + (wt == 0))) * (wt != 0)

    hsmf = pyfits.getheader(smffn)
    zp = hsmf['MAG_ZP']

    hchip = pyfits.getheader(filename_base + '.fits', 1)
    chip = hchip['FPPOS'].upper().strip()

    filterid = 'PS1_' + hsmf['filterid'][0]

    tpsf = tractor.GaussianMixturePSF.fromStamp(psfstamp, N=3)

    twcs = wcs_ps1(smffn, chip, offset=offset)
    tsky = tractor.ConstantSky(0)
    photocal = tractor.MagsPhotoCal(
        filterid, zp + 2.5 * numpy.log10(hchip['exptime']) + 0.5)

    tim = tractor.Image(data=im,
                        invvar=invvar,
                        psf=tpsf,
                        wcs=twcs,
                        photocal=photocal,
                        sky=tsky,
                        name='PS1 %s %s' % (filterid, filename_base))
    tim.zr = [-100, 100]
    tim.extent = [0, im.shape[0], 0, im.shape[1]]

    return tim
Beispiel #2
0
def read_cfht_coadd(imgfn, weightfn, roi=None, radecroi=None, filtermap=None):
    '''
    Given filenames for CFHT coadd image and weight files, produce
    a tractor.Image object.

    *roi*: (x0,x1, y0,y1): a region-of-interest in pixel space;
           returns the subimage [x0,x1), [y0,y1).
    *radecroi*: (ra0, ra1, dec0, dec1): a region-of-interest in RA,Dec space;
           returns the subimage bounding the given RA,Dec box [ra0,ra1], [dec0,dec1].
    *filtermap*: dict, eg,  { 'i.MP9701': 'i' }, to map from the FILTER header keyword to
           a standard filter name.
    '''

    P = pyfits.open(imgfn)
    print 'Read', P[0].data.shape, 'image'
    img = P[0].data
    imgheader = P[0].header

    # WCS: the image file has a WCS header
    # we should be able to do:
    #twcs = tractor.FitsWcs(imgfn)
    # ARGH!  Memory issues reading the file; HACK: copy header...
    f, tempfn = tempfile.mkstemp()
    os.close(f)
    pyfits.writeto(tempfn, None, header=imgheader, clobber=True)
    twcs = tractor.FitsWcs(tempfn)

    # Cut down to the region-of-interest, if given.
    if roi is not None:
        x0, x1, y0, y1 = roi
    elif radecroi is not None:
        ralo, rahi, declo, dechi = radecroi
        xy = [
            twcs.positionToPixel(tractor.RaDecPos(r, d))
            for r, d in [(ralo, declo), (ralo, dechi), (rahi,
                                                        declo), (rahi, dechi)]
        ]
        xy = np.array(xy)
        x0, x1 = xy[:, 0].min(), xy[:, 0].max()
        y0, y1 = xy[:, 1].min(), xy[:, 1].max()
        print 'RA,Dec ROI', ralo, rahi, declo, dechi, 'becomes x,y ROI', x0, x1, y0, y1

        # Clip to image size...
        H, W = data.shape
        x0 = max(0, min(x0, W - 1))
        x1 = max(0, min(x1, W))
        y0 = max(0, min(y0, H - 1))
        y1 = max(0, min(y1, H))
        print ' clipped to', x0, x1, y0, y1

    else:
        H, W = img.shape
        x0, x1, y0, y1 = 0, W, 0, H

    if roi is not None or radecroi is not None:
        # Actually cut the pixels
        img = img[y0:y1, x0:x1].copy()
        # Also tell the WCS to apply an offset.
        twcs.setX0Y0(x0, y0)

    print 'Image:', img.shape

    # HACK, tell the WCS how big the image is...
    # (needed because of the previous HACK, copying the header)
    twcs.wcs.set_imagesize(x1 - x0, y1 - y0)
    print twcs

    # Argh, this doesn't work: the files are .fz compressed
    #P = pyfits.open(weightfn)
    #weight = P[1].data[y0:y1, x0:x1]
    # HACK: use "imcopy" to uncompress to a temp file!
    #print 'Writing to temp file', tempfn
    cmd = "imcopy '%s[%i:%i,%i:%i]' '!%s'" % (weightfn, x0 + 1, x1, y0 + 1, y1,
                                              tempfn)
    print 'running', cmd
    os.system(cmd)
    P = pyfits.open(tempfn)
    weight = P[0].data
    print 'Read', weight.shape, 'weight image'

    # PSF model: FAKE IT for now
    tpsf = tractor.GaussianMixturePSF(np.array([0.9, 0.1]), np.zeros((2, 2)),
                                      np.array([1, 2]))

    # SKY level: assume zero
    #sky = np.median(img)
    #print 'Image median value:', sky
    sky = 0.
    tsky = tractor.ConstantSky(sky)

    # Photometric calibration: the FITS header says:
    '''
    FILTER  = 'r.MP9601'           / Filter
    PHOTZP  =               30.000 / photometric zeropoint
    COMMENT AB magnitude = -2.5 * log10(flux) + PHOTZP
    COMMENT r.MP9601=r_SDSS-0.024*(g_SDSS-r_SDSS)
    '''
    # Grab the filter name, and apply the filtermap (if given)
    filter = imgheader['FILTER']
    if filtermap:
        filter = filtermap.get(filter, filter)
    zp = imgheader['PHOTZP']
    # Simple photocal object
    photocal = tractor.MagsPhotoCal(filter, zp)

    # For plotting: find the approximate standard deviation
    #print 'Median weight:', np.median(weight)
    sigma1 = 1. / np.sqrt(np.median(weight))
    zr = np.array([-3, 10]) * sigma1 + sky

    name = 'CFHT ' + imgheader.get('OBJECT', '')

    tim = tractor.Image(data=img,
                        invvar=weight,
                        psf=tpsf,
                        wcs=twcs,
                        sky=tsky,
                        photocal=photocal,
                        name=name,
                        zr=zr)
    tim.extent = [x0, x1, y0, y1]
    return tim
Beispiel #3
0
def read_wise_level1b(basefn, radecroi=None, radecrad=None, filtermap=None,
                      nanomaggies=False, mask_gz=False, unc_gz=False,
                      sipwcs=False, constantInvvar=False,
                      roi=None,
                      zrsigs=[-3, 10],
                      ):
    if filtermap is None:
        filtermap = {}

    intfn = basefn + '-int-1b.fits'
    maskfn = basefn + '-msk-1b.fits'

    if mask_gz:
        maskfn = maskfn + '.gz'
    uncfn = basefn + '-unc-1b.fits'
    if unc_gz:
        uncfn = uncfn + '.gz'

    logger.debug('intensity image   %s' % intfn)
    logger.debug('mask image        %s' % maskfn)
    logger.debug('uncertainty image %s' % uncfn)

    if sipwcs:
        wcs = Sip(intfn, 0)
        twcs = tractor.ConstantFitsWcs(wcs)
    else:
        twcs = tractor.ConstantFitsWcs(intfn)

    # Read enough of the image to get its size
    Fint = fitsio.FITS(intfn)
    H, W = Fint[0].get_info()['dims']

    if radecrad is not None:
        r, d, rad = radecrad
        x, y = twcs.positionToPixel(tractor.RaDecPos(r, d))
        pixrad = rad / (twcs.pixel_scale() / 3600.)
        print('Tractor WCS:', twcs)
        print('RA,Dec,rad', r, d, rad, 'becomes x,y,pixrad', x, y, pixrad)
        roi = (x - pixrad, x + pixrad + 1, y - pixrad, y + pixrad + 1)

    if radecroi is not None:
        ralo, rahi, declo, dechi = radecroi
        xy = [twcs.positionToPixel(tractor.RaDecPos(r, d))
              for r, d in [(ralo, declo), (ralo, dechi), (rahi, declo), (rahi, dechi)]]
        xy = np.array(xy)
        x0, x1 = xy[:, 0].min(), xy[:, 0].max()
        y0, y1 = xy[:, 1].min(), xy[:, 1].max()
        print('RA,Dec ROI', ralo, rahi, declo, dechi,
              'becomes x,y ROI', x0, x1, y0, y1)
        roi = (x0, x1 + 1, y0, y1 + 1)

    if roi is not None:
        x0, x1, y0, y1 = roi
        x0 = int(np.floor(x0))
        x1 = int(np.ceil(x1))
        y0 = int(np.floor(y0))
        y1 = int(np.ceil(y1))
        roi = (x0, x1, y0, y1)
        # Clip to image size...
        x0 = np.clip(x0, 0, W)
        x1 = np.clip(x1, 0, W)
        y0 = np.clip(y0, 0, H)
        y1 = np.clip(y1, 0, H)
        if x0 == x1 or y0 == y1:
            print('ROI is empty')
            return None
        assert(x0 < x1)
        assert(y0 < y1)
        #roi = (x0,x1,y0,y1)
        twcs.setX0Y0(x0, y0)

    else:
        x0, x1, y0, y1 = 0, W, 0, H
        roi = (x0, x1, y0, y1)

    ihdr = Fint[0].read_header()
    data = Fint[0][y0:y1, x0:x1]
    logger.debug('Read %s intensity' % (str(data.shape)))
    band = ihdr['BAND']

    F = fitsio.FITS(uncfn)
    assert(F[0].get_info()['dims'] == [H, W])
    unc = F[0][y0:y1, x0:x1]

    F = fitsio.FITS(maskfn)
    assert(F[0].get_info()['dims'] == [H, W])
    mask = F[0][y0:y1, x0:x1]

    # HACK -- circular Gaussian PSF of fixed size...
    # in arcsec
    fwhms = {1: 6.1, 2: 6.4, 3: 6.5, 4: 12.0}
    # -> sigma in pixels
    sig = fwhms[band] / 2.35 / twcs.pixel_scale()
    # print 'PSF sigma', sig, 'pixels'
    tpsf = tractor.NCircularGaussianPSF([sig], [1.])

    filter = 'w%i' % band
    if filtermap:
        filter = filtermap.get(filter, filter)
    zp = ihdr['MAGZP']
    if nanomaggies:
        photocal = tractor.LinearPhotoCal(tractor.NanoMaggies.zeropointToScale(zp),
                                          band=filter)
    else:
        photocal = tractor.MagsPhotoCal(filter, zp)

    # print 'Image median:', np.median(data)
    # print 'unc median:', np.median(unc)

    sky = np.median(data)
    tsky = tractor.ConstantSky(sky)

    name = 'WISE ' + ihdr['FRSETID'] + ' W%i' % band

    # Mask bits, from
    # http://wise2.ipac.caltech.edu/docs/release/allsky/expsup/sec4_4a.html#maskdef
    # 0 from static mask: excessively noisy due to high dark current alone
    # 1 from static mask: generally noisy [includes bit 0]
    # 2 from static mask: dead or very low responsivity
    # 3 from static mask: low responsivity or low dark current
    # 4 from static mask: high responsivity or high dark current
    # 5 from static mask: saturated anywhere in ramp
    # 6 from static mask: high, uncertain, or unreliable non-linearity
    # 7 from static mask: known broken hardware pixel or excessively noisy responsivity estimate [may include bit 1]
    # 8 reserved
    # 9 broken pixel or negative slope fit value (downlink value = 32767)
    # 10 saturated in sample read 1 (down-link value = 32753)
    # 11 saturated in sample read 2 (down-link value = 32754)
    # 12 saturated in sample read 3 (down-link value = 32755)
    # 13 saturated in sample read 4 (down-link value = 32756)
    # 14 saturated in sample read 5 (down-link value = 32757)
    # 15 saturated in sample read 6 (down-link value = 32758)
    # 16 saturated in sample read 7 (down-link value = 32759)
    # 17 saturated in sample read 8 (down-link value = 32760)
    # 18 saturated in sample read 9 (down-link value = 32761)
    # 19 reserved
    # 20 reserved
    # 21 new/transient bad pixel from dynamic masking
    # 22 reserved
    # 23 reserved
    # 24 reserved
    # 25 reserved
    # 26 non-linearity correction unreliable
    # 27 contains cosmic-ray or outlier that cannot be classified (from temporal outlier rejection in multi-frame pipeline)
    # 28 contains positive or negative spike-outlier
    # 29 reserved
    # 30 reserved
    # 31 not used: sign bit

    goodmask = ((mask & sum([1 << bit for bit in [0, 1, 2, 3, 4, 5, 6, 7, 9,
                                                  10, 11, 12, 13, 14, 15, 16, 17, 18,
                                                  21, 26, 27, 28]])) == 0)
    sigma1 = np.median(unc[goodmask])
    zr = np.array(zrsigs) * sigma1 + sky

    # constant
    cinvvar = np.zeros_like(data)
    cinvvar[goodmask] = 1. / (sigma1**2)
    # varying
    vinvvar = np.zeros_like(data)
    vinvvar[goodmask] = 1. / (unc[goodmask])**2

    bad = np.flatnonzero(np.logical_not(np.isfinite(vinvvar)))
    if len(bad):
        vinvvar.flat[bad] = 0.
        cinvvar.flat[bad] = 0.
        data.flat[bad] = sky

    if constantInvvar:
        invvar = cinvvar
    else:
        invvar = vinvvar

    # avoid NaNs
    data[np.logical_not(goodmask)] = sky

    mjd = ihdr['MJD_OBS']
    time = TAITime(None, mjd=mjd)

    tim = tractor.Image(data=data, invvar=invvar, psf=tpsf, wcs=twcs,
                        sky=tsky, photocal=photocal, time=time, name=name, zr=zr,
                        domask=False)
    tim.extent = [x0, x1, y0, y1]
    tim.sigma1 = sigma1
    #tim.roi = roi

    # FIXME
    tim.maskplane = mask
    tim.uncplane = unc
    tim.goodmask = goodmask

    # carry both around for retrofitting
    tim.vinvvar = vinvvar
    tim.cinvvar = cinvvar

    return tim
Beispiel #4
0
    ##  https://github.com/dstndstn/tractor/blob/13d3239500c5af873935c81d079c928f4cdf0b1d/doc/galsim.rst
    ##  _gflux        = tractor.Fluxes(g=gflux, r=0.0, z=0.0)
    _gflux = tractor.NanoMaggies(**{'g': gflux, 'r': 0.0, 'z': 0.0})

    src = RexGalaxy(tractor.RaDecPos(ra, dec), _gflux, LogRadius(gre))

    wcs = Tan(ra, dec, W / 2. + 0.5, H / 2. + 0.5, -ps, 0., 0., ps, float(W),
              float(H))
    wcs = tractor.ConstantFitsWcs(wcs)

    tims = []

    for band in ['g', 'r', 'z']:
        ##  photcal    = tractor.LinearPhotoCal(1., band=band)
        photcal = tractor.MagsPhotoCal(band, zpt)

        csky_level_sig = photcal.brightnessToCounts(sky_level_sig)

        ##  The rms of the noise in ADU.
        ##  noise      = galsim.PoissonNoise(rng, sky_level=sky_level_pixel)
        ##  Gaussian approximation for large N.
        ##  noise      = galsim.GaussianNoise(rng, sigma=sky_level_sig)
        ##  Rendered in counts.
        noise = np.random.normal(loc=csky_level_sig,
                                 scale=np.sqrt(csky_level_sig),
                                 size=(H, W))

        tim = tractor.Image(data=np.zeros((H, W), np.float32),
                            inverr=np.ones((H, W), np.float32),
                            psf=psf,
Beispiel #5
0
def read_wise_level3(basefn, radecroi=None, filtermap=None,
                     nanomaggies=False):
    if filtermap is None:
        filtermap = {}
    intfn = basefn + '-int-3.fits'
    uncfn = basefn + '-unc-3.fits'

    print('intensity image', intfn)
    print('uncertainty image', uncfn)

    P = pyfits.open(intfn)
    ihdr = P[0].header
    data = P[0].data
    print('Read', data.shape, 'intensity')
    band = ihdr['BAND']

    P = pyfits.open(uncfn)
    unc = P[0].data
    print('Read', unc.shape, 'uncertainty')

    ''' cov:
    BAND    =                    1 / wavelength band number
    WAVELEN =                3.368 / [microns] effective wavelength of band
    COADDID = '3342p000_ab41'      / atlas-image identifier
    MAGZP   =                 20.5 / [mag] relative photometric zero point
    MEDINT  =      4.0289044380188 / [DN] median of intensity pixels
    '''
    ''' int:
    BUNIT   = 'DN      '           / image pixel units
    CTYPE1  = 'RA---SIN'           / Projection type for axis 1
    CTYPE2  = 'DEC--SIN'           / Projection type for axis 2
    CRPIX1  =          2048.000000 / Axis 1 reference pixel at CRVAL1,CRVAL2
    CRPIX2  =          2048.000000 / Axis 2 reference pixel at CRVAL1,CRVAL2
    CDELT1  =  -0.0003819444391411 / Axis 1 scale at CRPIX1,CRPIX2 (deg/pix)
    CDELT2  =   0.0003819444391411 / Axis 2 scale at CRPIX1,CRPIX2 (deg/pix)
    CROTA2  =             0.000000 / Image twist: +axis2 W of N, J2000.0 (deg)
    '''
    ''' unc:
    FILETYPE= '1-sigma uncertainty image' / product description
    '''

    twcs = tractor.WcslibWcs(intfn)
    print('WCS', twcs)
    # twcs.debug()
    print('pixel scale', twcs.pixel_scale())

    # HACK -- circular Gaussian PSF of fixed size...
    # in arcsec
    fwhms = {1: 6.1, 2: 6.4, 3: 6.5, 4: 12.0}
    # -> sigma in pixels
    sig = fwhms[band] / 2.35 / twcs.pixel_scale()
    print('PSF sigma', sig, 'pixels')
    tpsf = tractor.NCircularGaussianPSF([sig], [1.])

    if radecroi is not None:
        ralo, rahi, declo, dechi = radecroi
        xy = [twcs.positionToPixel(tractor.RaDecPos(r, d))
              for r, d in [(ralo, declo), (ralo, dechi), (rahi, declo), (rahi, dechi)]]
        xy = np.array(xy)
        x0, x1 = xy[:, 0].min(), xy[:, 0].max()
        y0, y1 = xy[:, 1].min(), xy[:, 1].max()
        print('RA,Dec ROI', ralo, rahi, declo, dechi,
              'becomes x,y ROI', x0, x1, y0, y1)

        # Clip to image size...
        H, W = data.shape
        x0 = max(0, min(x0, W - 1))
        x1 = max(0, min(x1, W))
        y0 = max(0, min(y0, H - 1))
        y1 = max(0, min(y1, H))
        print(' clipped to', x0, x1, y0, y1)

        data = data[y0:y1, x0:x1]
        unc = unc[y0:y1, x0:x1]
        twcs.setX0Y0(x0, y0)
        print('Cut data to', data.shape)

    else:
        H, W = data.shape
        x0, x1, y0, y1 = 0, W, 0, H

    filt = 'w%i' % band
    if filtermap:
        filt = filtermap.get(filt, filt)
    zp = ihdr['MAGZP']

    if nanomaggies:
        photocal = tractor.LinearPhotoCal(tractor.NanoMaggies.zeropointToScale(zp),
                                          band=filt)
    else:
        photocal = tractor.MagsPhotoCal(filt, zp)

    print('Image median:', np.median(data))
    print('unc median:', np.median(unc))

    sky = np.median(data)
    tsky = tractor.ConstantSky(sky)

    sigma1 = np.median(unc)
    zr = np.array([-3, 10]) * sigma1 + sky

    name = 'WISE ' + ihdr['COADDID'] + ' W%i' % band

    tim = tractor.Image(data=data, invvar=1. / (unc**2), psf=tpsf, wcs=twcs,
                        sky=tsky, photocal=photocal, name=name, zr=zr,
                        domask=False)
    tim.extent = [x0, x1, y0, y1]
    return tim