Example #1
0
def add_depth_tag(decals, brick, outdir, overwrite=False):
    outfn = os.path.join(outdir, 'tractor', brick[:3], 'tractor-%s.fits' % brick)
    if os.path.exists(outfn) and not overwrite:
        print 'Exists:', outfn
        return
    fn = decals.find_file('tractor', brick=brick)
    if not os.path.exists(fn):
        print 'Does not exist:', fn
        return
    T = fits_table(fn, lower=False)
    primhdr = fitsio.read_header(fn)
    hdr = fitsio.read_header(fn, ext=1)
    print 'Read', len(T), 'from', fn
    T.decam_depth    = np.zeros((len(T), len(decals.allbands)), np.float32)
    T.decam_galdepth = np.zeros((len(T), len(decals.allbands)), np.float32)
    bands = 'grz'
    ibands = [decals.index_of_band(b) for b in bands]
    ix = np.clip(np.round(T.bx).astype(int), 0, 3599)
    iy = np.clip(np.round(T.by).astype(int), 0, 3599)
    for iband,band in zip(ibands, bands):
        fn = decals.find_file('depth', brick=brick, band=band)
        if os.path.exists(fn):
            print 'Reading', fn
            img = fitsio.read(fn)
            T.decam_depth[:,iband] = img[iy, ix]

        fn = decals.find_file('galdepth', brick=brick, band=band)
        if os.path.exists(fn):
            print 'Reading', fn
            img = fitsio.read(fn)
            T.decam_galdepth[:,iband] = img[iy, ix]
    outfn = os.path.join(outdir, 'tractor', brick[:3], 'tractor-%s.fits' % brick)
    trymakedirs(outfn, dir=True)

    for s in [
        'Data product of the DECam Legacy Survey (DECaLS)',
        'Full documentation at http://legacysurvey.org',
        ]:
        primhdr.add_record(dict(name='COMMENT', value=s, comment=s))

    # print 'Header:', hdr
    # T.writeto(outfn, header=hdr, primheader=primhdr)

    # Yuck, all this to get the units right
    tmpfn = outfn + '.tmp'
    fits = fitsio.FITS(tmpfn, 'rw', clobber=True)
    fits.write(None, header=primhdr)
    cols = T.get_columns()
    units = []
    for i in range(1, len(cols)+1):
        u = hdr.get('TUNIT%i' % i, '')
        units.append(u)
    # decam_depth units
    fluxiv = '1/nanomaggy^2'
    units[-2] = fluxiv
    units[-1] = fluxiv
    fits.write([T.get(c) for c in cols], names=cols, header=hdr, units=units)
    fits.close()
    os.rename(tmpfn, outfn)
    print 'Wrote', outfn
Example #2
0
 def copy_files_to_cache(fns):
     for fn in fns:
         cachefn = fn.replace(survey.survey_dir, survey.cache_dir)
         if not cachefn.startswith(survey.cache_dir):
             print('Skipping', fn)
             continue
         outdir = os.path.dirname(cachefn)
         trymakedirs(outdir)
         print('Copy', fn)
         print('  to', cachefn)
         shutil.copyfile(fn, cachefn)
Example #3
0
def merge_splinesky(survey, expnum, C, skyoutfn, opt):
    skies = []
    imobjs = []
    Cgood = []
    for ccd in C:
        im = survey.get_image_object(ccd)
        fn = im.skyfn
        if not os.path.exists(fn):
            print('File not found:', fn)
            if opt.all_found:
                return 0
            continue
        imobjs.append(im)
        Cgood.append(ccd)

    for ccd, im in zip(Cgood, imobjs):
        fn = im.skyfn
        print('Reading', fn)
        T = None
        try:
            T = fits_table(fn)
        except KeyboardInterrupt as e:
            raise e
        except:
            print('Failed to read file', fn, ':', sys.exc_info()[1])
        if T is not None:
            skies.append(T)

    if len(skies) == 0:
        return
    T = fits_table()
    T.gridw = np.array([t.gridvals[0].shape[1] for t in skies])
    T.gridh = np.array([t.gridvals[0].shape[0] for t in skies])
    padded = pad_arrays([t.gridvals[0] for t in skies])
    T.gridvals = np.concatenate([[p] for p in padded])
    padded = pad_arrays([t.xgrid[0] for t in skies])
    T.xgrid = np.concatenate([[p] for p in padded])
    padded = pad_arrays([t.ygrid[0] for t in skies])
    T.ygrid = np.concatenate([[p] for p in padded])

    cols = skies[0].columns()
    for c in ['gridvals', 'xgrid', 'ygrid', 'gridw', 'gridh']:
        cols.remove(c)

    T.add_columns_from(merge_tables(skies, columns=cols))
    fn = skyoutfn
    trymakedirs(fn, dir=True)
    tmpfn = os.path.join(os.path.dirname(fn), 'tmp-' + os.path.basename(fn))
    T.writeto(tmpfn)
    os.rename(tmpfn, fn)
    print('Wrote', fn)
    return 1
Example #4
0
    def run_se(self, surveyname, imgfn, maskfn):
        from astrometry.util.file import trymakedirs
        # grab header values...
        primhdr = self.read_image_primary_header()
        try:
            magzp = float(primhdr['MAGZERO'])
        except:
            magzp = 25.
        seeing = self.pixscale * self.fwhm
        print('FWHM', self.fwhm, 'pix')
        print('pixscale', self.pixscale, 'arcsec/pix')
        print('Seeing', seeing, 'arcsec')
        print('magzp', magzp)

        sedir = self.survey.get_se_dir()
        trymakedirs(self.sefn, dir=True)
        if surveyname != '90prime':
            cmd = ' '.join([
                'sex',
                '-c',
                os.path.join(sedir, surveyname + '.se'),
                '-SEEING_FWHM %f' % seeing,
                '-PARAMETERS_NAME',
                os.path.join(sedir, surveyname + '.param'),
                '-STARNNW_NAME',
                os.path.join(sedir, 'default.nnw'),
                '-PIXEL_SCALE 0',
                # SE has a *bizarre* notion of "sigma"
                '-DETECT_THRESH 1.0',
                '-ANALYSIS_THRESH 1.0',
                '-MAG_ZEROPOINT %f' % magzp,
                '-FLAG_IMAGE %s' % maskfn,
                '-FILTER_NAME %s' % os.path.join(sedir, 'gauss_5.0_9x9.conv'),
                '-CATALOG_NAME %s %s' % (self.sefn, imgfn)
            ])
        else:
            cmd = ' '.join([
                'sex', '-c',
                os.path.join(sedir, surveyname + '.se'), '-PARAMETERS_NAME',
                os.path.join(sedir, surveyname + '.param'), '-STARNNW_NAME',
                os.path.join(sedir, 'default.nnw'),
                '-FILTER_NAME %s' % os.path.join(sedir, surveyname + '.conv'),
                '-PHOT_APERTURES 7.5,15.0,22.0',
                '-CATALOG_NAME %s %s' % (self.sefn, imgfn)
            ])
        print(cmd)

        if os.system(cmd):
            raise RuntimeError('Command failed: ' + cmd)
Example #5
0
def merge_psfex(survey, expnum, C, psfoutfn, opt):
    psfex = []
    imobjs = []
    Cgood = []
    fns = []
    for ccd in C:
        im = survey.get_image_object(ccd)
        for fn in [im.psffn, im.old_single_psffn]:
            if os.path.exists(fn):
                break
        if not os.path.exists(fn):
            print('File not found:', fn)
            if opt.all_found:
                return 0
            continue
        imobjs.append(im)
        Cgood.append(ccd)
        fns.append(fn)

    for fn, ccd, im in zip(fns, Cgood, imobjs):
        print('Reading', fn)
        T = fits_table(fn)

        cols = T.get_columns()
        if not 'plver' in cols:
            from legacypipe.image import psfex_single_to_merged
            T = psfex_single_to_merged(fn, ccd.expnum, ccd.ccdname)
            for k in ['plver', 'procdate', 'plprocid']:
                T.set(k, np.array([getattr(ccd, k)]))
        psfex.append(T)

    if len(psfex) == 0:
        return
    padded = pad_arrays([p.psf_mask[0] for p in psfex])
    cols = psfex[0].columns()
    cols.remove('psf_mask')
    T = merge_tables(psfex, columns=cols)
    T.psf_mask = np.concatenate([[p] for p in padded])
    fn = psfoutfn
    trymakedirs(fn, dir=True)
    tmpfn = os.path.join(os.path.dirname(fn), 'tmp-' + os.path.basename(fn))
    T.writeto(tmpfn)
    os.rename(tmpfn, fn)
    print('Wrote', fn)
    return 1
Example #6
0
    def run_se(self, imgfn, maskfn):
        from astrometry.util.file import trymakedirs
        sedir = self.survey.get_se_dir()
        trymakedirs(self.sefn, dir=True)
        # We write the SE catalog to a temp file then rename, to avoid
        # partially-written outputs.

        from legacypipe.survey import create_temp
        import fitsio

        tmpmaskfn = create_temp(suffix='.fits')
        # # The test.mask file has 1 for good pix, 0 for bad... invert for SE
        goodpix = fitsio.read(maskfn)
        fitsio.write(tmpmaskfn, (1 - goodpix).astype(np.uint8), clobber=True)
        #tmpmaskfn = maskfn

        tmpfn = os.path.join(os.path.dirname(self.sefn),
                             'tmp-' + os.path.basename(self.sefn))
        cmd = ' '.join([
            'sex',
            '-c',
            os.path.join(sedir, self.camera + '.se'),
            '-PARAMETERS_NAME',
            os.path.join(sedir, self.camera + '.param'),
            '-FILTER_NAME %s' % os.path.join(sedir, self.camera + '.conv'),
            '-FLAG_IMAGE %s' % tmpmaskfn,
            '-CATALOG_NAME %s' % tmpfn,
            '-SEEING_FWHM %f' % 0.8,
            '-FITS_UNSIGNED N',
            #'-VERBOSE_TYPE FULL',
            #'-PIXEL_SCALE 0.185',
            #'-SATUR_LEVEL 100000',
            imgfn
        ])
        print(cmd)
        rtn = os.system(cmd)
        if rtn:
            raise RuntimeError('Command failed: ' + cmd)
        os.rename(tmpfn, self.sefn)

        os.unlink(tmpmaskfn)
Example #7
0
 def run_psfex(self, surveyname):
     from astrometry.util.file import trymakedirs
     from legacypipe.survey import get_git_version
     sedir = self.survey.get_se_dir()
     trymakedirs(self.psffn, dir=True)
     primhdr = self.read_image_primary_header()
     plver = primhdr.get('PLVER', '')
     verstr = get_git_version()
     cmds = [
         'psfex -c %s -PSF_DIR %s %s' %
         (os.path.join(sedir, surveyname + '.psfex'),
          os.path.dirname(self.psffn), self.sefn),
         'modhead %s LEGPIPEV %s "legacypipe git version"' %
         (self.psffn, verstr),
         'modhead %s PLVER %s "CP ver of image file"' % (self.psffn, plver)
     ]
     for cmd in cmds:
         print(cmd)
         rtn = os.system(cmd)
         if rtn:
             raise RuntimeError('Command failed: %s: return value: %i' %
                                (cmd, rtn))
Example #8
0
    def run_calibs(self,
                   pvastrom=True,
                   psfex=True,
                   sky=True,
                   se=False,
                   funpack=False,
                   fcopy=False,
                   use_mask=True,
                   force=False,
                   just_check=False,
                   git_version=None,
                   splinesky=False):
        '''
        Run calibration pre-processing steps.

        Parameters
        ----------
        just_check: boolean
            If True, returns True if calibs need to be run.
        '''
        from .common import (create_temp, get_version_header, get_git_version)

        #for fn in [self.pvwcsfn, self.sefn, self.psffn, self.skyfn, self.splineskyfn]:
        #    print('exists?', os.path.exists(fn), fn)

        if psfex and os.path.exists(self.psffn) and (not force):
            # Sometimes SourceExtractor gets interrupted or something and
            # writes out 0 detections.  Then PsfEx fails but in a way that
            # an output file is still written.  Try to detect & fix this
            # case.
            # Check the PsfEx output file for POLNAME1
            hdr = fitsio.read_header(self.psffn, ext=1)
            if hdr.get('POLNAME1', None) is None:
                print('Did not find POLNAME1 in PsfEx header', self.psffn,
                      '-- deleting')
                os.unlink(self.psffn)
            else:
                psfex = False
        if psfex:
            se = True

        if se and os.path.exists(self.sefn) and (not force):
            # Check SourceExtractor catalog for size = 0
            fn = self.sefn
            T = fits_table(fn, hdu=2)
            print('Read', len(T), 'sources from SE catalog', fn)
            if T is None or len(T) == 0:
                print('SourceExtractor catalog', fn,
                      'has no sources -- deleting')
                try:
                    os.unlink(fn)
                except:
                    pass
            if os.path.exists(self.sefn):
                se = False
        if se:
            funpack = True

        if pvastrom and os.path.exists(self.pvwcsfn) and (not force):
            fn = self.pvwcsfn
            if os.path.exists(fn):
                try:
                    wcs = Sip(fn)
                except:
                    print('Failed to read PV-SIP file', fn, '-- deleting')
                    os.unlink(fn)
            if os.path.exists(fn):
                pvastrom = False

        if sky and (not force) and (
            (os.path.exists(self.skyfn) and not splinesky) or
            (os.path.exists(self.splineskyfn) and splinesky)):
            fn = self.skyfn
            if splinesky:
                fn = self.splineskyfn

            if os.path.exists(fn):
                try:
                    hdr = fitsio.read_header(fn)
                except:
                    print('Failed to read sky file', fn, '-- deleting')
                    os.unlink(fn)
            if os.path.exists(fn):
                print('File', fn, 'exists -- skipping')
                sky = False

        if just_check:
            return (se or psfex or sky or pvastrom)

        tmpimgfn = None
        tmpmaskfn = None

        # Unpacked image file
        funimgfn = self.imgfn
        funmaskfn = self.dqfn

        if funpack:
            # For FITS files that are not actually fpack'ed, funpack -E
            # fails.  Check whether actually fpacked.
            hdr = fitsio.read_header(self.imgfn, ext=self.hdu)
            if not ((hdr['XTENSION'] == 'BINTABLE')
                    and hdr.get('ZIMAGE', False)):
                print(
                    'Image', self.imgfn, 'HDU', self.hdu,
                    'is not actually fpacked; not funpacking, just imcopying.')
                fcopy = True

            tmpimgfn = create_temp(suffix='.fits')
            tmpmaskfn = create_temp(suffix='.fits')

            if fcopy:
                cmd = 'imcopy %s"+%i" %s' % (self.imgfn, self.hdu, tmpimgfn)
            else:
                cmd = 'funpack -E %i -O %s %s' % (self.hdu, tmpimgfn,
                                                  self.imgfn)
            print(cmd)
            if os.system(cmd):
                raise RuntimeError('Command failed: ' + cmd)
            funimgfn = tmpimgfn

            if use_mask:
                if fcopy:
                    cmd = 'imcopy %s"+%i" %s' % (self.dqfn, self.hdu,
                                                 tmpmaskfn)
                else:
                    cmd = 'funpack -E %i -O %s %s' % (self.hdu, tmpmaskfn,
                                                      self.dqfn)
                print(cmd)
                if os.system(cmd):
                    #raise RuntimeError('Command failed: ' + cmd)
                    print('Command failed: ' + cmd)
                    M, hdr = fitsio.read(self.dqfn, ext=self.hdu, header=True)
                    print('Read', M.dtype, M.shape)
                    fitsio.write(tmpmaskfn, M, header=hdr, clobber=True)
                    print('Wrote', tmpmaskfn, 'with fitsio')

                funmaskfn = tmpmaskfn

        if se:
            # grab header values...
            primhdr = self.read_image_primary_header()
            magzp = primhdr['MAGZERO']
            seeing = self.pixscale * self.fwhm
            #print('FWHM', self.fwhm, 'pix')
            #print('pixscale', self.pixscale, 'arcsec/pix')
            #print('Seeing', seeing, 'arcsec')

        if se:
            maskstr = ''
            if use_mask:
                maskstr = '-FLAG_IMAGE ' + funmaskfn
            sedir = self.decals.get_se_dir()

            trymakedirs(self.sefn, dir=True)

            cmd = ' '.join([
                'sex',
                '-c',
                os.path.join(sedir, 'DECaLS.se'),
                maskstr,
                '-SEEING_FWHM %f' % seeing,
                '-PARAMETERS_NAME',
                os.path.join(sedir, 'DECaLS.param'),
                '-FILTER_NAME',
                os.path.join(sedir, 'gauss_5.0_9x9.conv'),
                '-STARNNW_NAME',
                os.path.join(sedir, 'default.nnw'),
                '-PIXEL_SCALE 0',
                # SE has a *bizarre* notion of "sigma"
                '-DETECT_THRESH 1.0',
                '-ANALYSIS_THRESH 1.0',
                '-MAG_ZEROPOINT %f' % magzp,
                '-CATALOG_NAME',
                self.sefn,
                funimgfn
            ])
            print(cmd)
            if os.system(cmd):
                raise RuntimeError('Command failed: ' + cmd)

        if pvastrom:
            # DECam images appear to have PV coefficients up to PVx_10,
            # which are up to cubic terms in xi,eta,r.  Overshoot what we
            # need in SIP terms.
            tmpwcsfn = create_temp(suffix='.wcs')
            cmd = ('wcs-pv2sip -S -o 6 -e %i %s %s' %
                   (self.hdu, self.imgfn, tmpwcsfn))
            print(cmd)
            if os.system(cmd):
                raise RuntimeError('Command failed: ' + cmd)
            # Read the resulting WCS header and add version info cards to it.
            version_hdr = get_version_header(None,
                                             self.decals.get_decals_dir(),
                                             git_version=git_version)
            primhdr = self.read_image_primary_header()
            plver = primhdr.get('PLVER', '').strip()
            version_hdr.add_record(
                dict(name='PLVER', value=plver,
                     comment='CP ver of image file'))
            wcshdr = fitsio.read_header(tmpwcsfn)
            os.unlink(tmpwcsfn)
            for r in wcshdr.records():
                version_hdr.add_record(r)

            trymakedirs(self.pvwcsfn, dir=True)

            fitsio.write(self.pvwcsfn, None, header=version_hdr, clobber=True)
            print('Wrote', self.pvwcsfn)

        if psfex:
            sedir = self.decals.get_se_dir()

            trymakedirs(self.psffn, dir=True)

            # If we wrote *.psf instead of *.fits in a previous run...
            oldfn = self.psffn.replace('.fits', '.psf')
            if os.path.exists(oldfn):
                print('Moving', oldfn, 'to', self.psffn)
                os.rename(oldfn, self.psffn)
            else:
                primhdr = self.read_image_primary_header()
                plver = primhdr.get('PLVER', '')
                verstr = get_git_version()
                cmds = [
                    'psfex -c %s -PSF_DIR %s %s' %
                    (os.path.join(sedir, 'DECaLS.psfex'),
                     os.path.dirname(self.psffn), self.sefn),
                    'modhead %s LEGPIPEV %s "legacypipe git version"' %
                    (self.psffn, verstr),
                    'modhead %s PLVER %s "CP ver of image file"' %
                    (self.psffn, plver)
                ]
                for cmd in cmds:
                    print(cmd)
                    rtn = os.system(cmd)
                    if rtn:
                        raise RuntimeError('Command failed: ' + cmd +
                                           ': return value: %i' % rtn)

        if sky:
            #print('Fitting sky for', self)

            hdr = get_version_header(None,
                                     self.decals.get_decals_dir(),
                                     git_version=git_version)
            primhdr = self.read_image_primary_header()
            plver = primhdr.get('PLVER', '')
            hdr.delete('PROCTYPE')
            hdr.add_record(
                dict(name='PROCTYPE',
                     value='ccd',
                     comment='NOAO processing type'))
            hdr.add_record(
                dict(name='PRODTYPE',
                     value='skymodel',
                     comment='NOAO product type'))
            hdr.add_record(
                dict(name='PLVER', value=plver,
                     comment='CP ver of image file'))

            slc = self.get_good_image_slice(None)
            #print('Good image slice is', slc)

            img = self.read_image(slice=slc)
            wt = self.read_invvar(slice=slc)

            if splinesky:
                from tractor.splinesky import SplineSky
                from scipy.ndimage.morphology import binary_dilation

                # Start by subtracting the overall median
                med = np.median(img[wt > 0])
                # Compute initial model...
                skyobj = SplineSky.BlantonMethod(img - med, wt > 0, 512)
                skymod = np.zeros_like(img)
                skyobj.addTo(skymod)
                # Now mask bright objects in (image - initial sky model)
                sig1 = 1. / np.sqrt(np.median(wt[wt > 0]))
                masked = (img - med - skymod) > (5. * sig1)
                masked = binary_dilation(masked, iterations=3)
                masked[wt == 0] = True
                # Now find the final sky model using that more extensive mask
                skyobj = SplineSky.BlantonMethod(img - med,
                                                 np.logical_not(masked), 512)
                # add the median back in
                skyobj.offset(med)

                if slc is not None:
                    sy, sx = slc
                    y0 = sy.start
                    x0 = sx.start
                    skyobj.shift(-x0, -y0)

                trymakedirs(self.splineskyfn, dir=True)
                skyobj.write_fits(self.splineskyfn, primhdr=hdr)
                print('Wrote sky model', self.splineskyfn)

            else:
                img = img[wt > 0]
                try:
                    skyval = estimate_mode(img, raiseOnWarn=True)
                    skymeth = 'mode'
                except:
                    skyval = np.median(img)
                    skymeth = 'median'
                tsky = ConstantSky(skyval)

                hdr.add_record(
                    dict(name='SKYMETH',
                         value=skymeth,
                         comment='estimate_mode, or fallback to median?'))
                trymakedirs(self.skyfn, dir=True)
                tsky.write_fits(self.skyfn, hdr=hdr)
                print('Wrote sky model', self.skyfn)

        if tmpimgfn is not None:
            os.unlink(tmpimgfn)
        if tmpmaskfn is not None:
            os.unlink(tmpmaskfn)
Example #9
0
fns = glob(indir + '/*/*/*.fits')
# Test sets!
# fns = glob(indir + '/decam/00500/*.fits')
# fns = glob(indir + '/mosaic/00064/*.fits')
# fns = glob(indir + '/90prime/73380/*.fits')
# fns = (glob(indir + '/decam/00500/*.fits')[:10] +
#        glob(indir + '/mosaic/00064/*.fits')[:10] +
#        glob(indir + '/90prime/73380/*.fits')[:10])
fns.sort()

for ifn,fn in enumerate(fns):
    print('Reading', ifn+1, 'of', len(fns), ':', fn)
    
    outfn = fn.replace(indir, outdir)
    dirname = os.path.dirname(outfn)
    trymakedirs(dirname)
    T = fits_table(fn)
    hdr = T.get_header()
    primhdr = fitsio.read_header(fn)
    #print('Header:', hdr)

    T.camera = T.camera.astype('S7')  # '90prime'
    T.ccdname = T.ccdname.astype('S4')   # 'CCD4'
    T.expnum = T.expnum.astype(np.int64)
    T.ccd_cuts = T.ccd_cuts.astype(np.int64)

    units = dict()
    for i,c in enumerate(T.get_columns()):
        u = hdr.get('TUNIT%i' % (i+1))
        if u is None:
            continue
Example #10
0
    def run_calibs(self, psfex=True, sky=True, funpack=False, git_version=None,
                       force=False,
                       **kwargs):
        print('run_calibs for', self.name, ': sky=', sky, 'kwargs', kwargs) 
        se = False
        if psfex and os.path.exists(self.psffn) and (not force):
            psfex = False
        if psfex:
            se = True

        if se and os.path.exists(self.sefn) and (not force):
            se = False
        if se:
            sedir = self.survey.get_se_dir()
            trymakedirs(self.sefn, dir=True)
            ####
            trymakedirs('junk',dir=True) #need temp dir for mask-2 and invvar map
            hdu=0
            maskfn= self.imgfn.replace('_scie_','_mask_')
            invvar= read_invvar(self.imgfn,maskfn,hdu) #note, all post processing on image,mask done in read_invvar
            mask= read_dq(maskfn,hdu)
            maskfn= os.path.join('junk',os.path.basename(maskfn))
            invvarfn= maskfn.replace('_mask_','_invvar_')
            fitsio.write(maskfn, mask)
            fitsio.write(invvarfn, invvar)
            print('wrote mask-2 to %s, invvar to %s' % (maskfn,invvarfn))
            #run se 
            hdr=fitsio.read_header(self.imgfn,ext=hdu)
            magzp  = zeropoint_for_ptf(hdr)
            seeing = hdr['PIXSCALE'] * hdr['MEDFWHM']
            gain= hdr['GAIN']
            cmd = ' '.join(['sex','-c', os.path.join(sedir,'ptf.se'),
                            '-WEIGHT_IMAGE %s' % invvarfn, '-WEIGHT_TYPE MAP_WEIGHT',
                            '-GAIN %f' % gain,
                            '-FLAG_IMAGE %s' % maskfn,
                            '-FLAG_TYPE OR',
                            '-SEEING_FWHM %f' % seeing,
                            '-DETECT_MINAREA 3',
                            '-PARAMETERS_NAME', os.path.join(sedir,'ptf.param'),
                            '-FILTER_NAME', os.path.join(sedir, 'ptf_gauss_3.0_5x5.conv'),
                            '-STARNNW_NAME', os.path.join(sedir, 'ptf_default.nnw'),
                            '-PIXEL_SCALE 0',
                            # SE has a *bizarre* notion of "sigma"
                            '-DETECT_THRESH 1.0',
                            '-ANALYSIS_THRESH 1.0',
                            '-MAG_ZEROPOINT %f' % magzp,
                            '-CATALOG_NAME', self.sefn,
                            self.imgfn])
            print(cmd)
            if os.system(cmd):
                raise RuntimeError('Command failed: ' + cmd)
        if psfex:
            sedir = self.survey.get_se_dir()
            trymakedirs(self.psffn, dir=True)
            # If we wrote *.psf instead of *.fits in a previous run...
            oldfn = self.psffn.replace('.fits', '.psf')
            if os.path.exists(oldfn):
                print('Moving', oldfn, 'to', self.psffn)
                os.rename(oldfn, self.psffn)
            else: 
                cmd= ' '.join(['psfex',self.sefn,'-c', os.path.join(sedir,'ptf.psfex'),
                    '-PSF_DIR',os.path.dirname(self.psffn)])
                print(cmd)
                if os.system(cmd):
                    raise RuntimeError('Command failed: ' + cmd)
