def main(): import argparse parser = argparse.ArgumentParser() parser.add_argument('--plots', action='store_true') parser.add_argument('--brick', help='Brick name to run') parser.add_argument( '--input-dir', default='/global/projecta/projectdirs/cosmo/work/legacysurvey/dr7') #/global/cscratch1/sd/desiproc/dr7out') parser.add_argument('--survey-dir', default='/global/cscratch1/sd/dstn/dr7-depthcut') parser.add_argument('--output-dir', default='/global/cscratch1/sd/dstn/bright') opt = parser.parse_args() plots = opt.plots ps = PlotSequence('bright') brickname = opt.brick insurvey = LegacySurveyData(opt.input_dir, cache_dir=opt.survey_dir) outsurvey = LegacySurveyData(opt.output_dir, output_dir=opt.output_dir) bfn = insurvey.find_file('blobmap', brick=brickname) print('Found blob map', bfn) blobs = fitsio.read(bfn) h, w = blobs.shape brick = insurvey.get_brick_by_name(brickname) brickwcs = wcs_for_brick(brick) radius = np.sqrt(2.) * 0.25 * 1.01 neighbors = insurvey.get_bricks_near(brick.ra, brick.dec, radius) print(len(neighbors), 'bricks nearby') def showbool(X): d = downsample_max(X, 8) h, w = X.shape plt.imshow(d, interpolation='nearest', origin='lower', vmin=0, vmax=1, extent=[0, w, 0, h], cmap='gray') brightblobs = set() for nb in neighbors: if nb.brickname == brickname: # ignore myself! continue print('Neighbor:', nb.brickname) mfn = insurvey.find_file('maskbits', brick=nb.brickname) if not os.path.exists(mfn): print('No maskbits file:', mfn) continue maskbits = fitsio.read(mfn) bright = ((maskbits & MASKBITS['BRIGHT']) > 0) print(np.sum(bright > 0), 'BRIGHT pixels set') primary = (maskbits & MASKBITS['NPRIMARY'] == 0) print(np.sum(primary), 'PRIMARY pixels set') edge = binary_dilation(primary, structure=np.ones((3, 3), bool)) edge = edge * np.logical_not(primary) brightedge = edge & bright if plots: plt.clf() showbool(bright) plt.title('bright: brick %s' % nb.brickname) ps.savefig() # plt.clf() # showbool(primary) # plt.title('PRIMARY, brick %s' % nb.brickname) # ps.savefig() # # plt.clf() # showbool(edge) # plt.title('boundary, brick %s' % nb.brickname) # ps.savefig() plt.clf() showbool(brightedge) plt.title('bright at edge, brick %s' % nb.brickname) ps.savefig() nwcs = wcs_for_brick(nb) yy, xx = np.nonzero(brightedge) print(len(yy), 'bright edge pixels') if len(yy) == 0: continue rr, dd = nwcs.pixelxy2radec(xx + 1, yy + 1) print('RA range', rr.min(), rr.max(), 'vs brick', brick.ra1, brick.ra2) print('Dec range', dd.min(), dd.max(), 'vs brick', brick.dec1, brick.dec2) # Find pixels that are within this brick's unique area I, = np.nonzero((rr >= brick.ra1) * (rr <= brick.ra2) * (dd >= brick.dec1) * (dd <= brick.dec2)) if plots: plt.clf() plt.plot( [brick.ra1, brick.ra1, brick.ra2, brick.ra2, brick.ra1], [brick.dec1, brick.dec2, brick.dec2, brick.dec1, brick.dec1], 'b-') plt.plot(rr, dd, 'k.') plt.plot(rr[I], dd[I], 'r.') plt.title('Bright pixels from %s' % nb.brickname) ps.savefig() if len(I) == 0: print('No edge pixels touch') #plt.plot(br,bd, 'b-') continue #print('Edge pixels touch!') #plt.plot(br,bd, 'r-', zorder=20) ok, x, y = brickwcs.radec2pixelxy(rr[I], dd[I]) x = np.round(x).astype(int) - 1 y = np.round(y).astype(int) - 1 print('Pixel ranges X', x.min(), x.max(), 'Y', y.min(), y.max()) assert (np.all((x >= 0) * (x < w) * (y >= 0) * (y < h))) print('Adding blobs:', np.unique(blobs[y, x])) brightblobs.update(blobs[y, x]) print('Blobs touching bright pixels:', brightblobs) print() brightblobs.discard(-1) if len(brightblobs) == 0: print('No neighboring bright blobs to update!') return print('Updating', len(brightblobs), 'blobs:', brightblobs) tmap = np.zeros(blobs.max() + 2, bool) for b in brightblobs: tmap[b + 1] = True touching = tmap[blobs + 1] if plots: plt.clf() showbool(touching) plt.title('Blobs touching bright, brick %s' % brickname) ps.savefig() mfn = insurvey.find_file('maskbits', brick=brickname) maskbits, hdr = fitsio.read(mfn, header=True) updated = maskbits | (MASKBITS['BRIGHT'] * touching) if np.all(maskbits == updated): print('No bits updated! (Bright stars were already masked)') return maskbits = updated if plots: plt.clf() showbool((maskbits & MASKBITS['BRIGHT']) > 0) plt.title('New maskbits map for BRIGHT, brick %s' % brickname) ps.savefig() with outsurvey.write_output('maskbits', brick=brickname) as out: out.fits.write(maskbits, hdr=hdr) tfn = insurvey.find_file('tractor', brick=brickname) phdr = fitsio.read_header(tfn, ext=0) hdr = fitsio.read_header(tfn, ext=1) T = fits_table(tfn) print('Read', len(T), 'sources') print('Bright:', Counter(T.brightstarinblob)) iby = np.clip(np.round(T.by), 0, h - 1).astype(int) ibx = np.clip(np.round(T.bx), 0, w - 1).astype(int) if plots: before = np.flatnonzero(T.brightstarinblob) T.brightstarinblob |= touching[iby, ibx] print('Bright:', Counter(T.brightstarinblob)) # yuck -- copy the TUNIT headers from input to output. units = [ hdr.get('TUNIT%i' % (i + 1), '') for i in range(len(T.get_columns())) ] if plots: plt.clf() showbool((maskbits & MASKBITS['BRIGHT']) > 0) ax = plt.axis() after = np.flatnonzero(T.brightstarinblob) plt.plot(T.bx[before], T.by[before], 'gx') plt.plot(T.bx[after], T.by[after], 'r.') plt.axis(ax) plt.title('sources with brightstarinblob, brick %s' % brickname) ps.savefig() with outsurvey.write_output('tractor', brick=brickname) as out: T.writeto(None, fits_object=out.fits, primheader=phdr, header=hdr, units=units)
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
def rbmain(): travis = 'travis' in sys.argv extra_args = [ '--old-calibs-ok', #'--verbose', ] if travis: extra_args.extend( ['--no-wise-ceres', '--no-gaia', '--no-large-galaxies']) if 'ceres' in sys.argv: 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' ]) sys.exit(0) # demo RexGalaxy, with plots if False: from legacypipe.survey import RexGalaxy from tractor import NanoMaggies, PixPos from tractor import Image, GaussianMixturePSF, LinearPhotoCal from legacypipe.survey import LogRadius rex = RexGalaxy(PixPos(1., 2.), NanoMaggies(r=3.), LogRadius(0.)) print('Rex:', rex) print('Rex params:', rex.getParams()) print('Rex nparams:', rex.numberOfParams()) H, W = 100, 100 tim = Image(data=np.zeros((H, W), np.float32), inverr=np.ones((H, W), np.float32), psf=GaussianMixturePSF(1., 0., 0., 4., 4., 0.), photocal=LinearPhotoCal(1., band='r')) derivs = rex.getParamDerivatives(tim) print('Derivs:', len(derivs)) print('Rex params:', rex.getParamNames()) import pylab as plt from astrometry.util.plotutils import PlotSequence ps = PlotSequence('rex') for d, nm in zip(derivs, rex.getParamNames()): plt.clf() plt.imshow(d.patch, interpolation='nearest', origin='lower') plt.title('Derivative %s' % nm) ps.savefig() sys.exit(0) # Test RexGalaxy surveydir = os.path.join(os.path.dirname(__file__), 'testcase6') outdir = 'out-testcase6-rex' main(args=[ '--brick', '1102p240', '--zoom', '500', '600', '650', '750', '--force-all', '--no-write', '--no-wise', #'--rex', #'--plots', '--survey-dir', surveydir, '--outdir', outdir ] + extra_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] == '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 ] + extra_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] == 'PSF ') # 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') outdir = 'out-testcase4' fn = os.path.join(surveydir, 'calib', 'decam', 'splinesky', '00431', '00431608', 'decam-00431608-N3.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 ] + extra_args + ['-v']) print('Checking for calib file', fn) assert (os.path.exists(fn)) # Wrap-around, hybrid PSF surveydir = os.path.join(os.path.dirname(__file__), 'testcase8') outdir = 'out-testcase8' main(args=[ '--brick', '1209p050', '--zoom', '720', '1095', '3220', '3500', '--force-all', '--no-write', '--no-wise', #'--plots', '--survey-dir', surveydir, '--outdir', outdir ] + extra_args) # Test with a Tycho-2 star + another saturated star in the blob. surveydir = os.path.join(os.path.dirname(__file__), 'testcase7') outdir = 'out-testcase7' # remove --no-gaia my_extra_args = [a for a in extra_args if a != '--no-gaia'] os.environ['GAIA_CAT_DIR'] = os.path.join(surveydir, 'gaia-dr2') 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 ] + my_extra_args) 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' # 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 ] + extra_args) 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' 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' ] + extra_args) # Read catalog into Tractor sources to test read_fits_catalog from legacypipe.catalog import read_fits_catalog from legacypipe.survey import LegacySurveyData, GaiaSource from tractor.galaxy import DevGalaxy from tractor import PointSource survey = LegacySurveyData(survey_dir=outdir) fn = survey.find_file('tractor', brick='2447p120') print('Checking', fn) T = fits_table(fn) cat = read_fits_catalog(T, fluxPrefix='') print('Read catalog:', cat) assert (len(cat) == 2) src = cat[0] assert (type(src) == DevGalaxy) assert (np.abs(src.pos.ra - 244.77973) < 0.00001) assert (np.abs(src.pos.dec - 12.07233) < 0.00001) src = cat[1] print('Source', src) assert (type(src) in [PointSource, GaiaSource]) assert (np.abs(src.pos.ra - 244.77830) < 0.00001) assert (np.abs(src.pos.dec - 12.07250) < 0.00001) # DevGalaxy(pos=RaDecPos[244.77975494973529, 12.072348111713127], brightness=NanoMaggies: g=19.2, r=17.9, z=17.1, shape=re=2.09234, e1=-0.198453, e2=0.023652, # PointSource(RaDecPos[244.77833280764278, 12.072521274981987], NanoMaggies: g=25, r=23, z=21.7) # 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' ] + extra_args) # 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' ] + extra_args) # MzLS + BASS data # surveydir2 = os.path.join(os.path.dirname(__file__), 'mzlsbass') # main(args=['--brick', '3521p002', '--zoom', '2400', '2450', '1200', '1250', # '--no-wise', '--force-all', '--no-write', # '--survey-dir', surveydir2, # '--outdir', 'out-mzlsbass']) # 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' ] + extra_args) # Decals Image Simulations # Uncomment WHEN galsim build for Travis #os.environ["DECALS_SIM_DIR"]= os.path.join(os.path.dirname(__file__),'image_sims') #brick= '2447p120' #sim_main(args=['--brick', brick, '-n', '2', '-o', 'STAR', \ # '-ic', '1', '--rmag-range', '18', '26', '--threads', '1',\ # '--zoom', '1020', '1070', '2775', '2815']) # Check if correct files written out #rt_dir= os.path.join(os.getenv('DECALS_SIM_DIR'),brick,'star','001') #assert( os.path.exists(os.path.join(rt_dir,'../','metacat-'+brick+'-star.fits')) ) #for fn in ['tractor-%s-star-01.fits' % brick,'simcat-%s-star-01.fits' % brick]: # assert( os.path.exists(os.path.join(rt_dir,fn)) ) #for fn in ['image','model','resid','simscoadd']: # assert( os.path.exists(os.path.join(rt_dir,'qa-'+brick+'-star-'+fn+'-01.jpg')) ) if not travis: # With ceres main(args=[ '--brick', '2447p120', '--zoom', '1020', '1070', '2775', '2815', '--no-wise', '--force-all', '--no-write', '--ceres', '--survey-dir', surveydir, '--outdir', 'out-testcase3-ceres' ] + extra_args)
def main(): survey = LegacySurveyData() brickname = '2351p137' # RA,Dec = 235.0442, 13.7125 bx, by = 3300, 1285 sz = 50 bbox = [bx - sz, bx + sz, by - sz, by + sz] objid = 1394 bands = ['g', 'r', 'z'] from legacypipe.runbrick import stage_tims, _get_mod, rgbkwargs, rgbkwargs_resid from legacypipe.survey import get_rgb, imsave_jpeg from legacypipe.coadds import make_coadds from astrometry.util.multiproc import multiproc from astrometry.util.fits import fits_table from legacypipe.catalog import read_fits_catalog # brick = survey.get_brick_by_name(brickname) # # Get WCS object describing brick # targetwcs = wcs_for_brick(brick) # (x0,x1,y0,y1) = bbox # W = x1-x0 # H = y1-y0 # targetwcs = targetwcs.get_subimage(x0, y0, W, H) # H,W = targetwcs.shape mp = multiproc() P = stage_tims(brickname=brickname, survey=survey, target_extent=bbox, pixPsf=True, hybridPsf=True, depth_cut=False, mp=mp) print('Got', P.keys()) tims = P['tims'] targetwcs = P['targetwcs'] H, W = targetwcs.shape # Read Tractor catalog fn = survey.find_file('tractor', brick=brickname) print('Trying to read catalog', fn) cat = fits_table(fn) print('Read', len(cat), 'sources') ok, xx, yy = targetwcs.radec2pixelxy(cat.ra, cat.dec) I = np.flatnonzero((xx > 0) * (xx < W) * (yy > 0) * (yy < H)) cat.cut(I) print('Cut to', len(cat), 'sources within box') I = np.flatnonzero(cat.objid != objid) cat.cut(I) print('Cut to', len(cat), 'sources with objid !=', objid) #cat.about() # Convert FITS catalog into tractor source objects print('Creating tractor sources...') srcs = read_fits_catalog(cat, fluxPrefix='') print('Sources:') for src in srcs: print(' ', src) print('Rendering model images...') mods = [_get_mod((tim, srcs)) for tim in tims] print('Producing coadds...') C = make_coadds(tims, bands, targetwcs, mods=mods, mp=mp) print('Coadds:', dir(C)) coadd_list = [('image', C.coimgs, rgbkwargs), ('model', C.comods, rgbkwargs), ('resid', C.coresids, rgbkwargs_resid)] #C.coimgs, C.comods, C.coresids for name, ims, rgbkw in coadd_list: rgb = get_rgb(ims, bands, **rgbkw) kwa = {} #with survey.write_output(name + '-jpeg', brick=brickname) as out: # imsave_jpeg(out.fn, rgb, origin='lower', **kwa) # print('Wrote', out.fn) outfn = name + '.jpg' imsave_jpeg(outfn, rgb, origin='lower', **kwa) del rgb
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)
from astrometry.util.fits import * import numpy as np from glob import glob from collections import Counter from legacypipe.survey import LegacySurveyData fns = glob('forced/*/*/forced-*.fits') F = merge_tables([fits_table(fn) for fn in fns]) dr6 = LegacySurveyData('/project/projectdirs/cosmo/data/legacysurvey/dr6') B = dr6.get_bricks_readonly() I = np.flatnonzero((B.ra1 < F.ra.max()) * (B.ra2 > F.ra.min()) * (B.dec1 < F.dec.max()) * (B.dec2 > F.dec.min())) print(len(I), 'bricks') T = merge_tables([fits_table(dr6.find_file('tractor', brick=B.brickname[i])) for i in I]) print(len(T), 'sources') T.cut(T.brick_primary) print(len(T), 'primary') # map from F to T index imap = dict([((b,o),i) for i,(b,o) in enumerate(zip(T.brickid, T.objid))]) F.tindex = np.array([imap[(b,o)] for b,o in zip(F.brickid, F.objid)]) assert(np.all(T.brickid[F.tindex] == F.brickid)) assert(np.all(T.objid[F.tindex] == F.objid)) fcols = 'apflux apflux_ivar camera expnum ccdname exptime flux flux_ivar fracflux mask mjd rchi2 x y brickid objid'.split() bands = np.unique(F.filter) for band in bands: Fb = F[F.filter == band]
def make_pickle_file(pfn, derivs=False, agn=False): survey = LegacySurveyData() ccds = survey.get_ccds() brickname = '0364m042' bricks = survey.get_bricks() brick = bricks[bricks.brickname == brickname][0] print('Brick', brick) catfn = survey.find_file('tractor', brick=brickname) print('Reading catalog from', catfn) cat = fits_table(catfn) print(len(cat), 'catalog entries') cat.cut(cat.brick_primary) print(len(cat), 'brick primary') ''' BRICKNAM BRICKID BRICKQ BRICKROW BRICKCOL RA DEC 0364m042 306043 3 343 145 36.4255910987483 -4.25000000000000 RA1 RA2 DEC1 DEC2 36.3004172461752 36.5507649513213 -4.37500000000000 -4.12500000000000 ''' rlo, rhi = brick.ra1, brick.ra2 dlo, dhi = brick.dec1, brick.dec2 #rlo,rhi = 36.4, 36.5 #dlo,dhi = -4.4, -4.3 ra, dec = (rlo + rhi) / 2., (dlo + dhi) / 2. ## optional cat.cut( (cat.ra > rlo) * (cat.ra < rhi) * (cat.dec > dlo) * (cat.dec < dhi)) print('Cut to', len(cat), 'catalog objects in RA,Dec box') lightcurves = dict([((brickname, oid), []) for oid in cat.objid]) # close enough to equator to ignore cos(dec) dra = 4096 / 2. * 0.262 / 3600. ddec = 2048 / 2. * 0.262 / 3600. ccds.cut((np.abs(ccds.ra - ra) < (rhi - rlo) / 2. + dra) * (np.abs(ccds.dec - dec) < (dhi - dlo) / 2. + ddec)) print('Cut to', len(ccds), 'CCDs overlapping brick') ### HACK #ccds = ccds[:50] for i, (expnum, ccdname) in enumerate(zip(ccds.expnum, ccds.ccdname)): ee = '%08i' % expnum flavor = 'vanilla' cols = [ 'brickname', 'objid', 'camera', 'expnum', 'ccdname', 'mjd', 'filter', 'flux', 'flux_ivar' ] if derivs: flavor = 'derivs' cols.extend( ['flux_dra', 'flux_ddec', 'flux_dra_ivar', 'flux_ddec_ivar']) if agn: flavor = 'agn' cols.extend(['flux_agn', 'flux_agn_ivar']) fn = 'forced/%s/%s/%s/forced-decam-%s-%s.fits' % (flavor, ee[:5], ee, ee, ccdname) if not os.path.exists(fn): print('WARNING: missing:', fn) continue T = fits_table(fn) print(i + 1, 'of', len(ccds), ':', len(T), 'in', fn) T.cut(T.brickname == brickname) print(len(T), 'in brick', brickname) found = 0 for t in T: #oid,expnum,ccdname,mjd,filter,flux,fluxiv in zip(T.objid, T.expnum, T.ccdname, T.mjd, T.filter, T.flux, T.flux_ivar): lc = lightcurves.get((t.brickname, t.objid), None) if lc is None: continue found += 1 #lc.append((expnum, ccdname, mjd, filter, flux, fluxiv)) lc.append([t.get(c) for c in cols]) print('Matched', found, 'sources to light curves') #pickle_to_file(lightcurves, pfn) ll = {} for k, v in lightcurves.items(): if len(v) == 0: continue T = fits_table() # T.expnum = np.array([vv[0] for vv in v]) # T.ccdname= np.array([vv[1] for vv in v]) # T.mjd = np.array([vv[2] for vv in v]) # T.filter = np.array([vv[3] for vv in v]) # T.flux = np.array([vv[4] for vv in v]) # T.fluxiv = np.array([vv[5] for vv in v]) for i, c in enumerate(cols): T.set(c, np.array([vv[i] for vv in v])) ll[k] = T pickle_to_file(ll, pfn)
'--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 from legacypipe.catalog import read_fits_catalog from legacypipe.survey import LegacySurveyData from astrometry.util.fits import fits_table from tractor.galaxy import DevGalaxy from tractor import PointSource survey = LegacySurveyData(survey_dir=outdir) fn = survey.find_file('tractor', brick='2447p120') T = fits_table(fn) cat = read_fits_catalog(T) print('Read catalog:', cat) assert(len(cat) == 2) src = cat[0] assert(type(src) == DevGalaxy) assert(np.abs(src.pos.ra - 244.77975) < 0.00001) assert(np.abs(src.pos.dec - 12.07234) < 0.00001) src = cat[1] assert(type(src) == PointSource) assert(np.abs(src.pos.ra - 244.77833) < 0.00001) assert(np.abs(src.pos.dec - 12.07252) < 0.00001) # DevGalaxy(pos=RaDecPos[244.77975494973529, 12.072348111713127], brightness=NanoMaggies: g=19.2, r=17.9, z=17.1, shape=re=2.09234, e1=-0.198453, e2=0.023652, # PointSource(RaDecPos[244.77833280764278, 12.072521274981987], NanoMaggies: g=25, r=23, z=21.7)
'--no-wise', '--force-all', '--no-write', '--survey-dir', surveydir, '--outdir', outdir, '--checkpoint', checkpoint_fn, '--checkpoint-period', '1', '--threads', '2'] + extra_args) # Read catalog into Tractor sources to test read_fits_catalog from legacypipe.catalog import read_fits_catalog from legacypipe.survey import LegacySurveyData, GaiaSource from astrometry.util.fits import fits_table from tractor.galaxy import DevGalaxy from tractor import PointSource survey = LegacySurveyData(survey_dir=outdir) fn = survey.find_file('tractor', brick='2447p120') print('Checking', fn) T = fits_table(fn) cat = read_fits_catalog(T, fluxPrefix='') print('Read catalog:', cat) assert(len(cat) == 2) src = cat[0] assert(type(src) == DevGalaxy) assert(np.abs(src.pos.ra - 244.77975) < 0.00001) assert(np.abs(src.pos.dec - 12.07234) < 0.00001) src = cat[1] print('Source', src) assert(type(src) in [PointSource, GaiaSource]) assert(np.abs(src.pos.ra - 244.77833) < 0.00001) assert(np.abs(src.pos.dec - 12.07252) < 0.00001) # DevGalaxy(pos=RaDecPos[244.77975494973529, 12.072348111713127], brightness=NanoMaggies: g=19.2, r=17.9, z=17.1, shape=re=2.09234, e1=-0.198453, e2=0.023652,
def plot_light_curves(pfn, ucal=False): lightcurves = unpickle_from_file(pfn) if ucal: tag = 'ucal-' else: tag = '' survey = LegacySurveyData() brickname = '0364m042' catfn = survey.find_file('tractor', brick=brickname) print('Reading catalog from', catfn) cat = fits_table(catfn) print(len(cat), 'catalog entries') cat.cut(cat.brick_primary) print(len(cat), 'brick primary') I = [] for i, oid in enumerate(cat.objid): if (brickname, oid) in lightcurves: I.append(i) I = np.array(I) cat.cut(I) print('Cut to', len(cat), 'with light curves') S = fits_table('specObj-dr12-trim-2.fits') from astrometry.libkd.spherematch import match_radec I, J, d = match_radec(S.ra, S.dec, cat.ra, cat.dec, 2. / 3600.) print('Matched', len(I), 'to spectra') plt.subplots_adjust(hspace=0) movie_jpegs = [] movie_wcs = None for i in range(28): fn = os.path.join('des-sn-movie', 'epoch%i' % i, 'coadd', brickname[:3], brickname, 'legacysurvey-%s-image.jpg' % brickname) print(fn) if not os.path.exists(fn): continue img = plt.imread(fn) img = np.flipud(img) h, w, d = img.shape fn = os.path.join('des-sn-movie', 'epoch%i' % i, 'coadd', brickname[:3], brickname, 'legacysurvey-%s-image-r.fits' % brickname) if not os.path.exists(fn): continue wcs = Tan(fn) movie_jpegs.append(img) movie_wcs = wcs plt.figure(figsize=(8, 6), dpi=100) n = 0 fluxtags = [('flux', 'flux_ivar', '', 'a')] if ucal: fluxtags.append(('uflux', 'uflux_ivar', ': ucal', 'b')) for oid, ii in zip(cat.objid[J], I): print('Objid', oid) spec = S[ii] k = (brickname, oid) v = lightcurves[k] # Cut bad CCDs v.cut(np.array([e not in [230151, 230152, 230153] for e in v.expnum])) plt.clf() print('obj', k, 'has', len(v), 'measurements') T = v for fluxtag, fluxivtag, fluxname, plottag in fluxtags: plt.clf() filts = np.unique(T.filter) for i, f in enumerate(filts): from tractor.brightness import NanoMaggies plt.subplot(len(filts), 1, i + 1) fluxes = np.hstack( [T.get(ft[0])[T.filter == f] for ft in fluxtags]) fluxes = fluxes[np.isfinite(fluxes)] mn, mx = np.percentile(fluxes, [5, 95]) print('Flux percentiles for filter', f, ':', mn, mx) # note swap mn, mx = NanoMaggies.nanomaggiesToMag( mx), NanoMaggies.nanomaggiesToMag(mn) print('-> mags', mn, mx) cut = (T.filter == f) * (T.flux_ivar > 0) if ucal: cut *= np.isfinite(T.uflux) I = np.flatnonzero(cut) print(' ', len(I), 'in', f, 'band') I = I[np.argsort(T.mjd[I])] mediv = np.median(T.flux_ivar[I]) # cut really noisy ones I = I[T.flux_ivar[I] > 0.25 * mediv] #plt.plot(T.mjd[I], T.flux[I], '.-', color=dict(g='g',r='r',z='m')[f]) # plt.errorbar(T.mjd[I], T.flux[I], yerr=1/np.sqrt(T.fluxiv[I]), # fmt='.-', color=dict(g='g',r='r',z='m')[f]) #plt.errorbar(T.mjd[I], T.flux[I], yerr=1/np.sqrt(T.fluxiv[I]), # fmt='.', color=dict(g='g',r='r',z='m')[f]) # if ucal: # mag,dmag = NanoMaggies.fluxErrorsToMagErrors(T.flux[I], T.flux_ivar[I]) # else: # mag,dmag = NanoMaggies.fluxErrorsToMagErrors(T.uflux[I], T.uflux_ivar[I]) mag, dmag = NanoMaggies.fluxErrorsToMagErrors( T.get(fluxtag)[I], T.get(fluxivtag)[I]) plt.errorbar(T.mjd[I], mag, yerr=dmag, fmt='.', color=dict(g='g', r='r', z='m')[f]) #yl,yh = plt.ylim() #plt.ylim(yh,yl) plt.ylim(mx, mn) plt.ylabel(f) if i + 1 < len(filts): plt.xticks([]) #plt.yscale('symlog') outfn = 'cutout_%.4f_%.4f.jpg' % (spec.ra, spec.dec) if not os.path.exists(outfn): url = 'http://legacysurvey.org/viewer/jpeg-cutout/?ra=%.4f&dec=%.4f&zoom=14&layer=sdssco&size=128' % ( spec.ra, spec.dec) cmd = 'wget -O %s "%s"' % (outfn, url) print(cmd) os.system(cmd) pix = plt.imread(outfn) h, w, d = pix.shape fig = plt.gcf() #print('fig bbox:', fig.bbox) #print('xmax, ymax', fig.bbox.xmax, fig.bbox.ymax) #plt.figimage(pix, 0, fig.bbox.ymax - h, zorder=10) #plt.figimage(pix, 0, fig.bbox.ymax, zorder=10) #plt.figimage(pix, fig.bbox.xmax - w, fig.bbox.ymax, zorder=10) plt.figimage(pix, fig.bbox.xmax - (w + 2), fig.bbox.ymax - (h + 2), zorder=10) plt.suptitle('SDSS spectro object: %s at (%.4f, %.4f)%s' % (spec.label.strip(), spec.ra, spec.dec, fluxname)) plt.savefig('forced-%s%i-%s.png' % (tag, n, plottag)) ok, x, y = movie_wcs.radec2pixelxy(spec.ra, spec.dec) x = int(np.round(x - 1)) y = int(np.round(y - 1)) sz = 32 plt.clf() plt.subplots_adjust(hspace=0, wspace=0) k = 1 for i, img in enumerate(movie_jpegs): stamp = img[y - sz:y + sz + 1, x - sz:x + sz + 1] plt.subplot(5, 6, k) plt.imshow(stamp, interpolation='nearest', origin='lower') plt.xticks([]) plt.yticks([]) k += 1 plt.suptitle('SDSS spectro object: %s at (%.4f, %.4f): DES images' % (spec.label.strip(), spec.ra, spec.dec)) plt.savefig('forced-%s%i-c.png' % (tag, n)) n += 1
def main(): import argparse parser = argparse.ArgumentParser() parser.add_argument( '-b', '--brick', help='Brick name to run; required unless --radec is given') parser.add_argument( '--survey-dir', type=str, default=None, help='Override the $LEGACY_SURVEY_DIR environment variable') parser.add_argument('-d', '--outdir', dest='output_dir', help='Set output base directory, default "."') parser.add_argument( '--out', help='Output filename -- if not set, defaults to path within --outdir.' ) parser.add_argument('-r', '--run', default=None, help='Set the run type to execute (for images)') parser.add_argument( '--catalog', help= 'Use the given FITS catalog file, rather than reading from a data release directory' ) parser.add_argument('--catalog-dir', help='Set LEGACY_SURVEY_DIR to use to read catalogs') parser.add_argument( '--catalog-dir-north', help='Set LEGACY_SURVEY_DIR to use to read Northern catalogs') parser.add_argument( '--catalog-dir-south', help='Set LEGACY_SURVEY_DIR to use to read Southern catalogs') parser.add_argument( '--catalog-resolve-dec-ngc', type=float, help= 'Dec at which to switch from Northern to Southern catalogs (NGC only)', default=32.375) parser.add_argument('-v', '--verbose', dest='verbose', action='count', default=0, help='Make more verbose') opt = parser.parse_args() if opt.brick is None: parser.print_help() return -1 verbose = opt.verbose if 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) from legacypipe.runs import get_survey survey = get_survey(opt.run, survey_dir=opt.survey_dir, output_dir=opt.output_dir) columns = [ 'release', 'brickid', 'objid', ] cat = None catsurvey = survey if opt.catalog is not None: cat = fits_table(opt.catalog, columns=columns) print('Read', len(cat), 'sources from', opt.catalog) else: from astrometry.util.starutil_numpy import radectolb # The "north" and "south" directories often don't have # 'survey-bricks" files of their own -- use the 'survey' one # instead. brick = None for s in [survey, catsurvey]: try: brick = s.get_brick_by_name(opt.brick) break except: import traceback traceback.print_exc() pass l, b = radectolb(brick.ra, brick.dec) # NGC and above resolve line? -> north if b > 0 and brick.dec >= opt.catalog_resolve_dec_ngc: if opt.catalog_dir_north: catsurvey = LegacySurveyData(survey_dir=opt.catalog_dir_north) else: if opt.catalog_dir_south: catsurvey = LegacySurveyData(survey_dir=opt.catalog_dir_south) fn = catsurvey.find_file('tractor', brick=opt.brick) cat = fits_table(fn, columns=columns) print('Read', len(cat), 'sources from', fn) program_name = sys.argv[0] ## FIXME -- from catalog? release = 9999 version_hdr = get_version_header(program_name, opt.survey_dir, release) 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')) cat, forced = merge_forced(survey, opt.brick, cat) units = [] for i, col in enumerate(forced.get_columns()): units.append(forced._header.get('TUNIT%i' % (i + 1), '')) cols = forced.get_columns() if opt.out: cat.writeto(opt.out, primheader=version_hdr) forced.writeto(opt.out, append=True, units=units, columns=cols) else: with survey.write_output('forced-brick', brick=opt.brick) as out: cat.writeto(None, fits_object=out.fits, primheader=version_hdr) forced.writeto(None, fits_object=out.fits, append=True, units=units, columns=cols)
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(survey=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 survey.find_ccds() expnum = None # Try parsing HDU number try: opt.hdu = int(opt.hdu) ccdname = None except: ccdname = opt.hdu opt.hdu = -1 if survey is None: survey = LegacySurveyData() 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 survey-ccds.fits table T = survey.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) ccd = T[0] im = survey.get_image_object(ccd) tim = im.get_tractor_image(slc=zoomslice, pixPsf=True, splinesky=True, constant_invvar=opt.constant_invvar) print('Got tim:', tim) print('Read image:', Time()-t0) if opt.catfn in ['DR1', 'DR2', 'DR3']: margin = 20 TT = [] chipwcs = tim.subwcs bricks = bricks_touching_wcs(chipwcs, survey=survey) for b in bricks: # there is some overlap with this brick... read the catalog. fn = survey.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') T.cut((T.out_of_bounds == False) * (T.left_blob == False)) print('Cut to', len(T), 'on out_of_bounds and left_blob') 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 # 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 cat = read_fits_catalog(T) # print('Got cat:', cat) print('Read catalog:', Time()-t0) print('Forced photom...') opti = None forced_kwargs = {} if opt.ceres: from tractor.ceres_optimizer import CeresOptimizer B = 8 opti = CeresOptimizer(BW=B, BH=B) #forced_kwargs.update(verbose=True) for src in cat: # Limit sizes of huge models from tractor.galaxy import ProfileGalaxy if isinstance(src, ProfileGalaxy): px,py = tim.wcs.positionToPixel(src.getPosition()) h = src._getUnitFluxPatchSize(tim, px, py, tim.modelMinval) MAXHALF = 128 if h > MAXHALF: print('halfsize', h,'for',src,'-> setting to',MAXHALF) src.halfsize = MAXHALF tr = Tractor([tim], cat, optimizer=opti) tr.freezeParam('images') for src in cat: src.freezeAllBut('brightness') src.getBrightness().freezeAllBut(tim.band) disable_galaxy_cache() 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)).astype(np.float32) 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.forced: if opt.plots is None: forced_kwargs.update(wantims=False) R = tr.optimize_forced_photometry(variance=True, fitstats=True, shared_params=False, priors=False, **forced_kwargs) 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) print('Forced photom:', Time()-t0) 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.astype(np.float32) ap = 1./(np.vstack(apimgerr).T)**2 ap[np.logical_not(np.isfinite(ap))] = 0. F.apflux_ivar = ap.astype(np.float32) print('Aperture photom:', Time()-t0) 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...') 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
def main(): import argparse parser = argparse.ArgumentParser() parser.add_argument('--catalog', help='Catalog to render') parser.add_argument('--brick-coadd', help='Produce a coadd of the images overlapping the given brickname.') parser.add_argument('--ccds', help='Use this table of CCDs') parser.add_argument('--brick-wcs', help='File containing a WCS header describing the coadd WCS to render.') parser.add_argument('--brick-wcs-ext', type=int, help='FITS file extension containing a WCS header describing the coadd WCS to render.') parser.add_argument('--outlier-mask-brick', help='Comma-separated list of bricknames from which outlier masks should be read.') parser.add_argument('--out', help='Filename pattern ("BAND" will be replaced by band name) of output images.') parser.add_argument('--resid', help='Filename pattern ("BAND" will be replaced by band name) of residual images.') parser.add_argument('--jpeg', help='Write RGB image to this filename') parser.add_argument('--resid-jpeg', help='Write RGB residual image to this filename') opt = parser.parse_args() if opt.catalog is None: print('Need catalog!') return -1 cat = fits_table(opt.catalog) if opt.ccds is None: if opt.brick_coadd is None: print('Need brick catalog!') return -1 brickname = opt.brick_coadd survey = LegacySurveyData() if opt.brick_wcs is None: print('FIXME') return -1 else: wcs = Tan(opt.brick_wcs, opt.brick_wcs_ext) tcat = read_fits_catalog(cat) if opt.ccds: ccdfn = opt.ccds else: ccdfn = survey.find_file('ccds-table', brick=brickname) print('Reading', ccdfn) ccds = fits_table(ccdfn) 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)]]) tims = [] for ccd in ccds: im = survey.get_image_object(ccd) #slc = slice(ccd.ccd_y0, ccd.ccd_y1), slice(ccd.ccd_x0, ccd.ccd_x1) #tim = im.get_tractor_image(slc=slc) tim = im.get_tractor_image(radecpoly=targetrd) print('Read', tim) tims.append(tim) if opt.outlier_mask_brick is not None: bricks = opt.outlier_mask_brick.split(',') for b in bricks: print('Reading outlier mask for brick', b, ':', survey.find_file('outliers_mask', brick=b, output=False)) ok = read_outlier_mask_file(survey, tims, b, subimage=True, output=False) tr = Tractor(tims, tcat) mods = list(tr.getModelImages()) bands = 'grz' def write_model(band, cowimg=None, cowmod=None, **kwargs): if cowmod is None: print('No model for', band) return outfn = opt.out.replace('BAND', band) fitsio.write(outfn, cowmod, clobber=True) print('Wrote model for', band, 'to', outfn) if opt.resid: outfn = opt.resid.replace('BAND', band) fitsio.write(outfn, cowimg - cowmod, clobber=True) print('Wrote resid for', band, 'to', outfn) C = make_coadds(tims, bands, wcs, mods=mods, callback=write_model) if opt.jpeg: from legacypipe.survey import get_rgb import pylab as plt plt.imsave(opt.jpeg, get_rgb(C.comods, bands), origin='lower') if opt.resid_jpeg: from legacypipe.survey import get_rgb import pylab as plt plt.imsave(opt.resid_jpeg, get_rgb([im-mod for im,mod in zip(C.coimgs, C.comods)], bands), origin='lower')
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