Example #11
0
    def run_calibs(self, psfex=True, sky=True, funpack=False, git_version=None,
                   force=False,
                   **kwargs):
        from astrometry.util.file import trymakedirs
        from legacypipe.common import (create_temp, get_version_header,
                                       get_git_version)

        print('run_calibs for', self.name, ': sky=', sky, 'kwargs', kwargs)

        se = False
        if psfex and os.path.exists(self.psffn) and (not force):
            psfex = False
        if psfex:
            se = True

        if se and os.path.exists(self.sefn) and (not force):
            se = False
        if se:
            funpack = True

        if sky and (not force) and os.path.exists(self.splineskyfn):
            sky = False

        tmpimgfn = None
        tmpmaskfn = None

        # Unpacked image file
        funimgfn = self.imgfn
        funmaskfn = self.dqfn
        
        if funpack:
            # For FITS files that are not actually fpack'ed, funpack -E
            # fails.  Check whether actually fpacked.
            hdr = fitsio.read_header(self.imgfn, ext=self.hdu)
            if not ((hdr['XTENSION'] == 'BINTABLE') and hdr.get('ZIMAGE', False)):
                print('Image', self.imgfn, 'HDU', self.hdu, 'is not actually fpacked; not funpacking, just imcopying.')
                fcopy = True

            tmpimgfn  = create_temp(suffix='.fits')
            tmpmaskfn = create_temp(suffix='.fits')
    
            cmd = 'funpack -E %i -O %s %s' % (self.hdu, tmpimgfn, self.imgfn)
            print(cmd)
            if os.system(cmd):
                raise RuntimeError('Command failed: ' + cmd)
            funimgfn = tmpimgfn
            
            cmd = 'funpack -E %i -O %s %s' % (self.hdu, tmpmaskfn, self.dqfn)
            print(cmd)
            if os.system(cmd):
                print('Command failed: ' + cmd)
                M,hdr = self._read_fits(self.dqfn, ext=self.hdu, header=True)
                print('Read', M.dtype, M.shape)
                fitsio.write(tmpmaskfn, M, header=hdr, clobber=True)
                print('Wrote', tmpmaskfn, 'with fitsio')
            funmaskfn = tmpmaskfn
    
        if se:
            # grab header values...
            primhdr = self.read_image_primary_header()
            magzp  = primhdr['MAGZERO']
            seeing = self.pixscale * self.fwhm

            print('FWHM', self.fwhm, 'pix')
            print('pixscale', self.pixscale, 'arcsec/pix')
            print('Seeing', seeing, 'arcsec')
    
        if se:
            maskstr = '-FLAG_IMAGE ' + funmaskfn
            sedir = self.decals.get_se_dir()

            trymakedirs(self.sefn, dir=True)

            cmd = ' '.join([
                'sex',
                '-c', os.path.join(sedir, 'DECaLS.se'),
                maskstr,
                '-SEEING_FWHM %f' % seeing,
                '-PARAMETERS_NAME', os.path.join(sedir, 'DECaLS.param'),
                '-FILTER_NAME', os.path.join(sedir, 'gauss_5.0_9x9.conv'),
                '-STARNNW_NAME', os.path.join(sedir, 'default.nnw'),
                '-PIXEL_SCALE 0',
                # SE has a *bizarre* notion of "sigma"
                '-DETECT_THRESH 1.0',
                '-ANALYSIS_THRESH 1.0',
                '-MAG_ZEROPOINT %f' % magzp,
                '-CATALOG_NAME', self.sefn,
                funimgfn])
            print(cmd)
            if os.system(cmd):
                raise RuntimeError('Command failed: ' + cmd)
        if psfex:
            sedir = self.decals.get_se_dir()
            trymakedirs(self.psffn, dir=True)

            # If we wrote *.psf instead of *.fits in a previous run...
            oldfn = self.psffn.replace('.fits', '.psf')
            if os.path.exists(oldfn):
                print('Moving', oldfn, 'to', self.psffn)
                os.rename(oldfn, self.psffn)
            else:
                primhdr = self.read_image_primary_header()
                plver = primhdr.get('PLVER', '')
                verstr = get_git_version()
                cmds = ['psfex -c %s -PSF_DIR %s %s' %
                        (os.path.join(sedir, 'DECaLS.psfex'),
                         os.path.dirname(self.psffn), self.sefn),
                        'modhead %s LEGPIPEV %s "legacypipe git version"' %
                        (self.psffn, verstr),
                        'modhead %s PLVER %s "CP ver of image file"' %
                        (self.psffn, plver)]
                for cmd in cmds:
                    print(cmd)
                    rtn = os.system(cmd)
                    if rtn:
                        raise RuntimeError('Command failed: ' + cmd + ': return value: %i' % rtn)

        if sky:
            #print('Fitting sky for', self)

            hdr = get_version_header(None, self.decals.get_decals_dir(),
                                     git_version=git_version)
            primhdr = self.read_image_primary_header()
            plver = primhdr.get('PLVER', '')
            hdr.delete('PROCTYPE')
            hdr.add_record(dict(name='PROCTYPE', value='ccd',
                                comment='NOAO processing type'))
            hdr.add_record(dict(name='PRODTYPE', value='skymodel',
                                comment='NOAO product type'))
            hdr.add_record(dict(name='PLVER', value=plver,
                                comment='CP ver of image file'))

            slc = self.get_good_image_slice(None)
            #print('Good image slice is', slc)

            img = self.read_image(slice=slc)
            wt = self.read_invvar(slice=slc)

            from tractor.splinesky import SplineSky
            from scipy.ndimage.morphology import binary_dilation

            # Start by subtracting the overall median
            med = np.median(img[wt>0])
            # Compute initial model...
            skyobj = SplineSky.BlantonMethod(img - med, wt>0, 512)
            skymod = np.zeros_like(img)
            skyobj.addTo(skymod)
            # Now mask bright objects in (image - initial sky model)
            sig1 = 1./np.sqrt(np.median(wt[wt>0]))
            masked = (img - med - skymod) > (5.*sig1)
            masked = binary_dilation(masked, iterations=3)
            masked[wt == 0] = True
            # Now find the final sky model using that more extensive mask
            skyobj = SplineSky.BlantonMethod(img - med, np.logical_not(masked), 512)
            # add the median back in
            skyobj.offset(med)

            if slc is not None:
                sy,sx = slc
                y0 = sy.start
                x0 = sx.start
                skyobj.shift(-x0, -y0)

            trymakedirs(self.splineskyfn, dir=True)
            skyobj.write_fits(self.splineskyfn, primhdr=hdr)
            print('Wrote sky model', self.splineskyfn)

        if tmpimgfn is not None:
            os.unlink(tmpimgfn)
        if tmpmaskfn is not None:
            os.unlink(tmpmaskfn)
Example #12
0
def main(survey=None, opt=None, args=None):
    '''Driver function for forced photometry of individual Legacy
    Survey images.
    '''
    if args is None:
        args = sys.argv[1:]
    print('forced_photom.py', ' '.join(args))

    if opt is None:
        parser = get_parser()
        opt = parser.parse_args(args)

    import logging
    if opt.verbose == 0:
        lvl = logging.INFO
    else:
        lvl = logging.DEBUG
    logging.basicConfig(level=lvl, format='%(message)s', stream=sys.stdout)
    # tractor logging is *soooo* chatty
    logging.getLogger('tractor.engine').setLevel(lvl + 10)

    t0 = Time()
    if survey is None:
        survey = LegacySurveyData(survey_dir=opt.survey_dir,
                                  cache_dir=opt.cache_dir,
                                  output_dir=opt.out_dir)
    if opt.skip:
        if opt.out is not None:
            outfn = opt.out
        else:
            outfn = survey.find_file('forced',
                                     output=True,
                                     camera=opt.camera,
                                     expnum=opt.expnum)
        if os.path.exists(outfn):
            print('Ouput file exists:', outfn)
            return 0

    if opt.derivs and opt.agn:
        print('Sorry, can\'t do --derivs AND --agn')
        return -1

    if opt.out is None and opt.out_dir is None:
        print('Must supply either --out or --out-dir')
        return -1

    if opt.expnum is None and opt.out is None:
        print('If no --expnum is given, must supply --out filename')
        return -1

    if not opt.forced:
        opt.apphot = True

    zoomslice = None
    if opt.zoom is not None:
        (x0, x1, y0, y1) = opt.zoom
        zoomslice = (slice(y0, y1), slice(x0, x1))

    ps = None
    if opt.plots is not None:
        from astrometry.util.plotutils import PlotSequence
        ps = PlotSequence(opt.plots)

    # Cache CCDs files before the find_ccds call...
    # Copy required files into the cache?
    if opt.pre_cache:

        def copy_files_to_cache(fns):
            for fn in fns:
                cachefn = fn.replace(survey.survey_dir, survey.cache_dir)
                if not cachefn.startswith(survey.cache_dir):
                    print('Skipping', fn)
                    continue
                outdir = os.path.dirname(cachefn)
                trymakedirs(outdir)
                print('Copy', fn)
                print('  to', cachefn)
                shutil.copyfile(fn, cachefn)

        assert (survey.cache_dir is not None)
        fnset = set()
        fn = survey.find_file('bricks')
        fnset.add(fn)
        fns = survey.find_file('ccd-kds')
        fnset.update(fns)
        copy_files_to_cache(fnset)

    # Read metadata from survey-ccds.fits table
    ccds = survey.find_ccds(camera=opt.camera,
                            expnum=opt.expnum,
                            ccdname=opt.ccdname)
    print(len(ccds), 'with camera', opt.camera, 'and expnum', opt.expnum,
          'and ccdname', opt.ccdname)
    # sort CCDs
    ccds.cut(np.lexsort((ccds.ccdname, ccds.expnum, ccds.camera)))

    # If there is only one catalog survey_dir, we pass it to get_catalog_in_wcs
    # as the northern survey.
    catsurvey_north = survey
    catsurvey_south = None

    if opt.catalog_dir_north is not None:
        assert (opt.catalog_dir_south is not None)
        assert (opt.catalog_resolve_dec_ngc is not None)
        catsurvey_north = LegacySurveyData(survey_dir=opt.catalog_dir_north)
        catsurvey_south = LegacySurveyData(survey_dir=opt.catalog_dir_south)
    elif opt.catalog_dir is not None:
        catsurvey_north = LegacySurveyData(survey_dir=opt.catalog_dir)

    # Copy required CCD & calib files into the cache?
    if opt.pre_cache:
        assert (survey.cache_dir is not None)
        fnset = set()
        for ccd in ccds:
            im = survey.get_image_object(ccd)
            for key in im.get_cacheable_filename_variables():
                fn = getattr(im, key)
                if fn is None or not (os.path.exists(fn)):
                    continue
                fnset.add(fn)
        copy_files_to_cache(fnset)

    args = []
    for ccd in ccds:
        args.append((survey, catsurvey_north, catsurvey_south,
                     opt.catalog_resolve_dec_ngc, ccd, opt, zoomslice, ps))

    if opt.threads:
        from astrometry.util.multiproc import multiproc
        from astrometry.util.timingpool import TimingPool, TimingPoolMeas
        pool = TimingPool(opt.threads)
        poolmeas = TimingPoolMeas(pool, pickleTraffic=False)
        Time.add_measurement(poolmeas)
        mp = multiproc(None, pool=pool)
        tm = Time()
        FF = mp.map(bounce_one_ccd, args)
        print('Multi-processing forced-phot:', Time() - tm)
        del mp
        Time.measurements.remove(poolmeas)
        del poolmeas
        pool.close()
        pool.join()
        del pool
    else:
        FF = map(bounce_one_ccd, args)

    FF = [F for F in FF if F is not None]
    if len(FF) == 0:
        print('No photometry results to write.')
        return 0
    # Keep only the first header
    _, version_hdr, _, _ = FF[0]
    # unpack results
    outlier_masks = [m for _, _, m, _ in FF]
    outlier_hdrs = [h for _, _, _, h in FF]
    FF = [F for F, _, _, _ in FF]
    F = merge_tables(FF)

    if len(ccds):
        version_hdr.delete('CPHDU')
        version_hdr.delete('CCDNAME')

    from legacypipe.utils import add_bits
    from legacypipe.bits import DQ_BITS
    add_bits(version_hdr, DQ_BITS, 'DQMASK', 'DQ', 'D')
    from legacyzpts.psfzpt_cuts import CCD_CUT_BITS
    add_bits(version_hdr, CCD_CUT_BITS, 'CCD_CUTS', 'CC', 'C')
    for i, ap in enumerate(apertures_arcsec):
        version_hdr.add_record(
            dict(name='APRAD%i' % i,
                 value=ap,
                 comment='(optical) Aperture radius, in arcsec'))

    unitmap = {
        'exptime': 'sec',
        'flux': 'nanomaggy',
        'flux_ivar': '1/nanomaggy^2',
        'apflux': 'nanomaggy',
        'apflux_ivar': '1/nanomaggy^2',
        'psfdepth': '1/nanomaggy^2',
        'galdepth': '1/nanomaggy^2',
        'sky': 'nanomaggy/arcsec^2',
        'psfsize': 'arcsec',
        'fwhm': 'pixels',
        'ccdrarms': 'arcsec',
        'ccddecrms': 'arcsec',
        'ra': 'deg',
        'dec': 'deg',
        'skyrms': 'counts/sec',
        'dra': 'arcsec',
        'ddec': 'arcsec',
        'dra_ivar': '1/arcsec^2',
        'ddec_ivar': '1/arcsec^2'
    }

    columns = F.get_columns()
    order = [
        'release', 'brickid', 'brickname', 'objid', 'camera', 'expnum',
        'ccdname', 'filter', 'mjd', 'exptime', 'psfsize', 'fwhm', 'ccd_cuts',
        'airmass', 'sky', 'skyrms', 'psfdepth', 'galdepth', 'ccdzpt',
        'ccdrarms', 'ccddecrms', 'ccdphrms', 'ra', 'dec', 'flux', 'flux_ivar',
        'fracflux', 'rchisq', 'fracmasked', 'fracin', 'apflux', 'apflux_ivar',
        'x', 'y', 'dqmask', 'dra', 'ddec', 'dra_ivar', 'ddec_ivar'
    ]
    columns = [c for c in order if c in columns]
    units = [unitmap.get(c, '') for c in columns]

    if opt.out is not None:
        outdir = os.path.dirname(opt.out)
        if len(outdir):
            trymakedirs(outdir)
        tmpfn = os.path.join(outdir, 'tmp-' + os.path.basename(opt.out))
        fitsio.write(tmpfn, None, header=version_hdr, clobber=True)
        F.writeto(tmpfn, units=units, append=True, columns=columns)
        os.rename(tmpfn, opt.out)
        print('Wrote', opt.out)
    else:
        with survey.write_output('forced',
                                 camera=opt.camera,
                                 expnum=opt.expnum) as out:
            F.writeto(None,
                      fits_object=out.fits,
                      primheader=version_hdr,
                      units=units,
                      columns=columns)
            print('Wrote', out.real_fn)

    if opt.outlier_mask is not None:
        # Add outlier bit meanings to the primary header
        version_hdr.add_record(
            dict(name='COMMENT', value='Outlier mask bit meanings'))
        version_hdr.add_record(
            dict(name='OUTL_POS',
                 value=1,
                 comment='Outlier mask bit for Positive outlier'))
        version_hdr.add_record(
            dict(name='OUTL_NEG',
                 value=2,
                 comment='Outlier mask bit for Negative outlier'))

    if opt.outlier_mask == 'default':
        outdir = os.path.join(opt.out_dir, 'outlier-masks')
        camexp = set(zip(ccds.camera, ccds.expnum))
        for c, e in camexp:
            I = np.flatnonzero((ccds.camera == c) * (ccds.expnum == e))
            ccd = ccds[I[0]]
            imfn = ccd.image_filename.strip()
            outfn = os.path.join(outdir, imfn.replace('.fits',
                                                      '-outlier.fits'))
            trymakedirs(outfn, dir=True)
            tempfn = outfn.replace('.fits', '-tmp.fits')
            with fitsio.FITS(tempfn, 'rw', clobber=True) as fits:
                fits.write(None, header=version_hdr)
                for i in I:
                    mask = outlier_masks[i]
                    _, _, _, meth, tile = survey.get_compression_args(
                        'outliers_mask', shape=mask.shape)
                    fits.write(mask,
                               header=outlier_hdrs[i],
                               extname=ccds.ccdname[i],
                               compress=meth,
                               tile_dims=tile)
            os.rename(tempfn, outfn)
            print('Wrote', outfn)
    elif opt.outlier_mask is not None:
        with fitsio.FITS(opt.outlier_mask, 'rw', clobber=True) as F:
            F.write(None, header=version_hdr)
            for i, (hdr, mask) in enumerate(zip(outlier_hdrs, outlier_masks)):
                _, _, _, meth, tile = survey.get_compression_args(
                    'outliers_mask', shape=mask.shape)
                F.write(mask,
                        header=hdr,
                        extname=ccds.ccdname[i],
                        compress=meth,
                        tile_dims=tile)
        print('Wrote', opt.outlier_mask)

    tnow = Time()
    print('Total:', tnow - t0)
    return 0
Example #13
0
def main():
    fn = '/global/cscratch1/sd/dstn/c4d_190730_024955_ori/c4d_190730_024955_ori.52.fits'
    survey_dir = '/global/cscratch1/sd/dstn/subtractor-survey-dir'

    imagedir = os.path.join(survey_dir, 'images')
    trymakedirs(imagedir)
    calibdir = os.path.join(survey_dir, 'calib')

    psfexdir = os.path.join(calibdir, 'decam', 'psfex-merged')
    trymakedirs(psfexdir)
    skydir = os.path.join(calibdir, 'decam', 'splinesky-merged')
    trymakedirs(skydir)

    basename = os.path.basename(fn)
    basename = basename.replace('.fits', '')

    # Output filenames for legacyzpts calibration/zeropoint files
    f, photfn = tempfile.mkstemp()
    os.close(f)
    surveyfn = os.path.join(survey_dir, 'survey-ccds-%s.fits.gz' % basename)
    annfn = os.path.join(survey_dir, 'annotated-%s.fits' % basename)
    mp = multiproc()

    survey = LegacySurveyData(survey_dir)
    # Use the subclass above to handle DECam images!
    survey.image_typemap.update(decam=GoldsteinDecamImage)

    # Grab the exposure number and CCD name
    hdr = fitsio.read_header(fn)
    expnum = hdr['EXPNUM']
    ccdname = hdr['EXTNAME'].strip()
    print('Exposure', expnum, 'CCD', ccdname)

    import logging
    lvl = logging.INFO
    logging.basicConfig(level=lvl, format='%(message)s', stream=sys.stdout)
    # tractor logging is *soooo* chatty
    logging.getLogger('tractor.engine').setLevel(lvl + 10)

    if not os.path.exists(surveyfn):
        # Run calibrations and zeropoints
        runit(fn,
              photfn,
              surveyfn,
              annfn,
              mp,
              survey=survey,
              camera='decam',
              debug=False,
              choose_ccd=ccdname,
              splinesky=True,
              calibdir=calibdir,
              measureclass=GoldsteinDecamMeasurer)

    # Find catalog sources touching this CCD
    ccds = survey.find_ccds(expnum=expnum, ccdname=ccdname)
    assert (len(ccds) == 1)
    ccd = ccds[0]
    print('Got CCD', ccd)

    # Create Tractor image
    im = survey.get_image_object(ccd)
    print('Got image:', im)

    # Look at this sub-image, or the whole chip?
    #zoomslice=None
    zoomslice = (slice(0, 1000), slice(0, 1000))

    tim = im.get_tractor_image(slc=zoomslice,
                               pixPsf=True,
                               splinesky=True,
                               hybridPsf=True,
                               normalizePsf=True,
                               old_calibs_ok=True)
    print('Got tim:', tim)

    # Read catalog files touching this CCD
    catsurvey = LegacySurveyData(
        '/global/project/projectdirs/cosmo/work/legacysurvey/dr8/south')
    T = get_catalog_in_wcs(tim.subwcs, catsurvey)
    print('Got', len(T), 'DR8 catalog sources within CCD')

    # Gaia stars: move RA,Dec to the epoch of this image.
    I = np.flatnonzero(T.ref_epoch > 0)
    if len(I):
        from legacypipe.survey import radec_at_mjd
        print('Moving', len(I), 'Gaia stars to MJD', tim.time.toMjd())
        ra, dec = radec_at_mjd(T.ra[I], T.dec[I], T.ref_epoch[I].astype(float),
                               T.pmra[I], T.pmdec[I], T.parallax[I],
                               tim.time.toMjd())
        T.ra[I] = ra
        T.dec[I] = dec

    # Create Tractor Source objects from the catalog
    cat = read_fits_catalog(T, bands=tim.band)
    print('Created', len(cat), 'source objects')

    # Render model image!
    tr = Tractor([tim], cat)
    mod = tr.getModelImage(0)

    # plots
    ima = dict(interpolation='nearest',
               origin='lower',
               vmin=-2 * tim.sig1,
               vmax=10 * tim.sig1,
               cmap='gray')
    plt.clf()
    plt.imshow(tim.getImage(), **ima)
    plt.title('Image')
    plt.savefig('img.jpg')

    plt.clf()
    plt.imshow(mod, **ima)
    plt.title('Model')
    plt.savefig('mod.jpg')

    plt.clf()
    plt.imshow(tim.getImage() - mod, **ima)
    plt.title('Residual')
    plt.savefig('res.jpg')
Example #14
0
def main(decals=None, opt=None):
    '''Driver function for forced photometry of individual DECam images.
    '''
    if opt is None:
        parser = get_parser()
        opt = parser.parse_args()

    Time.add_measurement(MemMeas)
    t0 = Time()

    if os.path.exists(opt.outfn):
        print('Ouput file exists:', opt.outfn)
        sys.exit(0)

    if not opt.forced:
        opt.apphot = True

    zoomslice = None
    if opt.zoom is not None:
        (x0, x1, y0, y1) = opt.zoom
        zoomslice = (slice(y0, y1), slice(x0, x1))

    ps = None
    if opt.plots is not None:
        from astrometry.util.plotutils import PlotSequence
        ps = PlotSequence(opt.plots)

    # Try parsing filename as exposure number.
    try:
        expnum = int(opt.filename)
        opt.filename = None
    except:
        # make this 'None' for decals.find_ccds()
        expnum = None

    # Try parsing HDU number
    try:
        opt.hdu = int(opt.hdu)
        ccdname = None
    except:
        ccdname = opt.hdu
        opt.hdu = -1

    if decals is None:
        decals = Decals()

    if opt.filename is not None and opt.hdu >= 0:
        # Read metadata from file
        T = exposure_metadata([opt.filename], hdus=[opt.hdu])
        print('Metadata:')
        T.about()
    else:
        # Read metadata from decals-ccds.fits table
        T = decals.find_ccds(expnum=expnum, ccdname=ccdname)
        print(len(T), 'with expnum', expnum, 'and CCDname', ccdname)
        if opt.hdu >= 0:
            T.cut(T.image_hdu == opt.hdu)
            print(len(T), 'with HDU', opt.hdu)
        if opt.filename is not None:
            T.cut(
                np.array([f.strip() == opt.filename
                          for f in T.image_filename]))
            print(len(T), 'with filename', opt.filename)
        assert (len(T) == 1)

    im = decals.get_image_object(T[0])
    tim = im.get_tractor_image(slc=zoomslice, pixPsf=True, splinesky=True)
    print('Got tim:', tim)

    if opt.catfn in ['DR1', 'DR2']:
        if opt.catalog_path is None:
            opt.catalog_path = opt.catfn.lower()

        margin = 20
        TT = []
        chipwcs = tim.subwcs
        bricks = bricks_touching_wcs(chipwcs, decals=decals)
        for b in bricks:
            # there is some overlap with this brick... read the catalog.
            fn = os.path.join(opt.catalog_path, 'tractor', b.brickname[:3],
                              'tractor-%s.fits' % b.brickname)
            if not os.path.exists(fn):
                print('WARNING: catalog', fn, 'does not exist.  Skipping!')
                continue
            print('Reading', fn)
            T = fits_table(fn)
            ok, xx, yy = chipwcs.radec2pixelxy(T.ra, T.dec)
            W, H = chipwcs.get_width(), chipwcs.get_height()
            I = np.flatnonzero((xx >= -margin) * (xx <= (W + margin)) *
                               (yy >= -margin) * (yy <= (H + margin)))
            T.cut(I)
            print('Cut to', len(T), 'sources within image + margin')
            # print('Brick_primary:', np.unique(T.brick_primary))
            T.cut(T.brick_primary)
            print('Cut to', len(T), 'on brick_primary')
            T.cut((T.out_of_bounds == False) * (T.left_blob == False))
            print('Cut to', len(T), 'on out_of_bounds and left_blob')
            TT.append(T)
        T = merge_tables(TT)
        T._header = TT[0]._header
        del TT

        # Fix up various failure modes:
        # FixedCompositeGalaxy(pos=RaDecPos[240.51147402832561, 10.385488075518923], brightness=NanoMaggies: g=(flux -2.87), r=(flux -5.26), z=(flux -7.65), fracDev=FracDev(0.60177207), shapeExp=re=3.78351e-44, e1=9.30367e-13, e2=1.24392e-16, shapeDev=re=inf, e1=-0, e2=-0)
        # -> convert to EXP
        I = np.flatnonzero(
            np.array([((t.type == 'COMP') and (not np.isfinite(t.shapedev_r)))
                      for t in T]))
        if len(I):
            print('Converting', len(I), 'bogus COMP galaxies to EXP')
            for i in I:
                T.type[i] = 'EXP'

        # Same thing with the exp component.
        # -> convert to DEV
        I = np.flatnonzero(
            np.array([((t.type == 'COMP') and (not np.isfinite(t.shapeexp_r)))
                      for t in T]))
        if len(I):
            print('Converting', len(I), 'bogus COMP galaxies to DEV')
            for i in I:
                T.type[i] = 'DEV'

        if opt.write_cat:
            T.writeto(opt.write_cat)
            print('Wrote catalog to', opt.write_cat)

    else:
        T = fits_table(opt.catfn)

    T.shapeexp = np.vstack((T.shapeexp_r, T.shapeexp_e1, T.shapeexp_e2)).T
    T.shapedev = np.vstack((T.shapedev_r, T.shapedev_e1, T.shapedev_e2)).T

    cat = read_fits_catalog(T, ellipseClass=tractor.ellipses.EllipseE)
    # print('Got cat:', cat)

    print('Forced photom...')
    opti = None
    if opt.ceres:
        from tractor.ceres_optimizer import CeresOptimizer
        B = 8
        opti = CeresOptimizer(BW=B, BH=B)

    tr = Tractor([tim], cat, optimizer=opti)
    tr.freezeParam('images')
    for src in cat:
        src.freezeAllBut('brightness')
        src.getBrightness().freezeAllBut(tim.band)

    F = fits_table()
    F.brickid = T.brickid
    F.brickname = T.brickname
    F.objid = T.objid

    F.filter = np.array([tim.band] * len(T))
    F.mjd = np.array([tim.primhdr['MJD-OBS']] * len(T))
    F.exptime = np.array([tim.primhdr['EXPTIME']] * len(T))

    ok, x, y = tim.sip_wcs.radec2pixelxy(T.ra, T.dec)
    F.x = (x - 1).astype(np.float32)
    F.y = (y - 1).astype(np.float32)

    if opt.apphot:
        import photutils

        img = tim.getImage()
        ie = tim.getInvError()
        with np.errstate(divide='ignore'):
            imsigma = 1. / ie
        imsigma[ie == 0] = 0.

        apimg = []
        apimgerr = []

        # Aperture photometry locations
        xxyy = np.vstack(
            [tim.wcs.positionToPixel(src.getPosition()) for src in cat]).T
        apxy = xxyy - 1.

        apertures = apertures_arcsec / tim.wcs.pixel_scale()
        print('Apertures:', apertures, 'pixels')

        for rad in apertures:
            aper = photutils.CircularAperture(apxy, rad)
            p = photutils.aperture_photometry(img, aper, error=imsigma)
            apimg.append(p.field('aperture_sum'))
            apimgerr.append(p.field('aperture_sum_err'))
        ap = np.vstack(apimg).T
        ap[np.logical_not(np.isfinite(ap))] = 0.
        F.apflux = ap
        ap = 1. / (np.vstack(apimgerr).T)**2
        ap[np.logical_not(np.isfinite(ap))] = 0.
        F.apflux_ivar = ap

    if opt.forced:
        kwa = {}
        if opt.plots is None:
            kwa.update(wantims=False)

        R = tr.optimize_forced_photometry(variance=True,
                                          fitstats=True,
                                          shared_params=False,
                                          **kwa)

        if opt.plots:
            (data, mod, ie, chi, roi) = R.ims1[0]

            ima = tim.ima
            imchi = dict(interpolation='nearest',
                         origin='lower',
                         vmin=-5,
                         vmax=5)
            plt.clf()
            plt.imshow(data, **ima)
            plt.title('Data: %s' % tim.name)
            ps.savefig()

            plt.clf()
            plt.imshow(mod, **ima)
            plt.title('Model: %s' % tim.name)
            ps.savefig()

            plt.clf()
            plt.imshow(chi, **imchi)
            plt.title('Chi: %s' % tim.name)
            ps.savefig()

        F.flux = np.array([
            src.getBrightness().getFlux(tim.band) for src in cat
        ]).astype(np.float32)
        F.flux_ivar = R.IV.astype(np.float32)

        F.fracflux = R.fitstats.profracflux.astype(np.float32)
        F.rchi2 = R.fitstats.prochi2.astype(np.float32)

    program_name = sys.argv[0]
    version_hdr = get_version_header(program_name, decals.decals_dir)
    # HACK -- print only two directory names + filename of CPFILE.
    fname = os.path.basename(im.imgfn)
    d = os.path.dirname(im.imgfn)
    d1 = os.path.basename(d)
    d = os.path.dirname(d)
    d2 = os.path.basename(d)
    fname = os.path.join(d2, d1, fname)
    print('Trimmed filename to', fname)
    #version_hdr.add_record(dict(name='CPFILE', value=im.imgfn, comment='DECam comm.pipeline file'))
    version_hdr.add_record(
        dict(name='CPFILE', value=fname, comment='DECam comm.pipeline file'))
    version_hdr.add_record(
        dict(name='CPHDU', value=im.hdu, comment='DECam comm.pipeline ext'))
    version_hdr.add_record(
        dict(name='CAMERA', value='DECam', comment='Dark Energy Camera'))
    version_hdr.add_record(
        dict(name='EXPNUM', value=im.expnum, comment='DECam exposure num'))
    version_hdr.add_record(
        dict(name='CCDNAME', value=im.ccdname, comment='DECam CCD name'))
    version_hdr.add_record(
        dict(name='FILTER', value=tim.band, comment='Bandpass of this image'))
    version_hdr.add_record(
        dict(name='EXPOSURE',
             value='decam-%s-%s' % (im.expnum, im.ccdname),
             comment='Name of this image'))

    keys = [
        'TELESCOP', 'OBSERVAT', 'OBS-LAT', 'OBS-LONG', 'OBS-ELEV', 'INSTRUME'
    ]
    for key in keys:
        if key in tim.primhdr:
            version_hdr.add_record(dict(name=key, value=tim.primhdr[key]))

    hdr = fitsio.FITSHDR()

    units = {
        'mjd': 'sec',
        'exptime': 'sec',
        'flux': 'nanomaggy',
        'flux_ivar': '1/nanomaggy^2'
    }
    columns = F.get_columns()
    for i, col in enumerate(columns):
        if col in units:
            hdr.add_record(dict(name='TUNIT%i' % (i + 1), value=units[col]))

    outdir = os.path.dirname(opt.outfn)
    if len(outdir):
        trymakedirs(outdir)
    fitsio.write(opt.outfn, None, header=version_hdr, clobber=True)
    F.writeto(opt.outfn, header=hdr, append=True)
    print('Wrote', opt.outfn)

    print('Finished forced phot:', Time() - t0)
    return 0
Example #15
0
def merge_psfex(survey, expnum, C, psfoutfn, opt):
    psfex = []
    psfhdrvals = []
    imobjs = []
    Cgood = []
    for ccd in C:
        im = survey.get_image_object(ccd)
        fn = im.psffn
        if not os.path.exists(fn):
            print('File not found:', fn)
            if opt.all_found:
                return
            continue
        imobjs.append(im)
        Cgood.append(ccd)

    for ccd, im in zip(Cgood, imobjs):
        fn = im.psffn
        print('Reading', fn)
        T = fits_table(fn)
        hdr = fitsio.read_header(fn, ext=1)

        keys = [
            'LOADED',
            'ACCEPTED',
            'CHI2',
            'POLNAXIS',
            'POLNGRP',
            'PSF_FWHM',
            'PSF_SAMP',
            'PSFNAXIS',
            'PSFAXIS1',
            'PSFAXIS2',
            'PSFAXIS3',
        ]

        if hdr['POLNAXIS'] == 0:
            # No polynomials.  Fake it.
            T.polgrp1 = np.array([0])
            T.polgrp2 = np.array([0])
            T.polname1 = np.array(['fake'])
            T.polname2 = np.array(['fake'])
            T.polzero1 = np.array([0])
            T.polzero2 = np.array([0])
            T.polscal1 = np.array([1])
            T.polscal2 = np.array([1])
            T.poldeg1 = np.array([0])
        else:
            keys.extend([
                'POLGRP1', 'POLNAME1', 'POLZERO1', 'POLSCAL1', 'POLGRP2',
                'POLNAME2', 'POLZERO2', 'POLSCAL2', 'POLDEG1'
            ])

        for k in keys:
            try:
                v = hdr[k]
            except:
                print('Did not find key', k, 'in', fn)
                sys.exit(-1)
            T.set(k.lower(), np.array([hdr[k]]))
        psfex.append(T)
        #print(fn)
        #T.about()

        hdr = fitsio.read_header(fn)
        psfhdrvals.append([hdr.get(k, '') for k in ['LEGPIPEV', 'PLVER']] +
                          [expnum, ccd.ccdname])

    if len(psfex) == 0:
        return
    padded = pad_arrays([p.psf_mask[0] for p in psfex])
    cols = psfex[0].columns()
    cols.remove('psf_mask')
    T = merge_tables(psfex, columns=cols)
    T.psf_mask = np.concatenate([[p] for p in padded])
    T.legpipev = np.array([h[0] for h in psfhdrvals])
    T.plver = np.array([h[1] for h in psfhdrvals])
    T.expnum = np.array([h[2] for h in psfhdrvals])
    T.ccdname = np.array([h[3] for h in psfhdrvals])
    fn = psfoutfn
    trymakedirs(fn, dir=True)
    T.writeto(fn)
    print('Wrote', fn)
Example #16
0
def main():
    survey = LegacySurveyData()
    ccds = survey.get_ccds()
    print(len(ccds), 'CCDs')

    expnums = np.unique(ccds.expnum)
    print(len(expnums), 'unique exposures')

    for expnum in expnums:

        expnumstr = '%08i' % expnum
        skyoutfn = os.path.join('splinesky', expnumstr[:5], 'decam-%s.fits' % expnumstr)
        psfoutfn = os.path.join('psfex', expnumstr[:5], 'decam-%s.fits' % expnumstr)

        if os.path.exists(skyoutfn) and os.path.exists(psfoutfn):
            print('Exposure', expnum, 'is done already')
            continue

        C = ccds[ccds.expnum == expnum]
        print(len(C), 'CCDs in expnum', expnum)

        psfex = []
        psfhdrvals = []

        splinesky = []
        skyhdrvals = []

        for ccd in C:
            im = survey.get_image_object(ccd)

            fn = im.splineskyfn
            if os.path.exists(fn):
                T = fits_table(fn)
                splinesky.append(T)
                # print(fn)
                # T.about()
                hdr = fitsio.read_header(fn)
                skyhdrvals.append([hdr[k] for k in [
                            'SKY', 'LEGPIPEV', 'PLVER']] + [expnum, ccd.ccdname])
            else:
                print('File not found:', fn)

            fn = im.psffn
            if os.path.exists(fn):
                T = fits_table(fn)
                hdr = fitsio.read_header(fn, ext=1)

                keys = ['LOADED', 'ACCEPTED', 'CHI2', 'POLNAXIS', 
                        'POLNGRP', 'PSF_FWHM', 'PSF_SAMP', 'PSFNAXIS',
                        'PSFAXIS1', 'PSFAXIS2', 'PSFAXIS3',]

                if hdr['POLNAXIS'] == 0:
                    # No polynomials.  Fake it.
                    T.polgrp1 = np.array([0])
                    T.polgrp2 = np.array([0])
                    T.polname1 = np.array(['fake'])
                    T.polname2 = np.array(['fake'])
                    T.polzero1 = np.array([0])
                    T.polzero2 = np.array([0])
                    T.polscal1 = np.array([1])
                    T.polscal2 = np.array([1])
                    T.poldeg1 = np.array([0])
                    T.poldeg2 = np.array([0])
                else:
                    keys.extend([
                            'POLGRP1', 'POLNAME1', 'POLZERO1', 'POLSCAL1',
                            'POLGRP2', 'POLNAME2', 'POLZERO2', 'POLSCAL2',
                            'POLDEG1'])

                for k in keys:
                    T.set(k.lower(), np.array([hdr[k]]))
                psfex.append(T)
                #print(fn)
                #T.about()
    
                hdr = fitsio.read_header(fn)
                psfhdrvals.append([hdr.get(k,'') for k in [
                    'LEGPIPEV', 'PLVER']] + [expnum, ccd.ccdname])
            else:
                print('File not found:', fn)

        if len(psfex):
            padded = pad_arrays([p.psf_mask[0] for p in psfex])
            cols = psfex[0].columns()
            cols.remove('psf_mask')
            T = merge_tables(psfex, columns=cols)
            T.psf_mask = np.concatenate([[p] for p in padded])
            T.legpipev = np.array([h[0] for h in psfhdrvals])
            T.plver    = np.array([h[1] for h in psfhdrvals])
            T.expnum   = np.array([h[2] for h in psfhdrvals])
            T.ccdname  = np.array([h[3] for h in psfhdrvals])
            fn = psfoutfn
            trymakedirs(fn, dir=True)
            T.writeto(fn)
            print('Wrote', fn)

        if len(splinesky):
            T = fits_table()
            T.gridw = np.array([t.gridvals[0].shape[1] for t in splinesky])
            T.gridh = np.array([t.gridvals[0].shape[0] for t in splinesky])

            padded = pad_arrays([t.gridvals[0] for t in splinesky])
            T.gridvals = np.concatenate([[p] for p in padded])
            padded = pad_arrays([t.xgrid[0] for t in splinesky])
            T.xgrid = np.concatenate([[p] for p in padded])
            padded = pad_arrays([t.xgrid[0] for t in splinesky])
            T.ygrid = np.concatenate([[p] for p in padded])
    
            cols = splinesky[0].columns()
            print('Columns:', cols)
            for c in ['gridvals', 'xgrid', 'ygrid']:
                cols.remove(c)

            T.add_columns_from(merge_tables(splinesky, columns=cols))
            T.skyclass = np.array([h[0] for h in skyhdrvals])
            T.legpipev = np.array([h[1] for h in skyhdrvals])
            T.plver    = np.array([h[2] for h in skyhdrvals])
            T.expnum   = np.array([h[3] for h in skyhdrvals])
            T.ccdname  = np.array([h[4] for h in skyhdrvals])
            fn = skyoutfn
            trymakedirs(fn, dir=True)
            T.writeto(fn)
            print('Wrote', fn)
Example #17
0
    def run_calibs(
        self,
        pvastrom=True,
        psfex=True,
        sky=True,
        se=False,
        funpack=False,
        fcopy=False,
        use_mask=True,
        force=False,
        just_check=False,
        git_version=None,
        splinesky=False,
    ):

        """
        Run calibration pre-processing steps.

        Parameters
        ----------
        just_check: boolean
            If True, returns True if calibs need to be run.
        """
        from .common import create_temp, get_version_header, get_git_version

        # for fn in [self.pvwcsfn, self.sefn, self.psffn, self.skyfn, self.splineskyfn]:
        #    print('exists?', os.path.exists(fn), fn)

        if psfex and os.path.exists(self.psffn) and (not force):
            # Sometimes SourceExtractor gets interrupted or something and
            # writes out 0 detections.  Then PsfEx fails but in a way that
            # an output file is still written.  Try to detect & fix this
            # case.
            # Check the PsfEx output file for POLNAME1
            hdr = fitsio.read_header(self.psffn, ext=1)
            if hdr.get("POLNAME1", None) is None:
                print("Did not find POLNAME1 in PsfEx header", self.psffn, "-- deleting")
                os.unlink(self.psffn)
            else:
                psfex = False
        if psfex:
            se = True

        if se and os.path.exists(self.sefn) and (not force):
            # Check SourceExtractor catalog for size = 0
            fn = self.sefn
            T = fits_table(fn, hdu=2)
            print("Read", len(T), "sources from SE catalog", fn)
            if T is None or len(T) == 0:
                print("SourceExtractor catalog", fn, "has no sources -- deleting")
                try:
                    os.unlink(fn)
                except:
                    pass
            if os.path.exists(self.sefn):
                se = False
        if se:
            funpack = True

        if pvastrom and os.path.exists(self.pvwcsfn) and (not force):
            fn = self.pvwcsfn
            if os.path.exists(fn):
                try:
                    wcs = Sip(fn)
                except:
                    print("Failed to read PV-SIP file", fn, "-- deleting")
                    os.unlink(fn)
            if os.path.exists(fn):
                pvastrom = False

        if (
            sky
            and (not force)
            and ((os.path.exists(self.skyfn) and not splinesky) or (os.path.exists(self.splineskyfn) and splinesky))
        ):
            fn = self.skyfn
            if splinesky:
                fn = self.splineskyfn

            if os.path.exists(fn):
                try:
                    hdr = fitsio.read_header(fn)
                except:
                    print("Failed to read sky file", fn, "-- deleting")
                    os.unlink(fn)
            if os.path.exists(fn):
                print("File", fn, "exists -- skipping")
                sky = False

        if just_check:
            return se or psfex or sky or pvastrom

        tmpimgfn = None
        tmpmaskfn = None

        # Unpacked image file
        funimgfn = self.imgfn
        funmaskfn = self.dqfn

        if funpack:
            # For FITS files that are not actually fpack'ed, funpack -E
            # fails.  Check whether actually fpacked.
            hdr = fitsio.read_header(self.imgfn, ext=self.hdu)
            if not ((hdr["XTENSION"] == "BINTABLE") and hdr.get("ZIMAGE", False)):
                print("Image", self.imgfn, "HDU", self.hdu, "is not actually fpacked; not funpacking, just imcopying.")
                fcopy = True

            tmpimgfn = create_temp(suffix=".fits")
            tmpmaskfn = create_temp(suffix=".fits")

            if fcopy:
                cmd = 'imcopy %s"+%i" %s' % (self.imgfn, self.hdu, tmpimgfn)
            else:
                cmd = "funpack -E %i -O %s %s" % (self.hdu, tmpimgfn, self.imgfn)
            print(cmd)
            if os.system(cmd):
                raise RuntimeError("Command failed: " + cmd)
            funimgfn = tmpimgfn

            if use_mask:
                if fcopy:
                    cmd = 'imcopy %s"+%i" %s' % (self.dqfn, self.hdu, tmpmaskfn)
                else:
                    cmd = "funpack -E %i -O %s %s" % (self.hdu, tmpmaskfn, self.dqfn)
                print(cmd)
                if os.system(cmd):
                    # raise RuntimeError('Command failed: ' + cmd)
                    print("Command failed: " + cmd)
                    M, hdr = fitsio.read(self.dqfn, ext=self.hdu, header=True)
                    print("Read", M.dtype, M.shape)
                    fitsio.write(tmpmaskfn, M, header=hdr, clobber=True)
                    print("Wrote", tmpmaskfn, "with fitsio")

                funmaskfn = tmpmaskfn

        if se:
            # grab header values...
            primhdr = self.read_image_primary_header()
            magzp = primhdr["MAGZERO"]
            seeing = self.pixscale * self.fwhm
            # print('FWHM', self.fwhm, 'pix')
            # print('pixscale', self.pixscale, 'arcsec/pix')
            # print('Seeing', seeing, 'arcsec')

        if se:
            maskstr = ""
            if use_mask:
                maskstr = "-FLAG_IMAGE " + funmaskfn
            sedir = self.decals.get_se_dir()

            trymakedirs(self.sefn, dir=True)

            cmd = " ".join(
                [
                    "sex",
                    "-c",
                    os.path.join(sedir, "DECaLS.se"),
                    maskstr,
                    "-SEEING_FWHM %f" % seeing,
                    "-PARAMETERS_NAME",
                    os.path.join(sedir, "DECaLS.param"),
                    "-FILTER_NAME",
                    os.path.join(sedir, "gauss_5.0_9x9.conv"),
                    "-STARNNW_NAME",
                    os.path.join(sedir, "default.nnw"),
                    "-PIXEL_SCALE 0",
                    # SE has a *bizarre* notion of "sigma"
                    "-DETECT_THRESH 1.0",
                    "-ANALYSIS_THRESH 1.0",
                    "-MAG_ZEROPOINT %f" % magzp,
                    "-CATALOG_NAME",
                    self.sefn,
                    funimgfn,
                ]
            )
            print(cmd)
            if os.system(cmd):
                raise RuntimeError("Command failed: " + cmd)

        if pvastrom:
            # DECam images appear to have PV coefficients up to PVx_10,
            # which are up to cubic terms in xi,eta,r.  Overshoot what we
            # need in SIP terms.
            tmpwcsfn = create_temp(suffix=".wcs")
            cmd = "wcs-pv2sip -S -o 6 -e %i %s %s" % (self.hdu, self.imgfn, tmpwcsfn)
            print(cmd)
            if os.system(cmd):
                raise RuntimeError("Command failed: " + cmd)
            # Read the resulting WCS header and add version info cards to it.
            version_hdr = get_version_header(None, self.decals.get_decals_dir(), git_version=git_version)
            primhdr = self.read_image_primary_header()
            plver = primhdr.get("PLVER", "").strip()
            version_hdr.add_record(dict(name="PLVER", value=plver, comment="CP ver of image file"))
            wcshdr = fitsio.read_header(tmpwcsfn)
            os.unlink(tmpwcsfn)
            for r in wcshdr.records():
                version_hdr.add_record(r)

            trymakedirs(self.pvwcsfn, dir=True)

            fitsio.write(self.pvwcsfn, None, header=version_hdr, clobber=True)
            print("Wrote", self.pvwcsfn)

        if psfex:
            sedir = self.decals.get_se_dir()

            trymakedirs(self.psffn, dir=True)

            # If we wrote *.psf instead of *.fits in a previous run...
            oldfn = self.psffn.replace(".fits", ".psf")
            if os.path.exists(oldfn):
                print("Moving", oldfn, "to", self.psffn)
                os.rename(oldfn, self.psffn)
            else:
                primhdr = self.read_image_primary_header()
                plver = primhdr.get("PLVER", "")
                verstr = get_git_version()
                cmds = [
                    "psfex -c %s -PSF_DIR %s %s"
                    % (os.path.join(sedir, "DECaLS.psfex"), os.path.dirname(self.psffn), self.sefn),
                    'modhead %s LEGPIPEV %s "legacypipe git version"' % (self.psffn, verstr),
                    'modhead %s PLVER %s "CP ver of image file"' % (self.psffn, plver),
                ]
                for cmd in cmds:
                    print(cmd)
                    rtn = os.system(cmd)
                    if rtn:
                        raise RuntimeError("Command failed: " + cmd + ": return value: %i" % rtn)

        if sky:
            # print('Fitting sky for', self)

            hdr = get_version_header(None, self.decals.get_decals_dir(), git_version=git_version)
            primhdr = self.read_image_primary_header()
            plver = primhdr.get("PLVER", "")
            hdr.delete("PROCTYPE")
            hdr.add_record(dict(name="PROCTYPE", value="ccd", comment="NOAO processing type"))
            hdr.add_record(dict(name="PRODTYPE", value="skymodel", comment="NOAO product type"))
            hdr.add_record(dict(name="PLVER", value=plver, comment="CP ver of image file"))

            slc = self.get_good_image_slice(None)
            # print('Good image slice is', slc)

            img = self.read_image(slice=slc)
            wt = self.read_invvar(slice=slc)

            if splinesky:
                from tractor.splinesky import SplineSky
                from scipy.ndimage.morphology import binary_dilation

                # Start by subtracting the overall median
                med = np.median(img[wt > 0])
                # Compute initial model...
                skyobj = SplineSky.BlantonMethod(img - med, wt > 0, 512)
                skymod = np.zeros_like(img)
                skyobj.addTo(skymod)
                # Now mask bright objects in (image - initial sky model)
                sig1 = 1.0 / np.sqrt(np.median(wt[wt > 0]))
                masked = (img - med - skymod) > (5.0 * sig1)
                masked = binary_dilation(masked, iterations=3)
                masked[wt == 0] = True
                # Now find the final sky model using that more extensive mask
                skyobj = SplineSky.BlantonMethod(img - med, np.logical_not(masked), 512)
                # add the median back in
                skyobj.offset(med)

                if slc is not None:
                    sy, sx = slc
                    y0 = sy.start
                    x0 = sx.start
                    skyobj.shift(-x0, -y0)

                trymakedirs(self.splineskyfn, dir=True)
                skyobj.write_fits(self.splineskyfn, primhdr=hdr)
                print("Wrote sky model", self.splineskyfn)

            else:
                img = img[wt > 0]
                try:
                    skyval = estimate_mode(img, raiseOnWarn=True)
                    skymeth = "mode"
                except:
                    skyval = np.median(img)
                    skymeth = "median"
                tsky = ConstantSky(skyval)

                hdr.add_record(dict(name="SKYMETH", value=skymeth, comment="estimate_mode, or fallback to median?"))
                trymakedirs(self.skyfn, dir=True)
                tsky.write_fits(self.skyfn, hdr=hdr)
                print("Wrote sky model", self.skyfn)

        if tmpimgfn is not None:
            os.unlink(tmpimgfn)
        if tmpmaskfn is not None:
            os.unlink(tmpmaskfn)
Example #18
0
        for band in bands:
            flux   = [ [] for i in range(len(B)) ]
            fluxiv = [ [] for i in range(len(B)) ]
            mjd    = [ [] for i in range(len(B)) ]

            J = np.flatnonzero((T.brickname == brick) * (T.filter == band))
            print(len(J), 'in brick', brick, 'band', band)
            if len(J) == 0:
                continue
            for j in J:
                i = tmap[T.srcid[j]]
                flux[i].append(T.flux[j])
                fluxiv[i].append(T.flux_ivar[j])
                mjd[i].append(T.mjd[j])

            nmax = max([len(lst) for lst in flux])
            print('Band:', band, 'Nmax:', nmax)
            if nmax == 0:
                continue
            for flist,col,dt in [(flux,   'forced_flux_%s'      % band, np.float32),
                                 (fluxiv, 'forced_flux_ivar_%s' % band, np.float32),
                                 (mjd,    'forced_mjd_%s'       % band, np.float64),]:
                arr = np.zeros((len(B), nmax), dt)
                for i,f in enumerate(flist):
                    arr[i,:len(f)] = f
                B.set(col, arr)

        outfn = os.path.join('fsweep', brick[:3], 'tractor-%s.fits' % brick)
        trymakedirs(outfn, dir=True)
        B.writeto(outfn)
Example #19
0
    def run_calibs(self, psfex=True, sky=True, se=False,
                   funpack=False, fcopy=False, use_mask=True,
                   force=False, just_check=False, git_version=None,
                   splinesky=False):

        '''
        Run calibration pre-processing steps.

        Parameters
        ----------
        just_check: boolean
            If True, returns True if calibs need to be run.
        '''
        from .survey import (create_temp, get_version_header,
                             get_git_version)
        
        if psfex and os.path.exists(self.psffn) and (not force):
            if self.check_psf(self.psffn):
                psfex = False
        if psfex:
            se = True
            
        if se and os.path.exists(self.sefn) and (not force):
            if self.check_se_cat(self.sefn):
                se = False
        if se:
            funpack = True

        if sky and (not force) and (
            (os.path.exists(self.skyfn) and not splinesky) or
            (os.path.exists(self.splineskyfn) and splinesky)):
            fn = self.skyfn
            if splinesky:
                fn = self.splineskyfn

            if os.path.exists(fn):
                try:
                    hdr = fitsio.read_header(fn)
                except:
                    print('Failed to read sky file', fn, '-- deleting')
                    os.unlink(fn)
            if os.path.exists(fn):
                print('File', fn, 'exists -- skipping')
                sky = False

        if just_check:
            return (se or psfex or sky)

        todelete = []
        if funpack:
            # The image & mask files to process (funpacked if necessary)
            imgfn,maskfn = self.funpack_files(self.imgfn, self.dqfn, self.hdu, todelete)
        else:
            imgfn,maskfn = self.imgfn,self.dqfn
    
        if se:
            self.run_se('DECaLS', imgfn, maskfn)
        if psfex:
            self.run_psfex('DECaLS')

        if sky:
            #print('Fitting sky for', self)

            hdr = get_version_header(None, self.survey.get_survey_dir(),
                                     git_version=git_version)
            primhdr = self.read_image_primary_header()
            plver = primhdr.get('PLVER', '')
            hdr.delete('PROCTYPE')
            hdr.add_record(dict(name='PROCTYPE', value='ccd',
                                comment='NOAO processing type'))
            hdr.add_record(dict(name='PRODTYPE', value='skymodel',
                                comment='NOAO product type'))
            hdr.add_record(dict(name='PLVER', value=plver,
                                comment='CP ver of image file'))

            slc = self.get_good_image_slice(None)
            #print('Good image slice is', slc)

            img = self.read_image(slice=slc)
            wt = self.read_invvar(slice=slc)

            if splinesky:
                from tractor.splinesky import SplineSky
                from scipy.ndimage.morphology import binary_dilation

                boxsize = DecamImage.splinesky_boxsize
                
                # Start by subtracting the overall median
                med = np.median(img[wt>0])
                # Compute initial model...
                skyobj = SplineSky.BlantonMethod(img - med, wt>0, boxsize)
                skymod = np.zeros_like(img)
                skyobj.addTo(skymod)
                # Now mask bright objects in (image - initial sky model)
                sig1 = 1./np.sqrt(np.median(wt[wt>0]))
                masked = (img - med - skymod) > (5.*sig1)
                masked = binary_dilation(masked, iterations=3)
                masked[wt == 0] = True

                sig1b = 1./np.sqrt(np.median(wt[masked == False]))
                print('Sig1 vs sig1b:', sig1, sig1b)

                # Now find the final sky model using that more extensive mask
                skyobj = SplineSky.BlantonMethod(
                    img - med, np.logical_not(masked), boxsize)
                # add the overall median back in
                skyobj.offset(med)

                if slc is not None:
                    sy,sx = slc
                    y0 = sy.start
                    x0 = sx.start
                    skyobj.shift(-x0, -y0)

                hdr.add_record(dict(name='SIG1', value=sig1,
                                    comment='Median stdev of unmasked pixels'))
                hdr.add_record(dict(name='SIG1B', value=sig1,
                                    comment='Median stdev of unmasked pixels+'))
                    
                trymakedirs(self.splineskyfn, dir=True)
                skyobj.write_fits(self.splineskyfn, primhdr=hdr)
                print('Wrote sky model', self.splineskyfn)
    
            else:
                try:
                    skyval = estimate_mode(img[wt > 0], raiseOnWarn=True)
                    skymeth = 'mode'
                except:
                    skyval = np.median(img[wt > 0])
                    skymeth = 'median'
                tsky = ConstantSky(skyval)

                hdr.add_record(dict(name='SKYMETH', value=skymeth,
                                    comment='estimate_mode, or fallback to median?'))

                from scipy.ndimage.morphology import binary_dilation
                sig1 = 1./np.sqrt(np.median(wt[wt>0]))
                masked = (img - skyval) > (5.*sig1)
                masked = binary_dilation(masked, iterations=3)
                masked[wt == 0] = True
                sig1b = 1./np.sqrt(np.median(wt[masked == False]))
                print('Sig1 vs sig1b:', sig1, sig1b)

                hdr.add_record(dict(name='SIG1', value=sig1,
                                    comment='Median stdev of unmasked pixels'))
                hdr.add_record(dict(name='SIG1B', value=sig1,
                                    comment='Median stdev of unmasked pixels+'))
                
                trymakedirs(self.skyfn, dir=True)
                tsky.write_fits(self.skyfn, hdr=hdr)
                print('Wrote sky model', self.skyfn)

        for fn in todelete:
            os.unlink(fn)
Example #20
0
def render_fake_image(expnum, ccdname, survey_out_dir):
    survey = LegacySurveyData()
    ccds = survey.find_ccds(expnum=expnum,ccdname=ccdname)
    ccd = ccds[0]
    band = ccd.filter
    im = survey.get_image_object(ccd)
    print('Read', im)

    tim = im.get_tractor_image(gaussPsf=True, nanomaggies=False, subsky=False)
    tim.wcs = NullWCS()

    H,W = im.shape

    s0 = 4.

    dsdy = 1./2000.

    x0 = W/2.
    y0 = H/2.

    ny = 21
    nx = 11

    # Lay down a grid of point sources, where the PSF is varying in width as a
    # function of Y position.
    yy = np.linspace(0., H, ny+1)
    xx = np.linspace(0., W, nx+1)
    # center of cells
    yy = yy[:-1] + (yy[1]-yy[0])/2.
    xx = xx[:-1] + (xx[1]-xx[0])/2.

    modimg = np.zeros_like(tim.getImage())

    flux = NanoMaggies.magToNanomaggies(16.)
    star = PointSource(PixPos(0.,0.), NanoMaggies(**{ band: flux }))

    for y in yy:
        for x in xx:
            print('Rendering star at', x, y)
            s = s0 + dsdy * (y - y0)
            psf = NCircularGaussianPSF([s], [1.])
            tim.psf = psf
            star.pos.x = x
            star.pos.y = y
            mod = star.getModelPatch(tim)
            mod.addTo(modimg)

    np.random.seed(42)
    noise = np.random.normal(size=modimg.shape)
    ie = tim.getInvError()
    noise /= ie
    noise[ie == 0] = 0
    modimg += noise

    #
    imagedir = os.path.join(survey_out_dir, 'images', 'decam')
    trymakedirs(imagedir)
    imagefn = os.path.join(imagedir, os.path.basename(ccd.image_filename.strip())).replace(
        '.fits.fz', '.fits')

    primhdr = im.read_image_primary_header()
    hdr = im.read_image_header()

    extname = hdr['EXTNAME']

    import fitsio
    fitsio.write(imagefn, None, header=primhdr, clobber=True)
    fitsio.write(imagefn, modimg, header=hdr, extname=extname, clobber=False)
    print('Wrote', imagefn)

    dq = im.read_dq()
    dqfn = imagefn.replace('_ooi_', '_ood_')
    fitsio.write(dqfn, None, header=primhdr, clobber=True)
    fitsio.write(dqfn, dq, header=hdr, clobber=False)
    print('Wrote', dqfn)

    iv = im.read_invvar()
    wtfn = imagefn.replace('_ooi_', '_oow_')
    fitsio.write(wtfn, None, header=primhdr, clobber=True)
    fitsio.write(wtfn, iv, header=hdr, clobber=False)
    print('Wrote', wtfn)

    # cmd = 'ln -s %s %s' % (im.dqfn, dqfn)
    # print cmd
    # os.system(cmd)
    # 
    # cmd = 'ln -s %s %s' % (im.wtfn, wtfn)
    # print cmd
    # os.system(cmd)

    ccds.image_filename = np.array(['decam/' + os.path.basename(imagefn)])
    ccds.image_hdu[0] = 1
    ccdfn = os.path.join(survey_out_dir, 'survey-ccds.fits')
    ccds.writeto(ccdfn)
    print('Wrote', ccdfn)

    cal = os.path.join(survey_out_dir, 'calib')
    trymakedirs(cal)

    for path in ['survey-bricks.fits', 'calib/se-config']:
        pathnm = os.path.join(survey_out_dir, path)
        if os.path.exists(pathnm):
            continue
        cmd = 'ln -s %s/%s %s' % (survey.get_survey_dir(), path, pathnm)
        print(cmd)
        os.system(cmd)
Example #21
0
def main():
    decals = Decals()
    ccds = decals.get_ccds()
    print(len(ccds), 'CCDs')

    expnums = np.unique(ccds.expnum)
    print(len(expnums), 'unique exposures')

    for expnum in expnums:

        expnumstr = '%08i' % expnum
        skyoutfn = os.path.join('splinesky', expnumstr[:5],
                                'decam-%s.fits' % expnumstr)
        psfoutfn = os.path.join('psfex', expnumstr[:5],
                                'decam-%s.fits' % expnumstr)

        if os.path.exists(skyoutfn) and os.path.exists(psfoutfn):
            print('Exposure', expnum, 'is done already')
            continue

        C = ccds[ccds.expnum == expnum]
        print(len(C), 'CCDs in expnum', expnum)

        psfex = []
        psfhdrvals = []

        splinesky = []
        skyhdrvals = []

        for ccd in C:
            im = decals.get_image_object(ccd)

            fn = im.splineskyfn
            if os.path.exists(fn):
                T = fits_table(fn)
                splinesky.append(T)
                # print(fn)
                # T.about()
                hdr = fitsio.read_header(fn)
                skyhdrvals.append(
                    [hdr[k] for k in ['SKY', 'LEGPIPEV', 'PLVER']] +
                    [expnum, ccd.ccdname])
            else:
                print('File not found:', fn)

            fn = im.psffn
            if os.path.exists(fn):
                T = fits_table(fn)
                hdr = fitsio.read_header(fn, ext=1)

                keys = [
                    'LOADED',
                    'ACCEPTED',
                    'CHI2',
                    'POLNAXIS',
                    'POLNGRP',
                    'PSF_FWHM',
                    'PSF_SAMP',
                    'PSFNAXIS',
                    'PSFAXIS1',
                    'PSFAXIS2',
                    'PSFAXIS3',
                ]

                if hdr['POLNAXIS'] == 0:
                    # No polynomials.  Fake it.
                    T.polgrp1 = np.array([0])
                    T.polgrp2 = np.array([0])
                    T.polname1 = np.array(['fake'])
                    T.polname2 = np.array(['fake'])
                    T.polzero1 = np.array([0])
                    T.polzero2 = np.array([0])
                    T.polscal1 = np.array([1])
                    T.polscal2 = np.array([1])
                    T.poldeg1 = np.array([0])
                    T.poldeg2 = np.array([0])
                else:
                    keys.extend([
                        'POLGRP1', 'POLNAME1', 'POLZERO1', 'POLSCAL1',
                        'POLGRP2', 'POLNAME2', 'POLZERO2', 'POLSCAL2',
                        'POLDEG1'
                    ])

                for k in keys:
                    T.set(k.lower(), np.array([hdr[k]]))
                psfex.append(T)
                #print(fn)
                #T.about()

                hdr = fitsio.read_header(fn)
                psfhdrvals.append(
                    [hdr.get(k, '')
                     for k in ['LEGPIPEV', 'PLVER']] + [expnum, ccd.ccdname])
            else:
                print('File not found:', fn)

        if len(psfex):
            padded = pad_arrays([p.psf_mask[0] for p in psfex])
            cols = psfex[0].columns()
            cols.remove('psf_mask')
            T = merge_tables(psfex, columns=cols)
            T.psf_mask = np.concatenate([[p] for p in padded])
            T.legpipev = np.array([h[0] for h in psfhdrvals])
            T.plver = np.array([h[1] for h in psfhdrvals])
            T.expnum = np.array([h[2] for h in psfhdrvals])
            T.ccdname = np.array([h[3] for h in psfhdrvals])
            fn = psfoutfn
            trymakedirs(fn, dir=True)
            T.writeto(fn)
            print('Wrote', fn)

        if len(splinesky):
            T = fits_table()
            T.gridw = np.array([t.gridvals[0].shape[1] for t in splinesky])
            T.gridh = np.array([t.gridvals[0].shape[0] for t in splinesky])

            padded = pad_arrays([t.gridvals[0] for t in splinesky])
            T.gridvals = np.concatenate([[p] for p in padded])
            padded = pad_arrays([t.xgrid[0] for t in splinesky])
            T.xgrid = np.concatenate([[p] for p in padded])
            padded = pad_arrays([t.xgrid[0] for t in splinesky])
            T.ygrid = np.concatenate([[p] for p in padded])

            cols = splinesky[0].columns()
            print('Columns:', cols)
            for c in ['gridvals', 'xgrid', 'ygrid']:
                cols.remove(c)

            T.add_columns_from(merge_tables(splinesky, columns=cols))
            T.skyclass = np.array([h[0] for h in skyhdrvals])
            T.legpipev = np.array([h[1] for h in skyhdrvals])
            T.plver = np.array([h[2] for h in skyhdrvals])
            T.expnum = np.array([h[3] for h in skyhdrvals])
            T.ccdname = np.array([h[4] for h in skyhdrvals])
            fn = skyoutfn
            trymakedirs(fn, dir=True)
            T.writeto(fn)
            print('Wrote', fn)
Example #22
0
    version_hdr.add_record(dict(name='CAMERA', value='DECam', comment='Dark Energy Camera'))
    version_hdr.add_record(dict(name='EXPNUM', value=im.expnum, comment='DECam exposure num'))
    version_hdr.add_record(dict(name='CCDNAME', value=im.ccdname, comment='DECam CCD name'))
    version_hdr.add_record(dict(name='FILTER', value=tim.band, comment='Bandpass of this image'))
    version_hdr.add_record(dict(name='EXPOSURE', value='decam-%s-%s' % (im.expnum, im.ccdname), comment='Name of this image'))
    
    keys = ['TELESCOP','OBSERVAT','OBS-LAT','OBS-LONG','OBS-ELEV',
            'INSTRUME']
    for key in keys:
        if key in tim.primhdr:
            version_hdr.add_record(dict(name=key, value=tim.primhdr[key]))

    hdr = fitsio.FITSHDR()

    units = {'mjd':'sec', 'exptime':'sec', 'flux':'nanomaggy',
             'flux_ivar':'1/nanomaggy^2'}
    columns = F.get_columns()
    for i,col in enumerate(columns):
        if col in units:
            hdr.add_record(dict(name='TUNIT%i' % (i+1), value=units[col]))

    outdir = os.path.dirname(outfn)
    if len(outdir):
        trymakedirs(outdir)
    fitsio.write(outfn, None, header=version_hdr, clobber=True)
    F.writeto(outfn, header=hdr, append=True)
    print 'Wrote', outfn

    print 'Finished forced phot:', Time()-t0

Example #23
0
    def run_calibs(self,
                   psfex=True,
                   sky=True,
                   funpack=False,
                   git_version=None,
                   force=False,
                   **kwargs):
        from astrometry.util.file import trymakedirs
        from legacypipe.common import (create_temp, get_version_header,
                                       get_git_version)

        print('run_calibs for', self.name, ': sky=', sky, 'kwargs', kwargs)

        se = False
        if psfex and os.path.exists(self.psffn) and (not force):
            psfex = False
        if psfex:
            se = True

        if se and os.path.exists(self.sefn) and (not force):
            se = False
        if se:
            funpack = True

        if sky and (not force) and os.path.exists(self.splineskyfn):
            sky = False

        tmpimgfn = None
        tmpmaskfn = None

        # Unpacked image file
        funimgfn = self.imgfn
        funmaskfn = self.dqfn

        if funpack:
            # For FITS files that are not actually fpack'ed, funpack -E
            # fails.  Check whether actually fpacked.
            hdr = fitsio.read_header(self.imgfn, ext=self.hdu)
            if not ((hdr['XTENSION'] == 'BINTABLE')
                    and hdr.get('ZIMAGE', False)):
                print(
                    'Image', self.imgfn, 'HDU', self.hdu,
                    'is not actually fpacked; not funpacking, just imcopying.')
                fcopy = True

            tmpimgfn = create_temp(suffix='.fits')
            tmpmaskfn = create_temp(suffix='.fits')

            cmd = 'funpack -E %i -O %s %s' % (self.hdu, tmpimgfn, self.imgfn)
            print(cmd)
            if os.system(cmd):
                raise RuntimeError('Command failed: ' + cmd)
            funimgfn = tmpimgfn

            cmd = 'funpack -E %i -O %s %s' % (self.hdu, tmpmaskfn, self.dqfn)
            print(cmd)
            if os.system(cmd):
                print('Command failed: ' + cmd)
                M, hdr = self._read_fits(self.dqfn, ext=self.hdu, header=True)
                print('Read', M.dtype, M.shape)
                fitsio.write(tmpmaskfn, M, header=hdr, clobber=True)
                print('Wrote', tmpmaskfn, 'with fitsio')
            funmaskfn = tmpmaskfn

        if se:
            # grab header values...
            primhdr = self.read_image_primary_header()
            magzp = primhdr['MAGZERO']
            seeing = self.pixscale * self.fwhm

            print('FWHM', self.fwhm, 'pix')
            print('pixscale', self.pixscale, 'arcsec/pix')
            print('Seeing', seeing, 'arcsec')

        if se:
            maskstr = '-FLAG_IMAGE ' + funmaskfn
            sedir = self.decals.get_se_dir()

            trymakedirs(self.sefn, dir=True)

            cmd = ' '.join([
                'sex',
                '-c',
                os.path.join(sedir, 'DECaLS.se'),
                maskstr,
                '-SEEING_FWHM %f' % seeing,
                '-PARAMETERS_NAME',
                os.path.join(sedir, 'DECaLS.param'),
                '-FILTER_NAME',
                os.path.join(sedir, 'gauss_5.0_9x9.conv'),
                '-STARNNW_NAME',
                os.path.join(sedir, 'default.nnw'),
                '-PIXEL_SCALE 0',
                # SE has a *bizarre* notion of "sigma"
                '-DETECT_THRESH 1.0',
                '-ANALYSIS_THRESH 1.0',
                '-MAG_ZEROPOINT %f' % magzp,
                '-CATALOG_NAME',
                self.sefn,
                funimgfn
            ])
            print(cmd)
            if os.system(cmd):
                raise RuntimeError('Command failed: ' + cmd)
        if psfex:
            sedir = self.decals.get_se_dir()
            trymakedirs(self.psffn, dir=True)

            # If we wrote *.psf instead of *.fits in a previous run...
            oldfn = self.psffn.replace('.fits', '.psf')
            if os.path.exists(oldfn):
                print('Moving', oldfn, 'to', self.psffn)
                os.rename(oldfn, self.psffn)
            else:
                primhdr = self.read_image_primary_header()
                plver = primhdr.get('PLVER', '')
                verstr = get_git_version()
                cmds = [
                    'psfex -c %s -PSF_DIR %s %s' %
                    (os.path.join(sedir, 'DECaLS.psfex'),
                     os.path.dirname(self.psffn), self.sefn),
                    'modhead %s LEGPIPEV %s "legacypipe git version"' %
                    (self.psffn, verstr),
                    'modhead %s PLVER %s "CP ver of image file"' %
                    (self.psffn, plver)
                ]
                for cmd in cmds:
                    print(cmd)
                    rtn = os.system(cmd)
                    if rtn:
                        raise RuntimeError('Command failed: ' + cmd +
                                           ': return value: %i' % rtn)

        if sky:
            #print('Fitting sky for', self)

            hdr = get_version_header(None,
                                     self.decals.get_decals_dir(),
                                     git_version=git_version)
            primhdr = self.read_image_primary_header()
            plver = primhdr.get('PLVER', '')
            hdr.delete('PROCTYPE')
            hdr.add_record(
                dict(name='PROCTYPE',
                     value='ccd',
                     comment='NOAO processing type'))
            hdr.add_record(
                dict(name='PRODTYPE',
                     value='skymodel',
                     comment='NOAO product type'))
            hdr.add_record(
                dict(name='PLVER', value=plver,
                     comment='CP ver of image file'))

            slc = self.get_good_image_slice(None)
            #print('Good image slice is', slc)

            img = self.read_image(slice=slc)
            wt = self.read_invvar(slice=slc)

            from tractor.splinesky import SplineSky
            from scipy.ndimage.morphology import binary_dilation

            # Start by subtracting the overall median
            med = np.median(img[wt > 0])
            # Compute initial model...
            skyobj = SplineSky.BlantonMethod(img - med, wt > 0, 512)
            skymod = np.zeros_like(img)
            skyobj.addTo(skymod)
            # Now mask bright objects in (image - initial sky model)
            sig1 = 1. / np.sqrt(np.median(wt[wt > 0]))
            masked = (img - med - skymod) > (5. * sig1)
            masked = binary_dilation(masked, iterations=3)
            masked[wt == 0] = True
            # Now find the final sky model using that more extensive mask
            skyobj = SplineSky.BlantonMethod(img - med, np.logical_not(masked),
                                             512)
            # add the median back in
            skyobj.offset(med)

            if slc is not None:
                sy, sx = slc
                y0 = sy.start
                x0 = sx.start
                skyobj.shift(-x0, -y0)

            trymakedirs(self.splineskyfn, dir=True)
            skyobj.write_fits(self.splineskyfn, primhdr=hdr)
            print('Wrote sky model', self.splineskyfn)

        if tmpimgfn is not None:
            os.unlink(tmpimgfn)
        if tmpmaskfn is not None:
            os.unlink(tmpmaskfn)
Example #24
0
def add_depth_tag(decals, brick, outdir, overwrite=False):
    outfn = os.path.join(outdir, 'tractor', brick[:3],
                         'tractor-%s.fits' % brick)
    if os.path.exists(outfn) and not overwrite:
        print 'Exists:', outfn
        return
    fn = decals.find_file('tractor', brick=brick)
    if not os.path.exists(fn):
        print 'Does not exist:', fn
        return
    T = fits_table(fn, lower=False)
    primhdr = fitsio.read_header(fn)
    hdr = fitsio.read_header(fn, ext=1)
    print 'Read', len(T), 'from', fn
    T.decam_depth = np.zeros((len(T), len(decals.allbands)), np.float32)
    T.decam_galdepth = np.zeros((len(T), len(decals.allbands)), np.float32)
    bands = 'grz'
    ibands = [decals.index_of_band(b) for b in bands]
    ix = np.clip(np.round(T.bx).astype(int), 0, 3599)
    iy = np.clip(np.round(T.by).astype(int), 0, 3599)
    for iband, band in zip(ibands, bands):
        fn = decals.find_file('depth', brick=brick, band=band)
        if os.path.exists(fn):
            print 'Reading', fn
            img = fitsio.read(fn)
            T.decam_depth[:, iband] = img[iy, ix]

        fn = decals.find_file('galdepth', brick=brick, band=band)
        if os.path.exists(fn):
            print 'Reading', fn
            img = fitsio.read(fn)
            T.decam_galdepth[:, iband] = img[iy, ix]
    outfn = os.path.join(outdir, 'tractor', brick[:3],
                         'tractor-%s.fits' % brick)
    trymakedirs(outfn, dir=True)

    for s in [
            'Data product of the DECam Legacy Survey (DECaLS)',
            'Full documentation at http://legacysurvey.org',
    ]:
        primhdr.add_record(dict(name='COMMENT', value=s, comment=s))

    # print 'Header:', hdr
    # T.writeto(outfn, header=hdr, primheader=primhdr)

    # Yuck, all this to get the units right
    tmpfn = outfn + '.tmp'
    fits = fitsio.FITS(tmpfn, 'rw', clobber=True)
    fits.write(None, header=primhdr)
    cols = T.get_columns()
    units = []
    for i in range(1, len(cols) + 1):
        u = hdr.get('TUNIT%i' % i, '')
        units.append(u)
    # decam_depth units
    fluxiv = '1/nanomaggy^2'
    units[-2] = fluxiv
    units[-1] = fluxiv
    fits.write([T.get(c) for c in cols], names=cols, header=hdr, units=units)
    fits.close()
    os.rename(tmpfn, outfn)
    print 'Wrote', outfn
Example #25
0
def merge_splinesky(survey, expnum, C, skyoutfn, opt):
    splinesky = []
    skyhdrvals = []
    imobjs = []
    Cgood = []
    for ccd in C:
        im = survey.get_image_object(ccd)
        fn = im.splineskyfn
        if not os.path.exists(fn):
            print('File not found:', fn)
            if opt.all_found:
                return
            continue
        imobjs.append(im)
        Cgood.append(ccd)

    for ccd, im in zip(Cgood, imobjs):
        fn = im.splineskyfn
        print('Reading', fn)
        T = None
        try:
            T = fits_table(fn)
        except KeyboardInterrupt:
            raise
        except:
            print('Failed to read file', fn, ':', sys.exc_info()[1])
        if T is not None:
            splinesky.append(T)
            # print(fn)
            # T.about()
            hdr = fitsio.read_header(fn)
            skyhdrvals.append(
                [hdr[k] for k in ['SKY', 'LEGPIPEV', 'PLVER', 'SIG1']] +
                [expnum, ccd.ccdname])

    if len(splinesky) == 0:
        return
    T = fits_table()
    T.gridw = np.array([t.gridvals[0].shape[1] for t in splinesky])
    T.gridh = np.array([t.gridvals[0].shape[0] for t in splinesky])

    padded = pad_arrays([t.gridvals[0] for t in splinesky])
    T.gridvals = np.concatenate([[p] for p in padded])
    padded = pad_arrays([t.xgrid[0] for t in splinesky])
    T.xgrid = np.concatenate([[p] for p in padded])
    padded = pad_arrays([t.ygrid[0] for t in splinesky])
    T.ygrid = np.concatenate([[p] for p in padded])

    cols = splinesky[0].columns()
    #print('Columns:', cols)
    for c in ['gridvals', 'xgrid', 'ygrid']:
        cols.remove(c)

    T.add_columns_from(merge_tables(splinesky, columns=cols))
    T.skyclass = np.array([h[0] for h in skyhdrvals])
    T.legpipev = np.array([h[1] for h in skyhdrvals])
    T.plver = np.array([h[2] for h in skyhdrvals])
    T.sig1 = np.array([h[3] for h in skyhdrvals])
    T.expnum = np.array([h[4] for h in skyhdrvals])
    T.ccdname = np.array([h[5] for h in skyhdrvals])
    fn = skyoutfn
    trymakedirs(fn, dir=True)
    T.writeto(fn)
    print('Wrote', fn)
Example #26
0
def main():
    import argparse

    parser = argparse.ArgumentParser(
        description='This script creates small self-contained data sets that '
        'are useful for test cases of the pipeline codes.')

    parser.add_argument('ccds', help='CCDs table describing region to grab')
    parser.add_argument('outdir', help='Output directory name')
    parser.add_argument('brick', help='Brick containing these images')

    parser.add_argument('--wise', help='For WISE outputs, give the path to a WCS file describing the sub-brick region of interest, eg, a coadd image')
    parser.add_argument('--fpack', action='store_true', default=False)
    parser.add_argument('--pad', action='store_true', default=False,
                        help='Keep original image size, but zero out pixels outside ROI')
    
    args = parser.parse_args()

    C = fits_table(args.ccds)
    print(len(C), 'CCDs in', args.ccds)
    C.camera = np.array([c.strip() for c in C.camera])
    
    survey = LegacySurveyData()
    bricks = survey.get_bricks_readonly()
    outbricks = bricks[np.array([n == args.brick for n in bricks.brickname])]
    assert(len(outbricks) == 1)
    
    outsurvey = LegacySurveyData(survey_dir = args.outdir)
    trymakedirs(args.outdir)
    outbricks.writeto(os.path.join(args.outdir, 'survey-bricks.fits.gz'))

    targetwcs = wcs_for_brick(outbricks[0])
    H,W = targetwcs.shape
    
    tycho = fits_table(os.path.join(survey.get_survey_dir(), 'tycho2.fits.gz'))
    print('Read', len(tycho), 'Tycho-2 stars')
    ok,tx,ty = targetwcs.radec2pixelxy(tycho.ra, tycho.dec)
    margin = 100
    tycho.cut(ok * (tx > -margin) * (tx < W+margin) *
              (ty > -margin) * (ty < H+margin))
    print('Cut to', len(tycho), 'Tycho-2 stars within brick')
    del ok,tx,ty
    tycho.writeto(os.path.join(args.outdir, 'tycho2.fits.gz'))
    
    outccds = C.copy()
    for c in ['ccd_x0', 'ccd_x1', 'ccd_y0', 'ccd_y1',
              'brick_x0', 'brick_x1', 'brick_y0', 'brick_y1',
              'plver', 'skyver', 'wcsver', 'psfver', 'skyplver', 'wcsplver',
              'psfplver' ]:
        outccds.delete_column(c)
    outccds.image_hdu[:] = 1

    # Convert to list to avoid truncating filenames
    outccds.image_filename = [fn for fn in outccds.image_filename]
    
    for iccd,ccd in enumerate(C):

        decam = (ccd.camera.strip() == 'decam')
        bok   = (ccd.camera.strip() == '90prime')

        im = survey.get_image_object(ccd)
        print('Got', im)
        slc = (slice(ccd.ccd_y0, ccd.ccd_y1), slice(ccd.ccd_x0, ccd.ccd_x1))
        tim = im.get_tractor_image(slc, pixPsf=True, splinesky=True,
                                   subsky=False, nanomaggies=False)
        print('Tim:', tim.shape)

        psf = tim.getPsf()
        print('PSF:', psf)
        psfex = psf.psfex
        print('PsfEx:', psfex)

        outim = outsurvey.get_image_object(ccd)
        print('Output image:', outim)

        print('Image filename:', outim.imgfn)
        trymakedirs(outim.imgfn, dir=True)

        imgdata = tim.getImage()
        dqdata = tim.dq
        if decam:
            # DECam-specific code remaps the DQ codes... re-read raw
            print('Reading data quality from', im.dqfn, 'hdu', im.hdu)
            dqdata = im._read_fits(im.dqfn, im.hdu, slice=tim.slice)
        ivdata = tim.getInvvar()

        if args.pad:
            # Create zero image of full size, copy in data.
            fullsize = np.zeros((ccd.height, ccd.width), imgdata.dtype)
            fullsize[slc] = imgdata
            imgdata = fullsize

            fullsize = np.zeros((ccd.height, ccd.width), dqdata.dtype)
            fullsize[slc] = dqdata
            dqdata = fullsize

            fullsize = np.zeros((ccd.height, ccd.width), ivdata.dtype)
            fullsize[slc] = ivdata
            ivdata = fullsize
            
        else:
            # Adjust the header WCS by x0,y0
            crpix1 = tim.hdr['CRPIX1']
            crpix2 = tim.hdr['CRPIX2']
            tim.hdr['CRPIX1'] = crpix1 - ccd.ccd_x0
            tim.hdr['CRPIX2'] = crpix2 - ccd.ccd_y0

        # Add image extension to filename
        # fitsio doesn't compress .fz by default, so drop .fz suffix
        
        outim.imgfn = outim.imgfn.replace('.fits', '-%s.fits' % im.ccdname)
        if not args.fpack:
            outim.imgfn = outim.imgfn.replace('.fits.fz', '.fits')

        # if bok:
        #     outim.whtfn  = outim.whtfn .replace('.wht.fits', '-%s.wht.fits' % im.ccdname)
        #     if not args.fpack:
        #         outim.whtfn  = outim.whtfn .replace('.fits.fz', '.fits')
        # else:
        if True:
            outim.wtfn  = outim.wtfn .replace('.fits', '-%s.fits' % im.ccdname)
            if not args.fpack:
                outim.wtfn  = outim.wtfn .replace('.fits.fz', '.fits')

        if outim.dqfn is not None:
            outim.dqfn  = outim.dqfn .replace('.fits', '-%s.fits' % im.ccdname)
            if not args.fpack:
                outim.dqfn  = outim.dqfn .replace('.fits.fz', '.fits')

        if bok:
            outim.psffn = outim.psffn.replace('.psf', '-%s.psf' % im.ccdname)

        ccdfn = outim.imgfn
        ccdfn = ccdfn.replace(outsurvey.get_image_dir(),'')
        if ccdfn.startswith('/'):
            ccdfn = ccdfn[1:]
        outccds.image_filename[iccd] = ccdfn

        print('Changed output filenames to:')
        print(outim.imgfn)
        print(outim.dqfn)

        ofn = outim.imgfn
        if args.fpack:
            f,ofn = tempfile.mkstemp(suffix='.fits')
            os.close(f)
        fitsio.write(ofn, None, header=tim.primhdr, clobber=True)
        fitsio.write(ofn, imgdata, header=tim.hdr, extname=ccd.ccdname)

        if args.fpack:
            cmd = 'fpack -qz 8 -S %s > %s && rm %s' % (ofn, outim.imgfn, ofn)
            print('Running:', cmd)
            rtn = os.system(cmd)
            assert(rtn == 0)

        h,w = tim.shape
        if not args.pad:
            outccds.width[iccd] = w
            outccds.height[iccd] = h
            outccds.crpix1[iccd] = crpix1 - ccd.ccd_x0
            outccds.crpix2[iccd] = crpix2 - ccd.ccd_y0

        wcs = Tan(*[float(x) for x in
                    [ccd.crval1, ccd.crval2, ccd.crpix1, ccd.crpix2,
                     ccd.cd1_1, ccd.cd1_2, ccd.cd2_1, ccd.cd2_2, ccd.width, ccd.height]])

        if args.pad:
            subwcs = wcs
        else:
            subwcs = wcs.get_subimage(ccd.ccd_x0, ccd.ccd_y0, w, h)
            outccds.ra[iccd],outccds.dec[iccd] = subwcs.radec_center()

        #if not bok:
        if True:
            print('Weight filename:', outim.wtfn)
            wfn = outim.wtfn
        # else:
        #     print('Weight filename:', outim.whtfn)
        #     wfn = outim.whtfn

        trymakedirs(wfn, dir=True)

        ofn = wfn
        if args.fpack:
            f,ofn = tempfile.mkstemp(suffix='.fits')
            os.close(f)

        fitsio.write(ofn, None, header=tim.primhdr, clobber=True)
        fitsio.write(ofn, ivdata, header=tim.hdr, extname=ccd.ccdname)

        if args.fpack:
            cmd = 'fpack -qz 8 -S %s > %s && rm %s' % (ofn, wfn, ofn)
            print('Running:', cmd)
            rtn = os.system(cmd)
            assert(rtn == 0)

        if outim.dqfn is not None:
            print('DQ filename', outim.dqfn)
            trymakedirs(outim.dqfn, dir=True)

            ofn = outim.dqfn
            if args.fpack:
                f,ofn = tempfile.mkstemp(suffix='.fits')
                os.close(f)

            fitsio.write(ofn, None, header=tim.primhdr, clobber=True)
            fitsio.write(ofn, dqdata, header=tim.hdr, extname=ccd.ccdname)

            if args.fpack:
                cmd = 'fpack -g -q 0 -S %s > %s && rm %s' % (ofn, outim.dqfn, ofn)
                print('Running:', cmd)
                rtn = os.system(cmd)
                assert(rtn == 0)

        print('PSF filename:', outim.psffn)
        trymakedirs(outim.psffn, dir=True)
        psfex.writeto(outim.psffn)

        if not bok:
            print('Sky filename:', outim.splineskyfn)
            sky = tim.getSky()
            print('Sky:', sky)
            trymakedirs(outim.splineskyfn, dir=True)
            sky.write_fits(outim.splineskyfn)

    outccds.writeto(os.path.join(args.outdir, 'survey-ccds-1.fits.gz'))

    # WISE
    if args.wise is not None:
        from wise.forcedphot import unwise_tiles_touching_wcs
        from wise.unwise import (unwise_tile_wcs, unwise_tiles_touching_wcs,
                                 get_unwise_tractor_image, get_unwise_tile_dir)
        # Read WCS...
        print('Reading TAN wcs header from', args.wise)
        targetwcs = Tan(args.wise)
        tiles = unwise_tiles_touching_wcs(targetwcs)
        print('Cut to', len(tiles), 'unWISE tiles')
        H,W = targetwcs.shape
        r,d = targetwcs.pixelxy2radec(np.array([1,   W,   W/2, W/2]),
                                      np.array([H/2, H/2, 1,   H  ]))
        roiradec = [r[0], r[1], d[2], d[3]]

        unwise_dir = os.environ['UNWISE_COADDS_DIR']
        wise_out = os.path.join(args.outdir, 'images', 'unwise')
        print('Will write WISE outputs to', wise_out)

        unwise_tr_dir = os.environ['UNWISE_COADDS_TIMERESOLVED_DIR']
        wise_tr_out = os.path.join(args.outdir, 'images', 'unwise-tr')
        print('Will write WISE time-resolved outputs to', wise_tr_out)

        W = fits_table(os.path.join(unwise_tr_dir, 'time_resolved_neo1-atlas.fits'))
        print('Read', len(W), 'time-resolved WISE coadd tiles')
        W.cut(np.array([t in tiles.coadd_id for t in W.coadd_id]))
        print('Cut to', len(W), 'time-resolved vs', len(tiles), 'full-depth')

        # Write the time-resolved index subset.
        W.writeto(os.path.join(wise_tr_out, 'time_resolved_neo1-atlas.fits'))

        # this ought to be enough for anyone =)
        Nepochs = 5

        wisedata = []

        # full depth
        for band in [1,2,3,4]:
            wisedata.append((unwise_dir, wise_out, tiles.coadd_id, band))

        # time-resolved
        for band in [1,2]:
            # W1 is bit 0 (value 0x1), W2 is bit 1 (value 0x2)
            bitmask = (1 << (band-1))
            for e in range(Nepochs):
                # Which tiles have images for this epoch?
                I = np.flatnonzero(W.epoch_bitmask[:,e] & bitmask)
                if len(I) == 0:
                    continue
                print('Epoch %i: %i tiles:' % (e, len(I)), W.coadd_id[I])
                edir = os.path.join(unwise_tr_dir, 'e%03i' % e)
                eoutdir = os.path.join(wise_tr_out, 'e%03i' % e)
                wisedata.append((edir, eoutdir, tiles.coadd_id[I], band))

        wrote_masks = set()

        for indir, outdir, tiles, band in wisedata:
            for tile in tiles:
                wanyband = 'w'
                tim = get_unwise_tractor_image(indir, tile, band,
                                               bandname=wanyband, roiradecbox=roiradec)
                print('Got unWISE tim', tim)
                print(tim.shape)
                
                thisdir = get_unwise_tile_dir(outdir, tile)
                print('Directory for this WISE tile:', thisdir)
                base = os.path.join(thisdir, 'unwise-%s-w%i-' % (tile, band))
                print('Base filename:', base)

                masked = True
                mu = 'm' if masked else 'u'

                imfn = base + 'img-%s.fits'       % mu
                ivfn = base + 'invvar-%s.fits.gz' % mu
                nifn = base + 'n-%s.fits.gz'      % mu
                nufn = base + 'n-u.fits.gz'

                #print('WISE image header:', tim.hdr)

                # Adjust the header WCS by x0,y0
                wcs = tim.wcs.wcs
                tim.hdr['CRPIX1'] = wcs.crpix[0]
                tim.hdr['CRPIX2'] = wcs.crpix[1]

                H,W = tim.shape
                tim.hdr['IMAGEW'] = W
                tim.hdr['IMAGEH'] = H

                print('WCS:', wcs)
                print('Header CRPIX', tim.hdr['CRPIX1'], tim.hdr['CRPIX2'])

                trymakedirs(imfn, dir=True)
                fitsio.write(imfn, tim.getImage(), header=tim.hdr, clobber=True)
                print('Wrote', imfn)
                fitsio.write(ivfn, tim.getInvvar(), header=tim.hdr, clobber=True)
                print('Wrote', ivfn)
                fitsio.write(nifn, tim.nims, header=tim.hdr, clobber=True)
                print('Wrote', nifn)
                fitsio.write(nufn, tim.nuims, header=tim.hdr, clobber=True)
                print('Wrote', nufn)

                if not (indir,tile) in wrote_masks:
                    print('Looking for mask file for', indir, tile)
                    # record that we tried this dir/tile combo
                    wrote_masks.add((indir,tile))
                    for idir in indir.split(':'):
                        tdir = get_unwise_tile_dir(idir, tile)
                        maskfn = 'unwise-%s-msk.fits.gz' % tile
                        fn = os.path.join(tdir, maskfn)
                        print('Mask file:', fn)
                        if os.path.exists(fn):
                            print('Reading', fn)
                            (x0,x1,y0,y1) = tim.roi
                            roislice = (slice(y0,y1), slice(x0,x1))
                            F = fitsio.FITS(fn)[0]
                            hdr = F.read_header()
                            M = F[roislice]
                            outfn = os.path.join(thisdir, maskfn)
                            fitsio.write(outfn, M, header=tim.hdr, clobber=True)
                            print('Wrote', outfn)
                            break

    outC = outsurvey.get_ccds_readonly()
    for iccd,ccd in enumerate(outC):
        outim = outsurvey.get_image_object(ccd)
        print('Got output image:', outim)
        otim = outim.get_tractor_image(pixPsf=True, splinesky=True)
        print('Got output tim:', otim)
Example #27
0
def main(survey=None, opt=None):
    '''Driver function for forced photometry of individual Legacy
    Survey images.
    '''
    if opt is None:
        parser = get_parser()
        opt = parser.parse_args()

    Time.add_measurement(MemMeas)
    t0 = Time()

    if os.path.exists(opt.outfn):
        print('Ouput file exists:', opt.outfn)
        sys.exit(0)

    if opt.derivs and opt.agn:
        print('Sorry, can\'t do --derivs AND --agn')
        sys.exit(0)

    if not opt.forced:
        opt.apphot = True

    zoomslice = None
    if opt.zoom is not None:
        (x0, x1, y0, y1) = opt.zoom
        zoomslice = (slice(y0, y1), slice(x0, x1))

    ps = None
    if opt.plots is not None:
        import pylab as plt
        from astrometry.util.plotutils import PlotSequence
        ps = PlotSequence(opt.plots)

    # Try parsing filename as exposure number.
    try:
        expnum = int(opt.expnum)
        filename = None
    except:
        # make this 'None' for survey.find_ccds()
        expnum = None
        filename = opt.expnum

    # Try parsing HDU number
    try:
        hdu = int(opt.ccdname)
        ccdname = None
    except:
        hdu = -1
        ccdname = opt.ccdname

    if survey is None:
        survey = LegacySurveyData()

    catsurvey = survey
    if opt.catalog_dir is not None:
        catsurvey = LegacySurveyData(survey_dir=opt.catalog_dir)

    if filename is not None and hdu >= 0:
        # FIXME -- try looking up in CCDs file?
        # Read metadata from file
        print('Warning: faking metadata from file contents')
        T = exposure_metadata([filename], hdus=[hdu])
        print('Metadata:')
        T.about()

        if not 'ccdzpt' in T.columns():
            phdr = fitsio.read_header(filename)
            T.ccdzpt = np.array([phdr['MAGZERO']])
            print('WARNING: using header MAGZERO')
            T.ccdraoff = np.array([0.])
            T.ccddecoff = np.array([0.])
            print('WARNING: setting CCDRAOFF, CCDDECOFF to zero.')

    else:
        # Read metadata from survey-ccds.fits table
        T = survey.find_ccds(expnum=expnum, ccdname=ccdname)
        print(len(T), 'with expnum', expnum, 'and CCDname', ccdname)
        if hdu >= 0:
            T.cut(T.image_hdu == hdu)
            print(len(T), 'with HDU', hdu)
        if filename is not None:
            T.cut(np.array([f.strip() == filename for f in T.image_filename]))
            print(len(T), 'with filename', filename)
        if opt.camera is not None:
            T.cut(T.camera == opt.camera)
            print(len(T), 'with camera', opt.camera)
        assert (len(T) == 1)

    ccd = T[0]
    im = survey.get_image_object(ccd)

    if opt.do_calib:
        #from legacypipe.survey import run_calibs
        #kwa = dict(splinesky=True)
        #run_calibs((im, kwa))
        im.run_calibs(splinesky=True)

    tim = im.get_tractor_image(slc=zoomslice,
                               pixPsf=True,
                               splinesky=True,
                               constant_invvar=opt.constant_invvar,
                               hybridPsf=opt.hybrid_psf,
                               normalizePsf=opt.normalize_psf)
    print('Got tim:', tim)

    print('Read image:', Time() - t0)

    if opt.catfn in ['DR1', 'DR2', 'DR3', 'DR5', 'DR']:

        margin = 20
        TT = []
        chipwcs = tim.subwcs
        bricks = bricks_touching_wcs(chipwcs, survey=catsurvey)
        for b in bricks:
            # there is some overlap with this brick... read the catalog.
            fn = catsurvey.find_file('tractor', brick=b.brickname)
            if not os.path.exists(fn):
                print('WARNING: catalog', fn, 'does not exist.  Skipping!')
                continue
            print('Reading', fn)
            T = fits_table(fn)
            ok, xx, yy = chipwcs.radec2pixelxy(T.ra, T.dec)
            W, H = chipwcs.get_width(), chipwcs.get_height()
            I = np.flatnonzero((xx >= -margin) * (xx <= (W + margin)) *
                               (yy >= -margin) * (yy <= (H + margin)))
            T.cut(I)
            print('Cut to', len(T), 'sources within image + margin')
            # print('Brick_primary:', np.unique(T.brick_primary))
            T.cut(T.brick_primary)
            print('Cut to', len(T), 'on brick_primary')
            for col in ['out_of_bounds', 'left_blob']:
                if col in T.get_columns():
                    T.cut(T.get(col) == False)
                    print('Cut to', len(T), 'on', col)
            if len(T):
                TT.append(T)
        if len(TT) == 0:
            print('No sources to photometer.')
            return 0
        T = merge_tables(TT, columns='fillzero')
        T._header = TT[0]._header
        del TT
        print('Total of', len(T), 'catalog sources')

        # Fix up various failure modes:
        # FixedCompositeGalaxy(pos=RaDecPos[240.51147402832561, 10.385488075518923], brightness=NanoMaggies: g=(flux -2.87), r=(flux -5.26), z=(flux -7.65), fracDev=FracDev(0.60177207), shapeExp=re=3.78351e-44, e1=9.30367e-13, e2=1.24392e-16, shapeDev=re=inf, e1=-0, e2=-0)
        # -> convert to EXP
        I = np.flatnonzero(
            np.array([((t.type == 'COMP') and (not np.isfinite(t.shapedev_r)))
                      for t in T]))
        if len(I):
            print('Converting', len(I), 'bogus COMP galaxies to EXP')
            for i in I:
                T.type[i] = 'EXP'

        # Same thing with the exp component.
        # -> convert to DEV
        I = np.flatnonzero(
            np.array([((t.type == 'COMP') and (not np.isfinite(t.shapeexp_r)))
                      for t in T]))
        if len(I):
            print('Converting', len(I), 'bogus COMP galaxies to DEV')
            for i in I:
                T.type[i] = 'DEV'

        if opt.write_cat:
            T.writeto(opt.write_cat)
            print('Wrote catalog to', opt.write_cat)

    else:
        T = fits_table(opt.catfn)

    surveydir = survey.get_survey_dir()
    del survey

    kwargs = {}
    cols = T.get_columns()
    if 'flux_r' in cols and not 'decam_flux_r' in cols:
        kwargs.update(fluxPrefix='')
    cat = read_fits_catalog(T, **kwargs)
    # Replace the brightness (which will be a NanoMaggies with g,r,z)
    # with a NanoMaggies with this image's band only.
    for src in cat:
        src.brightness = NanoMaggies(**{tim.band: 1.})

    print('Read catalog:', Time() - t0)

    print('Forced photom...')
    F = run_forced_phot(cat,
                        tim,
                        ceres=opt.ceres,
                        derivs=opt.derivs,
                        fixed_also=True,
                        agn=opt.agn,
                        do_forced=opt.forced,
                        do_apphot=opt.apphot,
                        ps=ps)
    t0 = Time()

    F.release = T.release
    F.brickid = T.brickid
    F.brickname = T.brickname
    F.objid = T.objid

    F.camera = np.array([ccd.camera] * len(F))
    F.expnum = np.array([im.expnum] * len(F)).astype(np.int32)
    F.ccdname = np.array([im.ccdname] * len(F))

    # "Denormalizing"
    F.filter = np.array([tim.band] * len(T))
    F.mjd = np.array([tim.primhdr['MJD-OBS']] * len(T))
    F.exptime = np.array([tim.primhdr['EXPTIME']] * len(T)).astype(np.float32)
    F.ra = T.ra
    F.dec = T.dec

    ok, x, y = tim.sip_wcs.radec2pixelxy(T.ra, T.dec)
    F.x = (x - 1).astype(np.float32)
    F.y = (y - 1).astype(np.float32)

    h, w = tim.shape
    F.mask = tim.dq[np.clip(np.round(F.y).astype(int), 0, h - 1),
                    np.clip(np.round(F.x).astype(int), 0, w - 1)]

    program_name = sys.argv[0]
    version_hdr = get_version_header(program_name, surveydir)
    filename = getattr(ccd, 'image_filename')
    if filename is None:
        # HACK -- print only two directory names + filename of CPFILE.
        fname = os.path.basename(im.imgfn)
        d = os.path.dirname(im.imgfn)
        d1 = os.path.basename(d)
        d = os.path.dirname(d)
        d2 = os.path.basename(d)
        filename = os.path.join(d2, d1, fname)
        print('Trimmed filename to', filename)
    version_hdr.add_record(
        dict(name='CPFILE', value=filename, comment='CP file'))
    version_hdr.add_record(dict(name='CPHDU', value=im.hdu, comment='CP ext'))
    version_hdr.add_record(
        dict(name='CAMERA', value=ccd.camera, comment='Camera'))
    version_hdr.add_record(
        dict(name='EXPNUM', value=im.expnum, comment='Exposure num'))
    version_hdr.add_record(
        dict(name='CCDNAME', value=im.ccdname, comment='CCD name'))
    version_hdr.add_record(
        dict(name='FILTER', value=tim.band, comment='Bandpass of this image'))
    version_hdr.add_record(
        dict(name='EXPOSURE',
             value='%s-%s-%s' % (ccd.camera, im.expnum, im.ccdname),
             comment='Name of this image'))

    keys = [
        'TELESCOP', 'OBSERVAT', 'OBS-LAT', 'OBS-LONG', 'OBS-ELEV', 'INSTRUME'
    ]
    for key in keys:
        if key in tim.primhdr:
            version_hdr.add_record(dict(name=key, value=tim.primhdr[key]))

    hdr = fitsio.FITSHDR()
    units = {
        'exptime': 'sec',
        'flux': 'nanomaggy',
        'flux_ivar': '1/nanomaggy^2'
    }
    columns = F.get_columns()
    for i, col in enumerate(columns):
        if col in units:
            hdr.add_record(dict(name='TUNIT%i' % (i + 1), value=units[col]))

    outdir = os.path.dirname(opt.outfn)
    if len(outdir):
        trymakedirs(outdir)
    fitsio.write(opt.outfn, None, header=version_hdr, clobber=True)
    F.writeto(opt.outfn, header=hdr, append=True)
    print('Wrote', opt.outfn)

    if opt.save_model or opt.save_data:
        hdr = fitsio.FITSHDR()
        tim.getWcs().wcs.add_to_header(hdr)
    if opt.save_model:
        print('Getting model image...')
        tr = Tractor([tim], cat)
        mod = tr.getModelImage(tim)
        fitsio.write(opt.save_model, mod, header=hdr, clobber=True)
        print('Wrote', opt.save_model)
    if opt.save_data:
        fitsio.write(opt.save_data, tim.getImage(), header=hdr, clobber=True)
        print('Wrote', opt.save_data)

    print('Finished forced phot:', Time() - t0)
    return 0
Example #28
0
def rbmain():
    from legacypipe.catalog import read_fits_catalog
    from legacypipe.survey import LegacySurveyData, wcs_for_brick
    from tractor.galaxy import DevGalaxy
    from tractor import PointSource, Catalog
    from tractor import GaussianMixturePSF
    from legacypipe.survey import BrickDuck
    from legacypipe.forced_photom import main as forced_main
    from astrometry.util.file import trymakedirs
    import shutil

    ceres = 'ceres' in sys.argv
    psfex = 'psfex' in sys.argv

    for v in [
            'UNWISE_COADDS_TIMERESOLVED_DIR', 'SKY_TEMPLATE_DIR',
            'LARGEGALAXIES_CAT', 'GAIA_CAT_DIR', 'TYCHO2_KD_DIR'
    ]:
        if v in os.environ:
            del os.environ[v]

    oldargs = sys.argv
    sys.argv = [sys.argv[0]]
    main()
    sys.argv = oldargs

    # Test create_kdtree and (reading CCD kd-tree)!
    indir = os.path.join(os.path.dirname(__file__), 'testcase6')
    with tempfile.TemporaryDirectory() as surveydir:
        files = [
            'calib', 'gaia', 'images', 'survey-bricks.fits.gz',
            'tycho2.kd.fits'
        ]
        for fn in files:
            src = os.path.join(indir, fn)
            dst = os.path.join(surveydir, fn)
            #trymakedirs(dst, dir=True)
            print('Copy', src, dst)
            if os.path.isfile(src):
                shutil.copy(src, dst)
            else:
                shutil.copytree(src, dst)

        from legacypipe.create_kdtrees import create_kdtree
        infn = os.path.join(indir, 'survey-ccds-1.fits.gz')
        outfn = os.path.join(surveydir, 'survey-ccds-1.kd.fits')
        create_kdtree(infn, outfn, False)

        os.environ['TYCHO2_KD_DIR'] = surveydir
        outdir = 'out-testcase6-kd'
        main(args=[
            '--brick', '1102p240', '--zoom', '500', '600', '650', '750',
            '--force-all', '--no-write', '--no-wise', '--no-gaia',
            '--survey-dir', surveydir, '--outdir', outdir
        ])
        fn = os.path.join(outdir, 'tractor', '110', 'tractor-1102p240.fits')
        assert (os.path.exists(fn))
        T = fits_table(fn)
        assert (len(T) == 2)
        # Since there is a Tycho-2 star in the blob, forced to be PSF.
        assert (T.type[0].strip() == 'PSF')
        assert (T.type[1].strip() == 'PSF')
        # There is a Tycho-2 star in the blob.
        I = np.flatnonzero(T.ref_cat == 'T2')
        assert (len(I) == 1)
        assert (T.ref_id[I][0] == 1909016711)

        cat = read_fits_catalog(T)
        assert (len(cat) == 2)
        assert (isinstance(cat[0], PointSource))
        assert (isinstance(cat[1], PointSource))
        cat, ivs = read_fits_catalog(T, invvars=True)
        assert (len(cat) == 2)
        assert (isinstance(cat[0], PointSource))
        assert (isinstance(cat[1], PointSource))
        cat2 = Catalog(*cat)
        assert (len(ivs) == len(cat2.getParams()))

        # test --fit-on-coadds
        outdir = 'out-testcase6-coadds'
        main(args=[
            '--brick', '1102p240', '--zoom', '500', '600', '650', '750',
            '--force-all', '--no-write', '--no-wise', '--no-gaia',
            '--survey-dir', surveydir, '--fit-on-coadds', '--outdir', outdir
        ])

        fn = os.path.join(outdir, 'tractor', '110', 'tractor-1102p240.fits')
        assert (os.path.exists(fn))
        T = fits_table(fn)
        assert (len(T) == 2)
        # Since there is a Tycho-2 star in the blob, forced to be PSF.
        assert (T.type[0].strip() == 'PSF')
        assert (T.type[1].strip() == 'PSF')
        # There is a Tycho-2 star in the blob.
        I = np.flatnonzero(T.ref_cat == 'T2')
        assert (len(I) == 1)
        assert (T.ref_id[I][0] == 1909016711)
        del os.environ['TYCHO2_KD_DIR']

        # test --skip-coadds
        r = main(args=[
            '--brick', '1102p240', '--zoom', '500', '600', '650', '750',
            '--force-all', '--no-write', '--no-wise', '--no-gaia',
            '--survey-dir', surveydir, '--outdir', outdir, '--skip-coadd'
        ])
        assert (r == 0)

        # test --skip
        r = main(args=[
            '--brick', '1102p240', '--zoom', '500', '600', '650', '750',
            '--force-all', '--no-write', '--no-wise', '--no-gaia',
            '--survey-dir', surveydir, '--outdir', outdir, '--skip'
        ])
        assert (r == 0)

        # NothingToDoError (neighbouring brick)
        r = main(args=[
            '--brick', '1102p240', '--zoom', '0', '100', '0', '100',
            '--force-all', '--no-write', '--no-wise', '--no-gaia',
            '--survey-dir', surveydir, '--outdir', outdir
        ])
        assert (r == 0)

    surveydir = os.path.join(os.path.dirname(__file__), 'testcase9')

    # Test for some get_tractor_image kwargs
    survey = LegacySurveyData(surveydir)
    fakebrick = BrickDuck(9.1228, 3.3975, 'quack')
    wcs = wcs_for_brick(fakebrick, W=100, H=100)
    ccds = survey.ccds_touching_wcs(wcs)
    ccd = ccds[0]
    im = survey.get_image_object(ccd)
    H, W = wcs.shape
    targetrd = np.array([
        wcs.pixelxy2radec(x, y)
        for x, y in [(1, 1), (W, 1), (W, H), (1, H), (1, 1)]
    ])
    tim = im.get_tractor_image(radecpoly=targetrd)
    assert (tim.getImage() is not None)
    assert (tim.getInvError() is not None)
    assert (tim.dq is not None)
    tim2 = im.get_tractor_image(radecpoly=targetrd, pixels=False)
    assert (np.all(tim2.getImage() == 0.))
    tim4 = im.get_tractor_image(radecpoly=targetrd, invvar=False)
    u = np.unique(tim4.inverr)
    assert (len(u) == 1)
    u = u[0]
    target = tim4.zpscale / tim4.sig1
    assert (np.abs(u / target - 1.) < 0.001)
    tim3 = im.get_tractor_image(radecpoly=targetrd, invvar=False, dq=False)
    assert (not hasattr(tim3, 'dq'))
    tim5 = im.get_tractor_image(radecpoly=targetrd, gaussPsf=True)
    print(tim5.getPsf())
    assert (isinstance(tim5.getPsf(), GaussianMixturePSF))

    surveydir = os.path.join(os.path.dirname(__file__), 'testcase12')
    os.environ['TYCHO2_KD_DIR'] = surveydir
    os.environ['GAIA_CAT_DIR'] = os.path.join(surveydir, 'gaia')
    os.environ['GAIA_CAT_VER'] = '2'
    os.environ['UNWISE_MODEL_SKY_DIR'] = os.path.join(surveydir, 'images',
                                                      'unwise-mod')
    #python legacypipe/runbrick.py --radec  --width 100 --height 100 --outdir dup5b --survey-dir test/testcase12 --force-all --no-wise
    unwdir = os.path.join(surveydir, 'images', 'unwise')
    main(args=[
        '--radec', '346.684', '12.791', '--width', '100', '--height', '100',
        '--no-wise-ceres', '--unwise-dir', unwdir, '--survey-dir', surveydir,
        '--outdir', 'out-testcase12', '--skip-coadd', '--force-all'
    ])

    # --plots for stage_wise_forced
    main(args=[
        '--radec', '346.684', '12.791', '--width', '100', '--height', '100',
        '--no-wise-ceres', '--unwise-dir', unwdir, '--survey-dir', surveydir,
        '--outdir', 'out-testcase12', '--stage', 'wise_forced', '--plots'
    ])
    del os.environ['GAIA_CAT_DIR']
    del os.environ['GAIA_CAT_VER']
    del os.environ['TYCHO2_KD_DIR']
    del os.environ['UNWISE_MODEL_SKY_DIR']

    M = fitsio.read(
        'out-testcase12/coadd/cus/custom-346684p12791/legacysurvey-custom-346684p12791-maskbits.fits.fz'
    )
    # Count masked & unmasked bits (the cluster splits this 100x100 field)
    from collections import Counter
    c = Counter(M.ravel())
    from legacypipe.bits import MASKBITS
    assert (c[0] >= 4000)
    assert (c[MASKBITS['CLUSTER']] >= 4000)

    surveydir = os.path.join(os.path.dirname(__file__), 'testcase9')
    os.environ['GAIA_CAT_DIR'] = os.path.join(surveydir, 'gaia')
    os.environ['GAIA_CAT_VER'] = '2'
    os.environ['LARGEGALAXIES_CAT'] = os.path.join(surveydir,
                                                   'sga-sub.kd.fits')
    main(args=[
        '--radec', '9.1228', '3.3975', '--width', '100', '--height', '100',
        '--old-calibs-ok', '--no-wise-ceres', '--no-wise', '--survey-dir',
        surveydir, '--outdir', 'out-testcase9', '--skip', '--force-all',
        '--ps', 'tc9-ps.fits', '--ps-t0',
        str(int(time.time()))
    ])
    # (omit --force-all --no-write... reading from pickles below!)

    # Test with --apodize
    main(args=[
        '--radec', '9.1228', '3.3975', '--width', '100', '--height', '100',
        '--old-calibs-ok', '--no-wise', '--force-all', '--no-write',
        '--survey-dir', surveydir, '--outdir', 'out-testcase9-ap', '--apodize'
    ])

    main(args=[
        '--radec', '9.1228', '3.3975', '--width', '100', '--height', '100',
        '--old-calibs-ok', '--no-wise-ceres', '--no-wise', '--survey-dir',
        surveydir, '--outdir', 'out-testcase9', '--plots', '--stage', 'halos'
    ])

    main(args=[
        '--radec', '9.1228', '3.3975', '--width', '100', '--height', '100',
        '--old-calibs-ok', '--no-wise-ceres', '--no-wise', '--survey-dir',
        surveydir, '--outdir', 'out-testcase9-coadds', '--stage',
        'image_coadds', '--blob-image'
    ])

    T = fits_table(
        'out-testcase9/tractor/cus/tractor-custom-009122p03397.fits')
    assert (len(T) == 4)
    # Gaia star becomes a DUP!
    assert (np.sum([t == 'DUP' for t in T.type]) == 1)
    # LSLGA galaxy exists!
    Igal = np.flatnonzero([r == 'L3' for r in T.ref_cat])
    assert (len(Igal) == 1)
    assert (np.all(T.ref_id[Igal] > 0))
    assert (T.type[Igal[0]] == 'SER')

    # --brick and --zoom rather than --radec --width --height
    main(args=[
        '--survey-dir', surveydir, '--outdir', 'out-testcase9b', '--zoom',
        '1950', '2050', '340', '440', '--brick', '0091p035', '--force-all'
    ])

    # test forced phot??
    shutil.copy('test/testcase9/survey-bricks.fits.gz', 'out-testcase9b')

    forced_main(args=[
        '--survey-dir', surveydir, '--no-ceres', '--catalog-dir',
        'out-testcase9b', '372546', 'N26', 'forced1.fits'
    ])
    assert (os.path.exists('forced1.fits'))
    _ = fits_table('forced1.fits')
    # ... more tests...!

    forced_main(args=[
        '--survey-dir', surveydir, '--no-ceres', '--catalog-dir',
        'out-testcase9b', '--derivs', '--threads', '2', '--apphot', '372547',
        'N26', 'forced2.fits'
    ])
    assert (os.path.exists('forced2.fits'))
    _ = fits_table('forced2.fits')

    forced_main(args=[
        '--survey-dir', surveydir, '--no-ceres', '--catalog-dir',
        'out-testcase9b', '--agn', '257266', 'S21', 'forced3.fits'
    ])
    assert (os.path.exists('forced3.fits'))
    _ = fits_table('forced3.fits')

    if ceres:
        forced_main(args=[
            '--survey-dir', surveydir, '--catalog-dir', 'out-testcase9b',
            '--derivs', '--threads', '2', '--apphot', '372546', 'N26',
            'forced4.fits'
        ])
        assert (os.path.exists('forced4.fits'))
        _ = fits_table('forced4.fits')

    # Test cache_dir
    with tempfile.TemporaryDirectory() as cachedir, \
        tempfile.TemporaryDirectory() as tempsurveydir:
        files = []
        for dirpath, _, filenames in os.walk(surveydir):
            for fn in filenames:
                path = os.path.join(dirpath, fn)
                relpath = os.path.relpath(path, surveydir)
                files.append(relpath)
        # cache or no?
        files.sort()
        files_cache = files[::2]
        files_nocache = files[1::2]
        # Survey-ccds *must* be in nocache.
        fn = 'survey-ccds-1.kd.fits'
        if fn in files_cache:
            files_cache.remove(fn)
            files_nocache.append(fn)

        for fn in files_cache:
            src = os.path.join(surveydir, fn)
            dst = os.path.join(cachedir, fn)
            trymakedirs(dst, dir=True)
            print('Copy', src, dst)
            shutil.copy(src, dst)

        for fn in files_nocache:
            src = os.path.join(surveydir, fn)
            dst = os.path.join(tempsurveydir, fn)
            trymakedirs(dst, dir=True)
            print('Copy', src, dst)
            shutil.copy(src, dst)

        main(args=[
            '--radec', '9.1228', '3.3975', '--width', '100', '--height', '100',
            '--no-wise', '--survey-dir', tempsurveydir, '--cache-dir',
            cachedir, '--outdir', 'out-testcase9cache', '--force-all'
        ])

    del os.environ['GAIA_CAT_DIR']
    del os.environ['GAIA_CAT_VER']
    del os.environ['LARGEGALAXIES_CAT']

    # if ceres:
    #     surveydir = os.path.join(os.path.dirname(__file__), 'testcase3')
    #     main(args=['--brick', '2447p120', '--zoom', '1020', '1070', '2775', '2815',
    #                '--no-wise', '--force-all', '--no-write', '--ceres',
    #                '--survey-dir', surveydir,
    #                '--outdir', 'out-testcase3-ceres',
    #                '--no-depth-cut'])

    # MzLS + BASS data
    # python legacypipe/runbrick.py --run north --brick 1773p595 --zoom 1300 1500 700 900 --survey-dir dr9-north -s coadds
    # fitscopy coadd/177/1773p595/legacysurvey-1773p595-ccds.fits"[#row<3 || #row==12]" cx.fits
    # python legacyanalysis/create_testcase.py cx.fits test/mzlsbass2 1773p595 --survey-dir dr9-north/ --fpack
    surveydir2 = os.path.join(os.path.dirname(__file__), 'mzlsbass2')
    os.environ['GAIA_CAT_DIR'] = os.path.join(surveydir2, 'gaia')
    os.environ['GAIA_CAT_VER'] = '2'
    main(args=[
        '--brick', '1773p595', '--zoom', '1300', '1500', '700', '900',
        '--no-wise', '--force-all', '--no-write', '--survey-dir', surveydir2,
        '--outdir', 'out-mzlsbass2'
    ])

    T = fits_table('out-mzlsbass2/tractor/177/tractor-1773p595.fits')
    assert (np.sum(T.ref_cat == 'G2') == 3)
    assert (np.sum(T.ref_id > 0) == 3)

    # Test --max-blobsize, --checkpoint, --bail-out

    outdir = 'out-mzlsbass2b'
    chk = 'checkpoint-mzb2b.p'
    if os.path.exists(chk):
        os.unlink(chk)
    main(args=[
        '--brick', '1773p595', '--zoom', '1300', '1500', '700', '900',
        '--no-wise', '--force-all', '--stage', 'fitblobs', '--write-stage',
        'srcs', '--survey-dir', surveydir2, '--outdir', outdir, '--checkpoint',
        chk, '--nblobs', '3'
    ])
    # err... --max-blobsize does not result in bailed-out blobs masked,
    # because it treats large blobs as *completed*...
    #'--max-blobsize', '3000',

    outdir = 'out-mzlsbass2c'
    main(args=[
        '--brick', '1773p595', '--zoom', '1300', '1500', '700', '900',
        '--no-wise', '--force-all', '--survey-dir', surveydir2, '--outdir',
        outdir, '--bail-out', '--checkpoint', chk, '--no-write'
    ])

    del os.environ['GAIA_CAT_DIR']
    del os.environ['GAIA_CAT_VER']

    M = fitsio.read(
        os.path.join(outdir, 'coadd', '177', '1773p595',
                     'legacysurvey-1773p595-maskbits.fits.fz'))
    assert (np.sum((M & MASKBITS['BAILOUT']) > 0) >= 1000)

    # Test RexGalaxy

    surveydir = os.path.join(os.path.dirname(__file__), 'testcase6')
    outdir = 'out-testcase6-rex'
    the_args = [
        '--brick',
        '1102p240',
        '--zoom',
        '500',
        '600',
        '650',
        '750',
        '--force-all',
        '--no-write',
        '--no-wise',
        '--skip-calibs',
        #'--rex', #'--plots',
        '--survey-dir',
        surveydir,
        '--outdir',
        outdir
    ]
    print('python legacypipe/runbrick.py', ' '.join(the_args))
    os.environ['GAIA_CAT_DIR'] = os.path.join(surveydir, 'gaia')
    os.environ['GAIA_CAT_VER'] = '2'
    main(args=the_args)
    fn = os.path.join(outdir, 'tractor', '110', 'tractor-1102p240.fits')
    assert (os.path.exists(fn))
    T = fits_table(fn)
    assert (len(T) == 2)
    print('Types:', T.type)
    # Since there is a Tycho-2 star in the blob, forced to be PSF.
    assert (T.type[0].strip() == 'PSF')
    cmd = (
        '(cd %s && sha256sum -c %s)' %
        (outdir, os.path.join('tractor', '110', 'brick-1102p240.sha256sum')))
    print(cmd)
    rtn = os.system(cmd)
    assert (rtn == 0)

    # Test with a Tycho-2 star in the blob.

    surveydir = os.path.join(os.path.dirname(__file__), 'testcase6')
    outdir = 'out-testcase6'
    main(args=[
        '--brick', '1102p240', '--zoom', '500', '600', '650', '750',
        '--force-all', '--no-write', '--no-wise', '--survey-dir', surveydir,
        '--outdir', outdir
    ])
    fn = os.path.join(outdir, 'tractor', '110', 'tractor-1102p240.fits')
    assert (os.path.exists(fn))
    T = fits_table(fn)
    assert (len(T) == 2)
    print('Types:', T.type)
    # Since there is a Tycho-2 star in the blob, forced to be PSF.
    assert (T.type[0].strip() == 'PSF')
    del os.environ['GAIA_CAT_DIR']
    del os.environ['GAIA_CAT_VER']

    # Test that we can run splinesky calib if required...

    from legacypipe.decam import DecamImage
    DecamImage.splinesky_boxsize = 128

    surveydir = os.path.join(os.path.dirname(__file__), 'testcase4')

    survey = LegacySurveyData(surveydir)
    # get brick by id
    brickid = 473357
    brick = survey.get_brick(brickid)
    assert (brick.brickname == '1867p255')
    assert (brick.brickid == brickid)

    outdir = 'out-testcase4'
    os.environ['GAIA_CAT_DIR'] = os.path.join(surveydir, 'gaia')
    os.environ['GAIA_CAT_VER'] = '2'

    fn = os.path.join(surveydir, 'calib', 'sky-single', 'decam', 'CP',
                      'V4.8.2', 'CP20170315', 'c4d_170316_062107_ooi_z_ls9',
                      'c4d_170316_062107_ooi_z_ls9-N2-splinesky.fits')
    if os.path.exists(fn):
        os.unlink(fn)

    main(args=[
        '--brick', '1867p255', '--zoom', '2050', '2300', '1150', '1400',
        '--force-all', '--no-write', '--coadd-bw', '--unwise-dir',
        os.path.join(surveydir, 'images', 'unwise'), '--unwise-tr-dir',
        os.path.join(surveydir, 'images',
                     'unwise-tr'), '--blob-image', '--no-hybrid-psf',
        '--survey-dir', surveydir, '--outdir', outdir, '-v', '--no-wise-ceres'
    ])
    print('Checking for calib file', fn)
    assert (os.path.exists(fn))

    # Test with blob-masking when creating sky calib.
    os.unlink(fn)

    main(args=[
        '--brick', '1867p255', '--zoom', '2050', '2300', '1150', '1400',
        '--force-all', '--no-write', '--coadd-bw', '--blob-mask-dir',
        surveydir, '--survey-dir', surveydir, '--stage', 'image_coadds',
        '--outdir', 'out-testcase4b', '--plots'
    ])
    print('Checking for calib file', fn)
    assert (os.path.exists(fn))

    if ceres:
        main(args=[
            '--brick', '1867p255', '--zoom', '2050', '2300', '1150', '1400',
            '--force-all', '--no-write', '--coadd-bw', '--unwise-dir',
            os.path.join(surveydir, 'images', 'unwise'), '--unwise-tr-dir',
            os.path.join(surveydir, 'images', 'unwise-tr'), '--survey-dir',
            surveydir, '--outdir', outdir
        ])
    if psfex:
        # Check that we can regenerate PsfEx files if necessary.
        fn = os.path.join(surveydir, 'calib', 'psfex', 'decam', 'CP', 'V4.8.2',
                          'CP20170315',
                          'c4d_170316_062107_ooi_z_ls9-psfex.fits')
        if os.path.exists(fn):
            os.unlink(fn)

        main(args=[
            '--brick', '1867p255', '--zoom', '2050', '2300', '1150', '1400',
            '--force-all', '--no-write', '--coadd-bw', '--unwise-dir',
            os.path.join(surveydir, 'images', 'unwise'), '--unwise-tr-dir',
            os.path.join(surveydir, 'images', 'unwise-tr'), '--blob-image',
            '--survey-dir', surveydir, '--outdir', outdir, '-v'
        ])
        print('After generating PsfEx calib:')
        os.system('find %s' % (os.path.join(surveydir, 'calib')))

    # Wrap-around, hybrid PSF
    surveydir = os.path.join(os.path.dirname(__file__), 'testcase8')
    outdir = 'out-testcase8'
    os.environ['GAIA_CAT_DIR'] = os.path.join(surveydir, 'gaia')
    os.environ['GAIA_CAT_VER'] = '2'

    main(args=[
        '--brick',
        '1209p050',
        '--zoom',
        '720',
        '1095',
        '3220',
        '3500',
        '--force-all',
        '--no-write',
        '--no-wise',  #'--plots',
        '--survey-dir',
        surveydir,
        '--outdir',
        outdir
    ])

    # Test with a Tycho-2 star + another saturated star in the blob.

    surveydir = os.path.join(os.path.dirname(__file__), 'testcase7')
    outdir = 'out-testcase7'
    os.environ['GAIA_CAT_DIR'] = os.path.join(surveydir, 'gaia')
    os.environ['GAIA_CAT_VER'] = '2'
    main(args=[
        '--brick',
        '1102p240',
        '--zoom',
        '250',
        '350',
        '1550',
        '1650',
        '--force-all',
        '--no-write',
        '--no-wise',  #'--plots',
        '--survey-dir',
        surveydir,
        '--outdir',
        outdir
    ])
    del os.environ['GAIA_CAT_DIR']
    del os.environ['GAIA_CAT_VER']
    fn = os.path.join(outdir, 'tractor', '110', 'tractor-1102p240.fits')
    assert (os.path.exists(fn))
    T = fits_table(fn)
    assert (len(T) == 4)

    # Check skipping blobs outside the brick's unique area.
    # (this now doesn't detect any sources at all, reasonably)
    # surveydir = os.path.join(os.path.dirname(__file__), 'testcase5')
    # outdir = 'out-testcase5'
    #
    # fn = os.path.join(outdir, 'tractor', '186', 'tractor-1867p255.fits')
    # if os.path.exists(fn):
    #     os.unlink(fn)
    #
    # main(args=['--brick', '1867p255', '--zoom', '0', '150', '0', '150',
    #            '--force-all', '--no-write', '--coadd-bw',
    #            '--survey-dir', surveydir,
    #            '--early-coadds',
    #            '--outdir', outdir] + extra_args)
    #
    # assert(os.path.exists(fn))
    # T = fits_table(fn)
    # assert(len(T) == 1)

    # Custom RA,Dec; blob ra,dec.
    surveydir = os.path.join(os.path.dirname(__file__), 'testcase4')
    outdir = 'out-testcase4b'
    os.environ['GAIA_CAT_DIR'] = os.path.join(surveydir, 'gaia')
    # Catalog written with one entry (--blobradec)
    fn = os.path.join(outdir, 'tractor', 'cus',
                      'tractor-custom-186743p25461.fits')
    if os.path.exists(fn):
        os.unlink(fn)
    main(args=[
        '--radec', '186.743965', '25.461788', '--width', '250', '--height',
        '250', '--force-all', '--no-write', '--no-wise', '--blobradec',
        '186.740369', '25.453855', '--survey-dir', surveydir, '--outdir',
        outdir
    ])

    assert (os.path.exists(fn))
    T = fits_table(fn)
    assert (len(T) == 1)

    surveydir = os.path.join(os.path.dirname(__file__), 'testcase3')
    outdir = 'out-testcase3'
    os.environ['GAIA_CAT_DIR'] = os.path.join(surveydir, 'gaia')
    os.environ['GAIA_CAT_VER'] = '2'
    checkpoint_fn = os.path.join(outdir, 'checkpoint.pickle')
    if os.path.exists(checkpoint_fn):
        os.unlink(checkpoint_fn)
    main(args=[
        '--brick', '2447p120', '--zoom', '1020', '1070', '2775', '2815',
        '--no-wise', '--force-all', '--no-write', '--survey-dir', surveydir,
        '--outdir', outdir, '--checkpoint', checkpoint_fn,
        '--checkpoint-period', '1', '--threads', '2'
    ])

    # Read catalog into Tractor sources to test read_fits_catalog
    survey = LegacySurveyData(survey_dir=outdir)
    fn = survey.find_file('tractor', brick='2447p120')
    print('Checking', fn)
    T = fits_table(fn)
    cat = read_fits_catalog(T)
    print('Read catalog:', cat)

    assert (len(cat) == 2)
    src = cat[1]
    print('Source0', src)
    from tractor.sersic import SersicGalaxy
    assert (type(src) in [DevGalaxy, SersicGalaxy])
    assert (np.abs(src.pos.ra - 244.77973) < 0.00001)
    assert (np.abs(src.pos.dec - 12.07234) < 0.00002)
    src = cat[0]
    print('Source1', src)
    assert (type(src) == PointSource)
    assert (np.abs(src.pos.ra - 244.77828) < 0.00001)
    assert (np.abs(src.pos.dec - 12.07250) < 0.00001)

    # Check that we can run again, using that checkpoint file.
    main(args=[
        '--brick', '2447p120', '--zoom', '1020', '1070', '2775', '2815',
        '--no-wise', '--force-all', '--no-write', '--survey-dir', surveydir,
        '--outdir', outdir, '--checkpoint', checkpoint_fn,
        '--checkpoint-period', '1', '--threads', '2'
    ])
    # Assert...... something?

    # Test --checkpoint without --threads
    main(args=[
        '--brick', '2447p120', '--zoom', '1020', '1070', '2775', '2815',
        '--no-wise', '--force-all', '--no-write', '--survey-dir', surveydir,
        '--outdir', outdir, '--checkpoint', checkpoint_fn,
        '--checkpoint-period', '1'
    ])

    # From Kaylan's Bootes pre-DR4 run
    # surveydir2 = os.path.join(os.path.dirname(__file__), 'mzlsbass3')
    # main(args=['--brick', '2173p350', '--zoom', '100', '200', '100', '200',
    #            '--no-wise', '--force-all', '--no-write',
    #            '--survey-dir', surveydir2,
    #            '--outdir', 'out-mzlsbass3'] + extra_args)

    # With plots!
    main(args=[
        '--brick', '2447p120', '--zoom', '1020', '1070', '2775', '2815',
        '--no-wise', '--force-all', '--no-write', '--survey-dir', surveydir,
        '--outdir', 'out-testcase3', '--plots', '--nblobs', '1'
    ])
def main(decals=None, opt=None):
    '''Driver function for forced photometry of individual DECam images.
    '''
    if opt is None:
        parser = get_parser()
        opt = parser.parse_args()

    Time.add_measurement(MemMeas)
    t0 = Time()

    if os.path.exists(opt.outfn):
        print('Ouput file exists:', opt.outfn)
        sys.exit(0)

    if not opt.forced:
        opt.apphot = True

    zoomslice = None
    if opt.zoom is not None:
        (x0,x1,y0,y1) = opt.zoom
        zoomslice = (slice(y0,y1), slice(x0,x1))

    ps = None
    if opt.plots is not None:
        from astrometry.util.plotutils import PlotSequence
        ps = PlotSequence(opt.plots)

    # Try parsing filename as exposure number.
    try:
        expnum = int(opt.filename)
        opt.filename = None
    except:
        # make this 'None' for decals.find_ccds()
        expnum = None

    # Try parsing HDU number
    try:
        opt.hdu = int(opt.hdu)
        ccdname = None
    except:
        ccdname = opt.hdu
        opt.hdu = -1

    if decals is None:
        decals = Decals()

    if opt.filename is not None and opt.hdu >= 0:
        # Read metadata from file
        T = exposure_metadata([opt.filename], hdus=[opt.hdu])
        print('Metadata:')
        T.about()
    else:
        # Read metadata from decals-ccds.fits table
        T = decals.find_ccds(expnum=expnum, ccdname=ccdname)
        print(len(T), 'with expnum', expnum, 'and CCDname', ccdname)
        if opt.hdu >= 0:
            T.cut(T.image_hdu == opt.hdu)
            print(len(T), 'with HDU', opt.hdu)
        if opt.filename is not None:
            T.cut(np.array([f.strip() == opt.filename for f in T.image_filename]))
            print(len(T), 'with filename', opt.filename)
        assert(len(T) == 1)

    im = decals.get_image_object(T[0])
    tim = im.get_tractor_image(slc=zoomslice, pixPsf=True, splinesky=True)
    print('Got tim:', tim)

    if opt.catfn in ['DR1', 'DR2']:
        if opt.catalog_path is None:
            opt.catalog_path = opt.catfn.lower()

        margin = 20
        TT = []
        chipwcs = tim.subwcs
        bricks = bricks_touching_wcs(chipwcs, decals=decals)
        for b in bricks:
            # there is some overlap with this brick... read the catalog.
            fn = os.path.join(opt.catalog_path, 'tractor', b.brickname[:3],
                              'tractor-%s.fits' % b.brickname)
            if not os.path.exists(fn):
                print('WARNING: catalog', fn, 'does not exist.  Skipping!')
                continue
            print('Reading', fn)
            T = fits_table(fn)
            ok,xx,yy = chipwcs.radec2pixelxy(T.ra, T.dec)
            W,H = chipwcs.get_width(), chipwcs.get_height()
            I = np.flatnonzero((xx >= -margin) * (xx <= (W+margin)) *
                               (yy >= -margin) * (yy <= (H+margin)))
            T.cut(I)
            print('Cut to', len(T), 'sources within image + margin')
            # print('Brick_primary:', np.unique(T.brick_primary))
            T.cut(T.brick_primary)
            print('Cut to', len(T), 'on brick_primary')
            T.cut((T.out_of_bounds == False) * (T.left_blob == False))
            print('Cut to', len(T), 'on out_of_bounds and left_blob')
            TT.append(T)
        T = merge_tables(TT)
        T._header = TT[0]._header
        del TT

        # Fix up various failure modes:
        # FixedCompositeGalaxy(pos=RaDecPos[240.51147402832561, 10.385488075518923], brightness=NanoMaggies: g=(flux -2.87), r=(flux -5.26), z=(flux -7.65), fracDev=FracDev(0.60177207), shapeExp=re=3.78351e-44, e1=9.30367e-13, e2=1.24392e-16, shapeDev=re=inf, e1=-0, e2=-0)
        # -> convert to EXP
        I = np.flatnonzero(np.array([((t.type == 'COMP') and
                                      (not np.isfinite(t.shapedev_r)))
                                     for t in T]))
        if len(I):
            print('Converting', len(I), 'bogus COMP galaxies to EXP')
            for i in I:
                T.type[i] = 'EXP'

        # Same thing with the exp component.
        # -> convert to DEV
        I = np.flatnonzero(np.array([((t.type == 'COMP') and
                                      (not np.isfinite(t.shapeexp_r)))
                                     for t in T]))
        if len(I):
            print('Converting', len(I), 'bogus COMP galaxies to DEV')
            for i in I:
                T.type[i] = 'DEV'

        if opt.write_cat:
            T.writeto(opt.write_cat)
            print('Wrote catalog to', opt.write_cat)

    else:
        T = fits_table(opt.catfn)

    T.shapeexp = np.vstack((T.shapeexp_r, T.shapeexp_e1, T.shapeexp_e2)).T
    T.shapedev = np.vstack((T.shapedev_r, T.shapedev_e1, T.shapedev_e2)).T

    cat = read_fits_catalog(T, ellipseClass=tractor.ellipses.EllipseE)
    # print('Got cat:', cat)

    print('Forced photom...')
    opti = None
    if opt.ceres:
        from tractor.ceres_optimizer import CeresOptimizer
        B = 8
        opti = CeresOptimizer(BW=B, BH=B)

    tr = Tractor([tim], cat, optimizer=opti)
    tr.freezeParam('images')
    for src in cat:
        src.freezeAllBut('brightness')
        src.getBrightness().freezeAllBut(tim.band)

    F = fits_table()
    F.brickid   = T.brickid
    F.brickname = T.brickname
    F.objid     = T.objid

    F.filter  = np.array([tim.band]               * len(T))
    F.mjd     = np.array([tim.primhdr['MJD-OBS']] * len(T))
    F.exptime = np.array([tim.primhdr['EXPTIME']] * len(T))

    ok,x,y = tim.sip_wcs.radec2pixelxy(T.ra, T.dec)
    F.x = (x-1).astype(np.float32)
    F.y = (y-1).astype(np.float32)

    if opt.apphot:
        import photutils

        img = tim.getImage()
        ie = tim.getInvError()
        with np.errstate(divide='ignore'):
            imsigma = 1. / ie
        imsigma[ie == 0] = 0.

        apimg = []
        apimgerr = []

        # Aperture photometry locations
        xxyy = np.vstack([tim.wcs.positionToPixel(src.getPosition()) for src in cat]).T
        apxy = xxyy - 1.

        apertures = apertures_arcsec / tim.wcs.pixel_scale()
        print('Apertures:', apertures, 'pixels')

        for rad in apertures:
            aper = photutils.CircularAperture(apxy, rad)
            p = photutils.aperture_photometry(img, aper, error=imsigma)
            apimg.append(p.field('aperture_sum'))
            apimgerr.append(p.field('aperture_sum_err'))
        ap = np.vstack(apimg).T
        ap[np.logical_not(np.isfinite(ap))] = 0.
        F.apflux = ap
        ap = 1./(np.vstack(apimgerr).T)**2
        ap[np.logical_not(np.isfinite(ap))] = 0.
        F.apflux_ivar = ap

    if opt.forced:
        kwa = {}
        if opt.plots is None:
            kwa.update(wantims=False)

        R = tr.optimize_forced_photometry(variance=True, fitstats=True,
                                          shared_params=False, **kwa)

        if opt.plots:
            (data,mod,ie,chi,roi) = R.ims1[0]

            ima = tim.ima
            imchi = dict(interpolation='nearest', origin='lower', vmin=-5, vmax=5)
            plt.clf()
            plt.imshow(data, **ima)
            plt.title('Data: %s' % tim.name)
            ps.savefig()

            plt.clf()
            plt.imshow(mod, **ima)
            plt.title('Model: %s' % tim.name)
            ps.savefig()

            plt.clf()
            plt.imshow(chi, **imchi)
            plt.title('Chi: %s' % tim.name)
            ps.savefig()

        F.flux = np.array([src.getBrightness().getFlux(tim.band)
                           for src in cat]).astype(np.float32)
        F.flux_ivar = R.IV.astype(np.float32)

        F.fracflux = R.fitstats.profracflux.astype(np.float32)
        F.rchi2    = R.fitstats.prochi2    .astype(np.float32)

    program_name = sys.argv[0]
    version_hdr = get_version_header(program_name, decals.decals_dir)
    # HACK -- print only two directory names + filename of CPFILE.
    fname = os.path.basename(im.imgfn)
    d = os.path.dirname(im.imgfn)
    d1 = os.path.basename(d)
    d = os.path.dirname(d)
    d2 = os.path.basename(d)
    fname = os.path.join(d2, d1, fname)
    print('Trimmed filename to', fname)
    #version_hdr.add_record(dict(name='CPFILE', value=im.imgfn, comment='DECam comm.pipeline file'))
    version_hdr.add_record(dict(name='CPFILE', value=fname, comment='DECam comm.pipeline file'))
    version_hdr.add_record(dict(name='CPHDU', value=im.hdu, comment='DECam comm.pipeline ext'))
    version_hdr.add_record(dict(name='CAMERA', value='DECam', comment='Dark Energy Camera'))
    version_hdr.add_record(dict(name='EXPNUM', value=im.expnum, comment='DECam exposure num'))
    version_hdr.add_record(dict(name='CCDNAME', value=im.ccdname, comment='DECam CCD name'))
    version_hdr.add_record(dict(name='FILTER', value=tim.band, comment='Bandpass of this image'))
    version_hdr.add_record(dict(name='EXPOSURE', value='decam-%s-%s' % (im.expnum, im.ccdname), comment='Name of this image'))

    keys = ['TELESCOP','OBSERVAT','OBS-LAT','OBS-LONG','OBS-ELEV',
            'INSTRUME']
    for key in keys:
        if key in tim.primhdr:
            version_hdr.add_record(dict(name=key, value=tim.primhdr[key]))

    hdr = fitsio.FITSHDR()

    units = {'mjd':'sec', 'exptime':'sec', 'flux':'nanomaggy',
             'flux_ivar':'1/nanomaggy^2'}
    columns = F.get_columns()
    for i,col in enumerate(columns):
        if col in units:
            hdr.add_record(dict(name='TUNIT%i' % (i+1), value=units[col]))

    outdir = os.path.dirname(opt.outfn)
    if len(outdir):
        trymakedirs(outdir)
    fitsio.write(opt.outfn, None, header=version_hdr, clobber=True)
    F.writeto(opt.outfn, header=hdr, append=True)
    print('Wrote', opt.outfn)

    print('Finished forced phot:', Time()-t0)
    return 0
Example #30
0
            fluxiv = [[] for i in range(len(B))]
            mjd = [[] for i in range(len(B))]

            J = np.flatnonzero((T.brickname == brick) * (T.filter == band))
            print(len(J), 'in brick', brick, 'band', band)
            if len(J) == 0:
                continue
            for j in J:
                i = tmap[T.srcid[j]]
                flux[i].append(T.flux[j])
                fluxiv[i].append(T.flux_ivar[j])
                mjd[i].append(T.mjd[j])

            nmax = max([len(lst) for lst in flux])
            print('Band:', band, 'Nmax:', nmax)
            if nmax == 0:
                continue
            for flist, col, dt in [
                (flux, 'forced_flux_%s' % band, np.float32),
                (fluxiv, 'forced_flux_ivar_%s' % band, np.float32),
                (mjd, 'forced_mjd_%s' % band, np.float64),
            ]:
                arr = np.zeros((len(B), nmax), dt)
                for i, f in enumerate(flist):
                    arr[i, :len(f)] = f
                B.set(col, arr)

        outfn = os.path.join('fsweep', brick[:3], 'tractor-%s.fits' % brick)
        trymakedirs(outfn, dir=True)
        B.writeto(outfn)
Example #31
0
def main(survey=None, opt=None):

    print(' '.join(sys.argv))
    '''Driver function for forced photometry of individual Legacy
    Survey images.
    '''
    if opt is None:
        parser = get_parser()
        opt = parser.parse_args()

    Time.add_measurement(MemMeas)
    t0 = tlast = Time()

    if opt.skip and os.path.exists(opt.outfn):
        print('Ouput file exists:', opt.outfn)
        sys.exit(0)

    if opt.derivs and opt.agn:
        print('Sorry, can\'t do --derivs AND --agn')
        sys.exit(0)

    if not opt.forced:
        opt.apphot = True

    zoomslice = None
    if opt.zoom is not None:
        (x0, x1, y0, y1) = opt.zoom
        zoomslice = (slice(y0, y1), slice(x0, x1))

    ps = None
    if opt.plots is not None:
        from astrometry.util.plotutils import PlotSequence
        ps = PlotSequence(opt.plots)

    # Try parsing first arg as exposure number (otherwise, it's a filename)
    try:
        expnum = int(opt.expnum)
        filename = None
    except:
        # make this 'None' for survey.find_ccds()
        expnum = None
        filename = opt.expnum

    # Try parsing HDU: "all" or HDU name or HDU number.
    all_hdus = (opt.ccdname == 'all')
    hdu = -1
    ccdname = None
    if not all_hdus:
        try:
            hdu = int(opt.ccdname)
        except:
            ccdname = opt.ccdname

    if survey is None:
        survey = LegacySurveyData(survey_dir=opt.survey_dir)

    catsurvey_north = survey
    catsurvey_south = None

    if opt.catalog_dir_north is not None:
        assert (opt.catalog_dir_south is not None)
        assert (opt.catalog_resolve_dec_ngc is not None)
        catsurvey_north = LegacySurveyData(survey_dir=opt.catalog_dir_north)
        catsurvey_south = LegacySurveyData(survey_dir=opt.catalog_dir_south)

    if opt.catalog_dir is not None:
        catsurvey_north = LegacySurveyData(survey_dir=opt.catalog_dir)

    if filename is not None and hdu >= 0:
        # FIXME -- try looking up in CCDs file?
        # Read metadata from file
        print('Warning: faking metadata from file contents')
        T = exposure_metadata([filename], hdus=[hdu])
        print('Metadata:')
        T.about()

        if not 'ccdzpt' in T.columns():
            phdr = fitsio.read_header(filename)
            T.ccdzpt = np.array([phdr['MAGZERO']])
            print('WARNING: using header MAGZERO')
            T.ccdraoff = np.array([0.])
            T.ccddecoff = np.array([0.])
            print('WARNING: setting CCDRAOFF, CCDDECOFF to zero.')

    else:
        # Read metadata from survey-ccds.fits table
        T = survey.find_ccds(expnum=expnum, ccdname=ccdname)
        print(len(T), 'with expnum', expnum, 'and ccdname', ccdname)
        if hdu >= 0:
            T.cut(T.image_hdu == hdu)
            print(len(T), 'with HDU', hdu)
        if filename is not None:
            T.cut(np.array([f.strip() == filename for f in T.image_filename]))
            print(len(T), 'with filename', filename)
        if opt.camera is not None:
            T.cut(T.camera == opt.camera)
            print(len(T), 'with camera', opt.camera)
        if not all_hdus:
            assert (len(T) == 1)

    args = []
    for ccd in T:
        args.append((survey, catsurvey_north, catsurvey_south,
                     opt.catalog_resolve_dec_ngc, ccd, opt, zoomslice, ps))

    if opt.threads:
        from astrometry.util.multiproc import multiproc
        from astrometry.util.timingpool import TimingPool, TimingPoolMeas
        pool = TimingPool(opt.threads)
        poolmeas = TimingPoolMeas(pool, pickleTraffic=False)
        Time.add_measurement(poolmeas)
        mp = multiproc(None, pool=pool)
        tm = Time()
        FF = mp.map(bounce_one_ccd, args)
        print('Multi-processing forced-phot:', Time() - tm)
    else:
        FF = map(bounce_one_ccd, args)

    FF = [F for F in FF if F is not None]
    if len(FF) == 0:
        print('No photometry results to write.')
        return 0
    # Keep only the first header
    _, version_hdr = FF[0]
    FF = [F for F, hdr in FF]
    F = merge_tables(FF)

    if all_hdus:
        version_hdr.delete('CPHDU')
        version_hdr.delete('CCDNAME')

    units = {
        'exptime': 'sec',
        'flux': 'nanomaggy',
        'flux_ivar': '1/nanomaggy^2',
        'apflux': 'nanomaggy',
        'apflux_ivar': '1/nanomaggy^2',
        'psfdepth': '1/nanomaggy^2',
        'galdepth': '1/nanomaggy^2',
        'sky': 'nanomaggy/arcsec^2',
        'psfsize': 'arcsec'
    }
    if opt.derivs:
        units.update({
            'dra': 'arcsec',
            'ddec': 'arcsec',
            'dra_ivar': '1/arcsec^2',
            'ddec_ivar': '1/arcsec^2'
        })

    columns = F.get_columns()
    order = [
        'release', 'brickid', 'brickname', 'objid', 'camera', 'expnum',
        'ccdname', 'filter', 'mjd', 'exptime', 'psfsize', 'ccd_cuts',
        'airmass', 'sky', 'psfdepth', 'galdepth', 'ra', 'dec', 'flux',
        'flux_ivar', 'fracflux', 'rchisq', 'fracmasked', 'apflux',
        'apflux_ivar', 'x', 'y', 'dqmask', 'dra', 'ddec', 'dra_ivar',
        'ddec_ivar'
    ]
    columns = [c for c in order if c in columns]

    # Set units headers (must happen after column ordering is set!)
    hdr = fitsio.FITSHDR()
    for i, col in enumerate(columns):
        if col in units:
            hdr.add_record(dict(name='TUNIT%i' % (i + 1), value=units[col]))

    outdir = os.path.dirname(opt.outfn)
    if len(outdir):
        trymakedirs(outdir)
    tmpfn = os.path.join(outdir, 'tmp-' + os.path.basename(opt.outfn))
    fitsio.write(tmpfn, None, header=version_hdr, clobber=True)
    F.writeto(tmpfn, header=hdr, append=True, columns=columns)
    os.rename(tmpfn, opt.outfn)
    print('Wrote', opt.outfn)

    tnow = Time()
    print('Total:', tnow - t0)
    return 0
Example #32
0
def render_fake_image(expnum, ccdname, decals_out_dir):
    decals = Decals()
    ccds = decals.find_ccds(expnum=expnum, ccdname=ccdname)
    ccd = ccds[0]
    band = ccd.filter
    im = decals.get_image_object(ccd)
    print('Read', im)

    tim = im.get_tractor_image(gaussPsf=True, nanomaggies=False, subsky=False)
    tim.wcs = NullWCS()

    H, W = im.shape

    s0 = 4.

    dsdy = 1. / 2000.

    x0 = W / 2.
    y0 = H / 2.

    ny = 21
    nx = 11

    # Lay down a grid of point sources, where the PSF is varying in width as a
    # function of Y position.
    yy = np.linspace(0., H, ny + 1)
    xx = np.linspace(0., W, nx + 1)
    # center of cells
    yy = yy[:-1] + (yy[1] - yy[0]) / 2.
    xx = xx[:-1] + (xx[1] - xx[0]) / 2.

    modimg = np.zeros_like(tim.getImage())

    flux = NanoMaggies.magToNanomaggies(16.)
    star = PointSource(PixPos(0., 0.), NanoMaggies(**{band: flux}))

    for y in yy:
        for x in xx:
            print('Rendering star at', x, y)
            s = s0 + dsdy * (y - y0)
            psf = NCircularGaussianPSF([s], [1.])
            tim.psf = psf
            star.pos.x = x
            star.pos.y = y
            mod = star.getModelPatch(tim)
            mod.addTo(modimg)

    np.random.seed(42)
    noise = np.random.normal(size=modimg.shape)
    ie = tim.getInvError()
    noise /= ie
    noise[ie == 0] = 0
    modimg += noise

    #
    imagedir = os.path.join(decals_out_dir, 'images', 'decam')
    trymakedirs(imagedir)
    imagefn = os.path.join(imagedir,
                           os.path.basename(
                               ccd.image_filename.strip())).replace(
                                   '.fits.fz', '.fits')

    primhdr = im.read_image_primary_header()
    hdr = im.read_image_header()

    extname = hdr['EXTNAME']

    import fitsio
    fitsio.write(imagefn, None, header=primhdr, clobber=True)
    fitsio.write(imagefn, modimg, header=hdr, extname=extname, clobber=False)
    print('Wrote', imagefn)

    dq = im.read_dq()
    dqfn = imagefn.replace('_ooi_', '_ood_')
    fitsio.write(dqfn, None, header=primhdr, clobber=True)
    fitsio.write(dqfn, dq, header=hdr, clobber=False)
    print('Wrote', dqfn)

    iv = im.read_invvar()
    wtfn = imagefn.replace('_ooi_', '_oow_')
    fitsio.write(wtfn, None, header=primhdr, clobber=True)
    fitsio.write(wtfn, iv, header=hdr, clobber=False)
    print('Wrote', wtfn)

    # cmd = 'ln -s %s %s' % (im.dqfn, dqfn)
    # print cmd
    # os.system(cmd)
    #
    # cmd = 'ln -s %s %s' % (im.wtfn, wtfn)
    # print cmd
    # os.system(cmd)

    ccds.image_filename = np.array(['decam/' + os.path.basename(imagefn)])
    ccds.image_hdu[0] = 1
    ccdfn = os.path.join(decals_out_dir, 'decals-ccds.fits')
    ccds.writeto(ccdfn)
    print('Wrote', ccdfn)

    cal = os.path.join(decals_out_dir, 'calib')
    trymakedirs(cal)

    for path in ['decals-bricks.fits', 'calib/se-config']:
        pathnm = os.path.join(decals_out_dir, path)
        if os.path.exists(pathnm):
            continue
        cmd = 'ln -s %s/%s %s' % (decals.get_decals_dir(), path, pathnm)
        print(cmd)
        os.system(cmd)
Example #33
0
def main():
    import argparse

    parser = argparse.ArgumentParser(
        description='This script creates small self-contained data sets that '
        'are useful for test cases of the pipeline codes.')

    parser.add_argument('ccds', help='CCDs table describing region to grab')
    parser.add_argument('outdir', help='Output directory name')
    parser.add_argument('brick', help='Brick containing these images')

    parser.add_argument('--survey-dir', type=str, default=None)
    parser.add_argument('--cache-dir', type=str, default=None,
                        help='Directory to search for cached files')
    parser.add_argument('--wise', help='For WISE outputs, give the path to a WCS file describing the sub-brick region of interest, eg, a coadd image')
    parser.add_argument('--wise-wcs-hdu', help='For WISE outputs, the HDU to read the WCS from in the file given by --wise.', type=int, default=0)
    parser.add_argument('--fpack', action='store_true', default=False)
    parser.add_argument('--gzip', action='store_true', default=False)
    parser.add_argument('--pad', action='store_true', default=False,
                        help='Keep original image size, but zero out pixels outside ROI')
    
    args = parser.parse_args()

    v = 'SKY_TEMPLATE_DIR'
    if v in os.environ:
        del os.environ[v]

    C = fits_table(args.ccds)
    print(len(C), 'CCDs in', args.ccds)
    C.camera = np.array([c.strip() for c in C.camera])
    
    survey = LegacySurveyData(cache_dir=args.cache_dir, survey_dir=args.survey_dir)

    if ',' in args.brick:
        ra,dec = args.brick.split(',')
        ra = float(ra)
        dec = float(dec)
        fakebricks = fits_table()
        fakebricks.brickname = np.array([('custom-%06i%s%05i' %
                                          (int(1000*ra), 'm' if dec < 0 else 'p',
                                           int(1000*np.abs(dec))))])
        fakebricks.ra  = np.array([ra])
        fakebricks.dec = np.array([dec])
        bricks = fakebricks
        outbricks = bricks
    else:
        bricks = survey.get_bricks_readonly()
        outbricks = bricks[np.array([n == args.brick for n in bricks.brickname])]
        assert(len(outbricks) == 1)

    outsurvey = LegacySurveyData(survey_dir = args.outdir)
    trymakedirs(args.outdir)
    outbricks.writeto(os.path.join(args.outdir, 'survey-bricks.fits.gz'))

    targetwcs = wcs_for_brick(outbricks[0])
    H,W = targetwcs.shape

    tycho2fn = survey.find_file('tycho2')
    kd = tree_open(tycho2fn, 'stars')
    radius = 1.
    rc,dc = targetwcs.radec_center()
    I = tree_search_radec(kd, rc, dc, radius)
    print(len(I), 'Tycho-2 stars within', radius, 'deg of RA,Dec (%.3f, %.3f)' % (rc,dc))
    # Read only the rows within range.
    tycho = fits_table(tycho2fn, rows=I)
    del kd
    print('Read', len(tycho), 'Tycho-2 stars')
    ok,tx,ty = targetwcs.radec2pixelxy(tycho.ra, tycho.dec)
    #margin = 100
    #tycho.cut(ok * (tx > -margin) * (tx < W+margin) *
    #          (ty > -margin) * (ty < H+margin))
    print('Cut to', len(tycho), 'Tycho-2 stars within brick')
    del ok,tx,ty
    #tycho.writeto(os.path.join(args.outdir, 'tycho2.fits.gz'))
    f,tfn = tempfile.mkstemp(suffix='.fits')
    os.close(f)
    tycho.writeto(tfn)
    outfn = os.path.join(args.outdir, 'tycho2.kd.fits')
    cmd = 'startree -i %s -o %s -P -k -n stars -T' % (tfn, outfn)
    print(cmd)
    rtn = os.system(cmd)
    assert(rtn == 0)
    os.unlink(tfn)

    from legacypipe.gaiacat import GaiaCatalog
    gcat = GaiaCatalog()
    # from ps1cat.py:
    wcs = targetwcs
    step=100.
    margin=10.
    # Grid the CCD in pixel space
    W,H = wcs.get_width(), wcs.get_height()
    xx,yy = np.meshgrid(
        np.linspace(1-margin, W+margin, 2+int((W+2*margin)/step)),
        np.linspace(1-margin, H+margin, 2+int((H+2*margin)/step)))
    # Convert to RA,Dec and then to unique healpixes
    ra,dec = wcs.pixelxy2radec(xx.ravel(), yy.ravel())
    healpixes = set()
    for r,d in zip(ra,dec):
        healpixes.add(gcat.healpix_for_radec(r, d))
    for hp in healpixes:
        hpcat = gcat.get_healpix_catalog(hp)
        ok,xx,yy = wcs.radec2pixelxy(hpcat.ra, hpcat.dec)
        onccd = np.flatnonzero((xx >= 1.-margin) * (xx <= W+margin) *
                               (yy >= 1.-margin) * (yy <= H+margin))
        hpcat.cut(onccd)
        if len(hpcat):
            outfn = os.path.join(args.outdir, 'gaia', 'chunk-%05d.fits' % hp)
            trymakedirs(os.path.join(args.outdir, 'gaia'))
            hpcat.writeto(outfn)
    
    outccds = C.copy()
    cols = outccds.get_columns()
    for c in ['ccd_x0', 'ccd_x1', 'ccd_y0', 'ccd_y1',
              'brick_x0', 'brick_x1', 'brick_y0', 'brick_y1',
              'skyver', 'wcsver', 'psfver', 'skyplver', 'wcsplver',
              'psfplver' ]:
        if c in cols:
            outccds.delete_column(c)
    outccds.image_hdu[:] = 1

    # Convert to list to avoid truncating filenames
    outccds.image_filename = [fn for fn in outccds.image_filename]
    
    for iccd,ccd in enumerate(C):

        decam = (ccd.camera.strip() == 'decam')
        bok   = (ccd.camera.strip() == '90prime')

        im = survey.get_image_object(ccd)
        print('Got', im)
        if survey.cache_dir is not None:
            im.check_for_cached_files(survey)
        slc = (slice(ccd.ccd_y0, ccd.ccd_y1), slice(ccd.ccd_x0, ccd.ccd_x1))

        psfkwargs = dict(pixPsf=True, gaussPsf=False, hybridPsf=False,
                         normalizePsf=False)

        tim = im.get_tractor_image(slc, pixPsf=True,
                                   subsky=False, nanomaggies=False,
                                   no_remap_invvar=True, old_calibs_ok=True)
        print('Tim:', tim.shape)

        psfrow = psfhdr = None

        if args.pad:
            psf = im.read_psf_model(0, 0, w=im.width, h=im.height, **psfkwargs)
            psfex = psf.psfex
        else:
            psf = tim.getPsf()
            psfex = psf.psfex

            # Did the PSF model come from a merged file?
            for fn in [im.merged_psffn, im.psffn] + im.old_merged_psffns:
                if not os.path.exists(fn):
                    continue
                T = fits_table(fn)
                I, = np.nonzero((T.expnum == im.expnum) *
                                np.array([c.strip() == im.ccdname for c in T.ccdname]))
                if len(I) != 1:
                    continue
                psfrow = T[I]
                x0 = ccd.ccd_x0
                y0 = ccd.ccd_y0
                psfrow.polzero1[0] -= x0
                psfrow.polzero2[0] -= y0
                #psfhdr = fitsio.read_header(im.merged_psffn)
                break
        psfex.fwhm = tim.psf_fwhm

        #### HACK
        #psfrow = None
        assert(psfrow is not None)
        if psfrow is not None:
            print('PSF row:', psfrow)
        #else:
        #    print('PSF:', psf)
        #    print('PsfEx:', psfex)

        skyrow = skyhdr = None

        if args.pad:
            primhdr = fitsio.read_header(im.imgfn)
            imghdr = fitsio.read_header(im.imgfn, hdu=im.hdu)

            sky = im.read_sky_model(splinesky=True, primhdr=primhdr, imghdr=imghdr)
            #skyhdr = fitsio.read_header(im.splineskyfn)
            #msky = im.read_merged_splinesky_model(slc=slc, old_calibs_ok=True)
        else:
            sky = tim.getSky()

            # Did the sky model come from a merged file?
            #msky = im.read_merged_splinesky_model(slc=slc, old_calibs_ok=True)

        print('merged skyfn:', im.merged_skyfn)
        print('single skyfn:', im.skyfn)
        print('old merged skyfns:', im.old_merged_skyfns)

        for fn in [im.merged_skyfn, im.skyfn] + im.old_merged_skyfns:
            if not os.path.exists(fn):
                continue
            T = fits_table(fn)
            I, = np.nonzero((T.expnum == im.expnum) *
                            np.array([c.strip() == im.ccdname for c in T.ccdname]))
            skyrow = T[I]
            skyrow.x0[0] = ccd.ccd_x0
            skyrow.y0[0] = ccd.ccd_y0
            # s_med = skyrow.sky_med[0]
            # s_john = skyrow.sky_john[0]
            # skyhdr = fitsio.read_header(fn)

        assert(skyrow is not None)
        ### HACK
        #skyrow = None
                
        if skyrow is not None:
            print('Sky row:', skyrow)
        else:
            print('Sky:', sky)


        # Output filename format:
        fn = ccd.image_filename.strip()
        ccd.image_filename = os.path.join(os.path.dirname(fn),
                                          '%s.%s.fits' % (os.path.basename(fn).split('.')[0], ccd.ccdname.strip()))
        outim = outsurvey.get_image_object(ccd)
        print('Output image:', outim)
        
        print('Image filename:', outim.imgfn)
        trymakedirs(outim.imgfn, dir=True)

        imgdata = tim.getImage()
        ivdata = tim.getInvvar()

        # Since we remap DQ codes (always with Mosaic and Bok, sometimes with DECam),
        # re-read from the FITS file rather than using tim.dq.
        print('Reading data quality from', im.dqfn, 'hdu', im.hdu)
        dqdata = im._read_fits(im.dqfn, im.hdu, slice=tim.slice)

        print('Tim shape:', tim.shape, 'Slice', tim.slice)
        print('image shape:', imgdata.shape, 'iv', ivdata.shape, 'DQ', dqdata.shape)

        from collections import Counter
        dqvals = Counter(dqdata.ravel())
        print('DQ pixel counts:')
        for k,n in dqvals.most_common():
            print('  0x%x' % k, ':', n)

        if args.pad:
            # Create zero image of full size, copy in data.
            fullsize = np.zeros((ccd.height, ccd.width), imgdata.dtype)
            fullsize[slc] = imgdata
            imgdata = fullsize

            fullsize = np.zeros((ccd.height, ccd.width), dqdata.dtype)
            fullsize[slc] = dqdata
            dqdata = fullsize

            fullsize = np.zeros((ccd.height, ccd.width), ivdata.dtype)
            fullsize[slc] = ivdata
            ivdata = fullsize
            
        else:
            # Adjust the header WCS by x0,y0
            crpix1 = tim.hdr['CRPIX1']
            crpix2 = tim.hdr['CRPIX2']
            tim.hdr['CRPIX1'] = crpix1 - ccd.ccd_x0
            tim.hdr['CRPIX2'] = crpix2 - ccd.ccd_y0

        # Add image extension to filename
        # fitsio doesn't compress .fz by default, so drop .fz suffix
        
        #outim.imgfn = outim.imgfn.replace('.fits', '-%s.fits' % im.ccdname)
        if not args.fpack:
            outim.imgfn = outim.imgfn.replace('.fits.fz', '.fits')
        if args.gzip:
            outim.imgfn = outim.imgfn.replace('.fits', '.fits.gz')

        #outim.wtfn  = outim.wtfn.replace('.fits', '-%s.fits' % im.ccdname)
        if not args.fpack:
            outim.wtfn  = outim.wtfn.replace('.fits.fz', '.fits')
        if args.gzip:
            outim.wtfn = outim.wtfn.replace('.fits', '.fits.gz')

        if outim.dqfn is not None:
            #outim.dqfn  = outim.dqfn.replace('.fits', '-%s.fits' % im.ccdname)
            if not args.fpack:
                outim.dqfn  = outim.dqfn.replace('.fits.fz', '.fits')
            if args.gzip:
                outim.dqfn = outim.dqfn.replace('.fits', '.fits.gz')

        if bok:
            outim.psffn = outim.psffn.replace('.psf', '-%s.psf' % im.ccdname)

        ccdfn = outim.imgfn
        ccdfn = ccdfn.replace(outsurvey.get_image_dir(), '')
        if ccdfn.startswith('/'):
            ccdfn = ccdfn[1:]
        outccds.image_filename[iccd] = ccdfn

        print('Changed output filenames to:')
        print(outim.imgfn)
        print(outim.dqfn)

        ofn = outim.imgfn
        if args.fpack:
            f,ofn = tempfile.mkstemp(suffix='.fits')
            os.close(f)
        fits = fitsio.FITS(ofn, 'rw', clobber=True)
        fits.write(None, header=tim.primhdr)
        fits.write(imgdata, header=tim.hdr, extname=ccd.ccdname)
        fits.close()

        if args.fpack:
            cmd = 'fpack -qz 8 -S %s > %s && rm %s' % (ofn, outim.imgfn, ofn)
            print('Running:', cmd)
            rtn = os.system(cmd)
            assert(rtn == 0)

        h,w = tim.shape
        if not args.pad:
            outccds.width[iccd] = w
            outccds.height[iccd] = h
            outccds.crpix1[iccd] = crpix1 - ccd.ccd_x0
            outccds.crpix2[iccd] = crpix2 - ccd.ccd_y0

        wcs = Tan(*[float(x) for x in
                    [ccd.crval1, ccd.crval2, ccd.crpix1, ccd.crpix2,
                     ccd.cd1_1, ccd.cd1_2, ccd.cd2_1, ccd.cd2_2, ccd.width, ccd.height]])

        if args.pad:
            subwcs = wcs
        else:
            subwcs = wcs.get_subimage(ccd.ccd_x0, ccd.ccd_y0, w, h)
            outccds.ra[iccd],outccds.dec[iccd] = subwcs.radec_center()

        print('Weight filename:', outim.wtfn)
        wfn = outim.wtfn
        trymakedirs(wfn, dir=True)

        ofn = wfn
        if args.fpack:
            f,ofn = tempfile.mkstemp(suffix='.fits')
            os.close(f)

        fits = fitsio.FITS(ofn, 'rw', clobber=True)
        fits.write(None, header=tim.primhdr)
        fits.write(ivdata, header=tim.hdr, extname=ccd.ccdname)
        fits.close()

        if args.fpack:
            cmd = 'fpack -qz 8 -S %s > %s && rm %s' % (ofn, wfn, ofn)
            print('Running:', cmd)
            rtn = os.system(cmd)
            assert(rtn == 0)

        if outim.dqfn is not None:
            print('DQ filename', outim.dqfn)
            trymakedirs(outim.dqfn, dir=True)

            ofn = outim.dqfn
            if args.fpack:
                f,ofn = tempfile.mkstemp(suffix='.fits')
                os.close(f)

            fits = fitsio.FITS(ofn, 'rw', clobber=True)
            fits.write(None, header=tim.primhdr)
            fits.write(dqdata, header=tim.hdr, extname=ccd.ccdname)
            fits.close()

            if args.fpack:
                cmd = 'fpack -g -q 0 -S %s > %s && rm %s' % (ofn, outim.dqfn, ofn)
                print('Running:', cmd)
                rtn = os.system(cmd)
                assert(rtn == 0)

        psfout = outim.psffn
        #if psfrow:
        #    psfout = outim.merged_psffn
        print('PSF output filename:', psfout)
        trymakedirs(psfout, dir=True)
        if psfrow:
            psfrow.writeto(psfout, primhdr=psfhdr)
        else:
            print('Writing PsfEx:', psfout)
            psfex.writeto(psfout)
            # update header
            F = fitsio.FITS(psfout, 'rw')
            F[0].write_keys([dict(name='EXPNUM', value=ccd.expnum),
                             dict(name='PLVER',  value=psf.plver),
                             dict(name='PROCDATE', value=psf.procdate),
                             dict(name='PLPROCID', value=psf.plprocid),])
            F.close()

        skyout = outim.skyfn
        #if skyrow:
        #    skyout = outim.merged_splineskyfn

        print('Sky output filename:', skyout)
        trymakedirs(skyout, dir=True)
        if skyrow is not None:
            skyrow.writeto(skyout, primhdr=skyhdr)
        else:
            primhdr = fitsio.FITSHDR()
            primhdr['PLVER'] = sky.plver
            primhdr['PLPROCID'] = sky.plprocid
            primhdr['PROCDATE'] = sky.procdate
            primhdr['EXPNUM'] = ccd.expnum
            primhdr['IMGDSUM'] = sky.datasum
            primhdr['S_MED'] = s_med
            primhdr['S_JOHN'] = s_john
            sky.write_fits(skyout, primhdr=primhdr)

        # HACK -- check result immediately.
        outccds.writeto(os.path.join(args.outdir, 'survey-ccds-1.fits.gz'))
        outsurvey.ccds = None
        outC = outsurvey.get_ccds_readonly()
        occd = outC[iccd]
        outim = outsurvey.get_image_object(occd)
        print('Got output image:', outim)
        otim = outim.get_tractor_image(pixPsf=True,
                                       hybridPsf=True, old_calibs_ok=True)
        print('Got output tim:', otim)

    outccds.writeto(os.path.join(args.outdir, 'survey-ccds-1.fits.gz'))

    # WISE
    if args.wise is not None:
        from wise.forcedphot import unwise_tiles_touching_wcs
        from wise.unwise import (unwise_tile_wcs, unwise_tiles_touching_wcs,
                                 get_unwise_tractor_image, get_unwise_tile_dir)
        # Read WCS...
        print('Reading TAN wcs header from', args.wise, 'HDU', args.wise_wcs_hdu)
        targetwcs = Tan(args.wise, args.wise_wcs_hdu)
        tiles = unwise_tiles_touching_wcs(targetwcs)
        print('Cut to', len(tiles), 'unWISE tiles')
        H,W = targetwcs.shape
        r,d = targetwcs.pixelxy2radec(np.array([1,   W,   W/2, W/2]),
                                      np.array([H/2, H/2, 1,   H  ]))
        roiradec = [r[0], r[1], d[2], d[3]]

        unwise_dir = os.environ['UNWISE_COADDS_DIR']
        wise_out = os.path.join(args.outdir, 'images', 'unwise')
        print('Will write WISE outputs to', wise_out)

        unwise_tr_dir = os.environ['UNWISE_COADDS_TIMERESOLVED_DIR']
        wise_tr_out = os.path.join(args.outdir, 'images', 'unwise-tr')
        print('Will write WISE time-resolved outputs to', wise_tr_out)
        trymakedirs(wise_tr_out)

        W = fits_table(os.path.join(unwise_tr_dir, 'time_resolved_atlas.fits'))
        print('Read', len(W), 'time-resolved WISE coadd tiles')
        W.cut(np.array([t in tiles.coadd_id for t in W.coadd_id]))
        print('Cut to', len(W), 'time-resolved vs', len(tiles), 'full-depth')

        # Write the time-resolved index subset.
        W.writeto(os.path.join(wise_tr_out, 'time_resolved_atlas.fits'))

        # this ought to be enough for anyone =)
        _,Nepochs = W.epoch_bitmask.shape
        print('N epochs in time-resolved atlas:', Nepochs)

        wisedata = []

        # full depth
        for band in [1,2,3,4]:
            wisedata.append((unwise_dir, wise_out, tiles.coadd_id, band, True))

        # time-resolved
        for band in [1,2]:
            # W1 is bit 0 (value 0x1), W2 is bit 1 (value 0x2)
            bitmask = (1 << (band-1))
            for e in range(Nepochs):
                # Which tiles have images for this epoch?
                I = np.flatnonzero(W.epoch_bitmask[:,e] & bitmask)
                if len(I) == 0:
                    continue
                print('Epoch %i: %i tiles:' % (e, len(I)), W.coadd_id[I])
                edir = os.path.join(unwise_tr_dir, 'e%03i' % e)
                eoutdir = os.path.join(wise_tr_out, 'e%03i' % e)
                wisedata.append((edir, eoutdir, tiles.coadd_id[I], band, False))

        wrote_masks = set()

        model_dir = os.environ.get('UNWISE_MODEL_SKY_DIR')
        if model_dir is not None:
            model_dir_out = os.path.join(args.outdir, 'images', 'unwise-mod')
            trymakedirs(model_dir_out)

        for indir, outdir, tiles, band, fulldepth in wisedata:
            for tile in tiles:
                wanyband = 'w'
                tim = get_unwise_tractor_image(indir, tile, band,
                                               bandname=wanyband, roiradecbox=roiradec)
                print('Got unWISE tim', tim)
                print(tim.shape)

                if model_dir is not None and fulldepth and band in [1,2]:
                    print('ROI', tim.roi)
                    #0387p575.1.mod.fits
                    fn = '%s.%i.mod.fits' % (tile, band)
                    print('Filename', fn)
                    F = fitsio.FITS(os.path.join(model_dir, fn))
                    x0,x1,y0,y1 = tim.roi
                    slc = slice(y0,y1),slice(x0,x1)

                    phdr = F[0].read_header()

                    outfn = os.path.join(model_dir_out, fn)
                    for e,extname in [(1,'MODEL'), (2,'SKY')]:
                        pix = F[e][slc]
                        hdr = F[e].read_header()
                        crpix1 = hdr['CRPIX1']
                        crpix2 = hdr['CRPIX2']
                        hdr['CRPIX1'] -= x0
                        hdr['CRPIX2'] -= y0
                        #print('mod', mod)
                        #print('Model', mod.shape)
                        if e == 1:
                            fitsio.write(outfn, None, clobber=True, header=phdr)
                        fitsio.write(outfn, pix, header=hdr, extname=extname)
                    print('Wrote', outfn)

                thisdir = get_unwise_tile_dir(outdir, tile)
                print('Directory for this WISE tile:', thisdir)
                base = os.path.join(thisdir, 'unwise-%s-w%i-' % (tile, band))
                print('Base filename:', base)

                masked = True
                mu = 'm' if masked else 'u'

                imfn = base + 'img-%s.fits'       % mu
                ivfn = base + 'invvar-%s.fits.gz' % mu
                nifn = base + 'n-%s.fits.gz'      % mu
                nufn = base + 'n-u.fits.gz'

                #print('WISE image header:', tim.hdr)

                # Adjust the header WCS by x0,y0
                wcs = tim.wcs.wcs
                tim.hdr['CRPIX1'] = wcs.crpix[0]
                tim.hdr['CRPIX2'] = wcs.crpix[1]

                H,W = tim.shape
                tim.hdr['IMAGEW'] = W
                tim.hdr['IMAGEH'] = H

                print('WCS:', wcs)
                print('Header CRPIX', tim.hdr['CRPIX1'], tim.hdr['CRPIX2'])

                trymakedirs(imfn, dir=True)
                fitsio.write(imfn, tim.getImage(), header=tim.hdr, clobber=True)
                print('Wrote', imfn)
                fitsio.write(ivfn, tim.getInvvar(), header=tim.hdr, clobber=True)
                print('Wrote', ivfn)
                fitsio.write(nifn, tim.nims, header=tim.hdr, clobber=True)
                print('Wrote', nifn)
                fitsio.write(nufn, tim.nuims, header=tim.hdr, clobber=True)
                print('Wrote', nufn)

                if not (indir,tile) in wrote_masks:
                    print('Looking for mask file for', indir, tile)
                    # record that we tried this dir/tile combo
                    wrote_masks.add((indir,tile))
                    for idir in indir.split(':'):
                        tdir = get_unwise_tile_dir(idir, tile)
                        maskfn = 'unwise-%s-msk.fits.gz' % tile
                        fn = os.path.join(tdir, maskfn)
                        print('Mask file:', fn)
                        if os.path.exists(fn):
                            print('Reading', fn)
                            (x0,x1,y0,y1) = tim.roi
                            roislice = (slice(y0,y1), slice(x0,x1))
                            F = fitsio.FITS(fn)[0]
                            hdr = F.read_header()
                            M = F[roislice]
                            outfn = os.path.join(thisdir, maskfn)
                            fitsio.write(outfn, M, header=tim.hdr, clobber=True)
                            print('Wrote', outfn)
                            break

    outC = outsurvey.get_ccds_readonly()
    for iccd,ccd in enumerate(outC):
        outim = outsurvey.get_image_object(ccd)
        print('Got output image:', outim)
        otim = outim.get_tractor_image(pixPsf=True,
                                       hybridPsf=True, old_calibs_ok=True)
        print('Got output tim:', otim)
Example #34
0
    def run_calibs(self, psfex=True, sky=True, se=False,
                   funpack=False, fcopy=False, use_mask=True,
                   force=False, just_check=False, git_version=None,
                   splinesky=False):

        '''
        Run calibration pre-processing steps.

        Parameters
        ----------
        just_check: boolean
            If True, returns True if calibs need to be run.
        '''
        from .survey import (create_temp, get_version_header,
                             get_git_version)
        
        if psfex and os.path.exists(self.psffn) and (not force):
            if self.check_psf(self.psffn):
                psfex = False
        if psfex:
            se = True
            
        if se and os.path.exists(self.sefn) and (not force):
            if self.check_se_cat(self.sefn):
                se = False
        if se:
            funpack = True

        if sky and (not force) and (
            (os.path.exists(self.skyfn) and not splinesky) or
            (os.path.exists(self.splineskyfn) and splinesky)):
            fn = self.skyfn
            if splinesky:
                fn = self.splineskyfn

            if os.path.exists(fn):
                try:
                    hdr = fitsio.read_header(fn)
                except:
                    print('Failed to read sky file', fn, '-- deleting')
                    os.unlink(fn)
            if os.path.exists(fn):
                print('File', fn, 'exists -- skipping')
                sky = False

        if just_check:
            return (se or psfex or sky)

        todelete = []
        if funpack:
            # The image & mask files to process (funpacked if necessary)
            imgfn,maskfn = self.funpack_files(self.imgfn, self.dqfn, self.hdu, todelete)
        else:
            imgfn,maskfn = self.imgfn,self.dqfn
    
        if se:
            self.run_se('DECaLS', imgfn, maskfn)
        if psfex:
            self.run_psfex('DECaLS')

        if sky:
            #print('Fitting sky for', self)

            hdr = get_version_header(None, self.survey.get_survey_dir(),
                                     git_version=git_version)
            primhdr = self.read_image_primary_header()
            plver = primhdr.get('PLVER', '')
            hdr.delete('PROCTYPE')
            hdr.add_record(dict(name='PROCTYPE', value='ccd',
                                comment='NOAO processing type'))
            hdr.add_record(dict(name='PRODTYPE', value='skymodel',
                                comment='NOAO product type'))
            hdr.add_record(dict(name='PLVER', value=plver,
                                comment='CP ver of image file'))

            slc = self.get_good_image_slice(None)
            #print('Good image slice is', slc)

            img = self.read_image(slice=slc)
            wt = self.read_invvar(slice=slc)

            if splinesky:
                from tractor.splinesky import SplineSky
                from scipy.ndimage.morphology import binary_dilation

                boxsize = DecamImage.splinesky_boxsize
                
                # Start by subtracting the overall median
                med = np.median(img[wt>0])
                # Compute initial model...
                skyobj = SplineSky.BlantonMethod(img - med, wt>0, boxsize)
                skymod = np.zeros_like(img)
                skyobj.addTo(skymod)
                # Now mask bright objects in (image - initial sky model)
                sig1 = 1./np.sqrt(np.median(wt[wt>0]))
                masked = (img - med - skymod) > (5.*sig1)
                masked = binary_dilation(masked, iterations=3)
                masked[wt == 0] = True

                sig1b = 1./np.sqrt(np.median(wt[masked == False]))
                print('Sig1 vs sig1b:', sig1, sig1b)

                # Now find the final sky model using that more extensive mask
                skyobj = SplineSky.BlantonMethod(
                    img - med, np.logical_not(masked), boxsize)
                # add the overall median back in
                skyobj.offset(med)

                if slc is not None:
                    sy,sx = slc
                    y0 = sy.start
                    x0 = sx.start
                    skyobj.shift(-x0, -y0)

                hdr.add_record(dict(name='SIG1', value=sig1,
                                    comment='Median stdev of unmasked pixels'))
                hdr.add_record(dict(name='SIG1B', value=sig1,
                                    comment='Median stdev of unmasked pixels+'))
                    
                trymakedirs(self.splineskyfn, dir=True)
                skyobj.write_fits(self.splineskyfn, primhdr=hdr)
                print('Wrote sky model', self.splineskyfn)
    
            else:
                try:
                    skyval = estimate_mode(img[wt > 0], raiseOnWarn=True)
                    skymeth = 'mode'
                except:
                    skyval = np.median(img[wt > 0])
                    skymeth = 'median'
                tsky = ConstantSky(skyval)

                hdr.add_record(dict(name='SKYMETH', value=skymeth,
                                    comment='estimate_mode, or fallback to median?'))

                from scipy.ndimage.morphology import binary_dilation
                sig1 = 1./np.sqrt(np.median(wt[wt>0]))
                masked = (img - skyval) > (5.*sig1)
                masked = binary_dilation(masked, iterations=3)
                masked[wt == 0] = True
                sig1b = 1./np.sqrt(np.median(wt[masked == False]))
                print('Sig1 vs sig1b:', sig1, sig1b)

                hdr.add_record(dict(name='SIG1', value=sig1,
                                    comment='Median stdev of unmasked pixels'))
                hdr.add_record(dict(name='SIG1B', value=sig1,
                                    comment='Median stdev of unmasked pixels+'))
                
                trymakedirs(self.skyfn, dir=True)
                tsky.write_fits(self.skyfn, hdr=hdr)
                print('Wrote sky model', self.skyfn)

        for fn in todelete:
            os.unlink(fn)