Beispiel #1
0
def map_sdss(req,
             ver,
             zoom,
             x,
             y,
             savecache=None,
             tag='sdss',
             get_images=False,
             ignoreCached=False,
             wcs=None,
             forcecache=False,
             forcescale=None,
             bestOnly=False,
             bands='gri',
             **kwargs):
    from decals import settings

    if savecache is None:
        savecache = settings.SAVE_CACHE
    zoom = int(zoom)
    zoomscale = 2.**zoom
    x = int(x)
    y = int(y)
    if zoom < 0 or x < 0 or y < 0 or x >= zoomscale or y >= zoomscale:
        raise RuntimeError('Invalid zoom,x,y %i,%i,%i' % (zoom, x, y))
    ver = int(ver)

    if not ver in tileversions[tag]:
        raise RuntimeError('Invalid version %i for tag %s' % (ver, tag))

    basedir = settings.DATA_DIR
    tilefn = os.path.join(basedir, 'tiles', tag,
                          '%i/%i/%i/%i.jpg' % (ver, zoom, x, y))
    if os.path.exists(tilefn) and not ignoreCached:
        if get_images:
            return None
        return send_file(tilefn,
                         'image/jpeg',
                         expires=oneyear,
                         modsince=req.META.get('HTTP_IF_MODIFIED_SINCE'))

    if not savecache:
        import tempfile
        f, tilefn = tempfile.mkstemp(suffix='.jpg')
        os.close(f)

    if wcs is None:
        try:
            wcs, W, H, zoomscale, zoom, x, y = get_tile_wcs(zoom, x, y)
        except RuntimeError as e:
            if get_images:
                return None
            return HttpResponse(e.strerror)
    else:
        W = wcs.get_width()
        H = wcs.get_height()

    from astrometry.util.fits import fits_table
    import numpy as np
    from astrometry.libkd.spherematch import tree_build_radec, tree_search_radec
    from astrometry.util.starutil_numpy import degrees_between, arcsec_between
    from astrometry.util.resample import resample_with_wcs, OverlapError
    from astrometry.util.util import Tan, Sip
    import fitsio

    print('Tile wcs: center', wcs.radec_center(), 'pixel scale',
          wcs.pixel_scale())

    global w_flist
    global w_flist_tree
    if w_flist is None:
        w_flist = fits_table(
            os.path.join(settings.DATA_DIR, 'sdss', 'window_flist.fits'),
            columns=['run', 'rerun', 'camcol', 'field', 'ra', 'dec', 'score'])
        print('Read', len(w_flist), 'window_flist entries')
        w_flist.cut(w_flist.rerun == '301')
        print('Cut to', len(w_flist), 'in rerun 301')
        w_flist_tree = tree_build_radec(w_flist.ra, w_flist.dec)

    # SDSS field size
    radius = 1.01 * np.hypot(10., 14.) / 2. / 60.

    # leaflet tile size
    ra, dec = wcs.pixelxy2radec(W / 2., H / 2.)[-2:]
    r0, d0 = wcs.pixelxy2radec(1, 1)[-2:]
    r1, d1 = wcs.pixelxy2radec(W, H)[-2:]
    radius = radius + max(degrees_between(ra, dec, r0, d0),
                          degrees_between(ra, dec, r1, d1))

    J = tree_search_radec(w_flist_tree, ra, dec, radius)

    print(len(J), 'overlapping SDSS fields found')
    if len(J) == 0:
        if get_images:
            return None
        if forcecache:
            # create symlink to blank.jpg!
            trymakedirs(tilefn)
            src = os.path.join(settings.STATIC_ROOT, 'blank.jpg')
            if os.path.exists(tilefn):
                os.unlink(tilefn)
            os.symlink(src, tilefn)
            print('Symlinked', tilefn, '->', src)
        from django.http import HttpResponseRedirect
        return HttpResponseRedirect(settings.STATIC_URL + 'blank.jpg')

    ww = [1, W * 0.25, W * 0.5, W * 0.75, W]
    hh = [1, H * 0.25, H * 0.5, H * 0.75, H]

    r, d = wcs.pixelxy2radec(
        [1] * len(hh) + ww + [W] * len(hh) + list(reversed(ww)),
        hh + [1] * len(ww) + list(reversed(hh)) + [H] * len(ww))[-2:]

    scaled = 0
    scalepat = None
    scaledir = 'sdss'

    if zoom <= 13 and forcescale is None:
        # Get *actual* pixel scales at the top & bottom
        r1, d1 = wcs.pixelxy2radec(W / 2., H)[-2:]
        r2, d2 = wcs.pixelxy2radec(W / 2., H - 1.)[-2:]
        r3, d3 = wcs.pixelxy2radec(W / 2., 1.)[-2:]
        r4, d4 = wcs.pixelxy2radec(W / 2., 2.)[-2:]
        # Take the min = most zoomed-in
        scale = min(arcsec_between(r1, d1, r2, d2),
                    arcsec_between(r3, d3, r4, d4))

        native_scale = 0.396
        scaled = int(np.floor(np.log2(scale / native_scale)))
        print('Zoom:', zoom, 'x,y', x, y, 'Tile pixel scale:', scale,
              'Scale step:', scaled)
        scaled = np.clip(scaled, 1, 7)
        dirnm = os.path.join(basedir, 'scaled', scaledir)
        scalepat = os.path.join(
            dirnm, '%(scale)i%(band)s', '%(rerun)s', '%(run)i', '%(camcol)i',
            'sdss-%(run)i-%(camcol)i-%(field)i-%(band)s.fits')

    if forcescale is not None:
        scaled = forcescale

    rimgs = [np.zeros((H, W), np.float32) for band in bands]
    rns = [np.zeros((H, W), np.float32) for band in bands]

    from astrometry.sdss import AsTransWrapper, DR9
    sdss = DR9(basedir=settings.SDSS_DIR)
    sdss.saveUnzippedFiles(settings.SDSS_DIR)
    #sdss.setFitsioReadBZ2()
    if settings.SDSS_PHOTOOBJS:
        sdss.useLocalTree(photoObjs=settings.SDSS_PHOTOOBJS,
                          resolve=settings.SDSS_RESOLVE)

    for jnum, j in enumerate(J):
        print('SDSS field', jnum, 'of', len(J), 'for zoom', zoom, 'x', x, 'y',
              y)
        im = w_flist[j]

        if im.score >= 0.5:
            weight = 1.
        else:
            weight = 0.001

        for band, rimg, rn in zip(bands, rimgs, rns):
            if im.rerun != '301':
                continue
            tmpsuff = '.tmp%08i' % np.random.randint(100000000)
            basefn = sdss.retrieve('frame',
                                   im.run,
                                   im.camcol,
                                   field=im.field,
                                   band=band,
                                   rerun=im.rerun,
                                   tempsuffix=tmpsuff)
            if scaled > 0:
                fnargs = dict(band=band,
                              rerun=im.rerun,
                              run=im.run,
                              camcol=im.camcol,
                              field=im.field)
                fn = get_scaled(scalepat,
                                fnargs,
                                scaled,
                                basefn,
                                read_base_wcs=read_astrans,
                                read_wcs=read_sip_wcs)
                print('get_scaled:', fn)
            else:
                fn = basefn
            frame = None
            if fn == basefn:
                frame = sdss.readFrame(im.run,
                                       im.camcol,
                                       im.field,
                                       band,
                                       filename=fn)
                h, w = frame.getImageShape()
                # Trim off the overlapping top of the image
                # Wimp out and instead of trimming 128 pix, trim 124!
                trim = 124
                subh = h - trim
                astrans = frame.getAsTrans()
                fwcs = AsTransWrapper(astrans, w, subh)
                fullimg = frame.getImage()
                fullimg = fullimg[:-trim, :]
            else:
                fwcs = Sip(fn)
                fitsimg = fitsio.FITS(fn)[0]
                h, w = fitsimg.get_info()['dims']
                fullimg = fitsimg.read()

            try:
                #Yo,Xo,Yi,Xi,nil = resample_with_wcs(wcs, fwcs, [], 3)
                Yo, Xo, Yi, Xi, [resamp
                                 ] = resample_with_wcs(wcs, fwcs, [fullimg], 2)
            except OverlapError:
                continue
            if len(Xi) == 0:
                #print 'No overlap'
                continue

            if sdssps is not None:
                x0 = Xi.min()
                x1 = Xi.max()
                y0 = Yi.min()
                y1 = Yi.max()
                slc = (slice(y0, y1 + 1), slice(x0, x1 + 1))
                if frame is not None:
                    img = frame.getImageSlice(slc)
                else:
                    img = fitsimg[slc]
            #rimg[Yo,Xo] += img[Yi-y0, Xi-x0]

            if bestOnly:
                K = np.flatnonzero(weight > rn[Yo, Xo])
                print('Updating', len(K), 'of', len(Yo), 'pixels')
                if len(K):
                    rimg[Yo[K], Xo[K]] = resamp[K] * weight
                    rn[Yo[K], Xo[K]] = weight
            else:
                rimg[Yo, Xo] += resamp * weight
                rn[Yo, Xo] += weight

            if sdssps is not None:
                # goodpix = np.ones(img.shape, bool)
                # fpM = sdss.readFpM(im.run, im.camcol, im.field, band)
                # for plane in [ 'INTERP', 'SATUR', 'CR', 'GHOST' ]:
                #     fpM.setMaskedPixels(plane, goodpix, False, roi=[x0,x1,y0,y1])
                plt.clf()
                #ima = dict(vmin=-0.05, vmax=0.5)
                #ima = dict(vmin=-0.5, vmax=2.)
                ima = dict(vmax=np.percentile(img, 99))
                plt.subplot(2, 3, 1)
                dimshow(img, ticks=False, **ima)
                plt.title('image')
                rthis = np.zeros_like(rimg)
                #rthis[Yo,Xo] += img[Yi-y0, Xi-x0]
                rthis[Yo, Xo] += resamp
                plt.subplot(2, 3, 2)
                dimshow(rthis, ticks=False, **ima)
                plt.title('resampled')
                # plt.subplot(2,3,3)
                # dimshow(goodpix, ticks=False, vmin=0, vmax=1)
                # plt.title('good pix')
                plt.subplot(2, 3, 4)
                dimshow(rimg / np.maximum(rn, 1), ticks=False, **ima)
                plt.title('coadd')
                plt.subplot(2, 3, 5)
                dimshow(rn, vmin=0, ticks=False)
                plt.title('coverage: max %i' % rn.max())
                plt.subplot(2, 3, 6)
                rgb = sdss_rgb(
                    [rimg / np.maximum(rn, 1) for rimg, rn in zip(rimgs, rns)],
                    bands)
                dimshow(rgb)
                plt.suptitle('SDSS %s, R/C/F %i/%i/%i' %
                             (band, im.run, im.camcol, im.field))
                sdssps.savefig()

    for rimg, rn in zip(rimgs, rns):
        rimg /= np.maximum(rn, 1e-3)
    del rns

    if get_images:
        return rimgs

    rgb = sdss_rgb(rimgs, bands)
    trymakedirs(tilefn)
    save_jpeg(tilefn, rgb)
    print('Wrote', tilefn)

    return send_file(tilefn, 'image/jpeg', unlink=(not savecache))
Beispiel #2
0
def map_coadd_bands(
    req,
    ver,
    zoom,
    x,
    y,
    bands,
    tag,
    imagedir,
    wcs=None,
    imagetag='image2',
    rgbfunc=None,
    rgbkwargs={},
    bricks=None,
    savecache=True,
    forcecache=False,
    return_if_not_found=False,
    model_gz=False,
    modeldir=None,
    scaledir=None,
    get_images=False,
    write_jpeg=False,
    ignoreCached=False,
    add_gz=False,
    filename=None,
    symlink_blank=False,
    hack_jpeg=False,
    drname=None,
    decals=None,
    basepat=None,
    scalepat=None,
    nativescale=14,
    maxscale=8,
):
    from decals import settings
    from map.views import tileversions

    zoom = int(zoom)
    zoomscale = 2.**zoom
    x = int(x)
    y = int(y)
    if zoom < 0 or x < 0 or y < 0 or x >= zoomscale or y >= zoomscale:
        raise RuntimeError('Invalid zoom,x,y %i,%i,%i' % (zoom, x, y))
    ver = int(ver)

    if not ver in tileversions[tag]:
        raise RuntimeError('Invalid version %i for tag %s' % (ver, tag))

    basedir = settings.DATA_DIR
    tilefn = os.path.join(basedir, 'tiles', tag,
                          '%i/%i/%i/%i.jpg' % (ver, zoom, x, y))
    if os.path.exists(tilefn) and not ignoreCached:
        return send_file(tilefn,
                         'image/jpeg',
                         expires=oneyear,
                         modsince=req.META.get('HTTP_IF_MODIFIED_SINCE'),
                         filename=filename)
    else:
        debug('Tile image does not exist:', tilefn)
    from astrometry.util.resample import resample_with_wcs, OverlapError
    from astrometry.util.util import Tan
    import numpy as np
    import fitsio

    if wcs is None:
        try:
            wcs, W, H, zoomscale, zoom, x, y = get_tile_wcs(zoom, x, y)
        except RuntimeError as e:
            return HttpResponse(e.strerror)
    else:
        W = wcs.get_width()
        H = wcs.get_height()

    if basepat is None:
        basepat = os.path.join(
            basedir, 'coadd', imagedir, '%(brickname).3s', '%(brickname)s',
            'decals-%(brickname)s-' + imagetag + '-%(band)s.fits')
    if modeldir is not None:
        modbasepat = os.path.join(
            basedir, 'coadd', modeldir, '%(brickname).3s', '%(brickname)s',
            'decals-%(brickname)s-' + imagetag + '-%(band)s.fits')
    else:
        modbasepat = basepat

    if model_gz and imagetag == 'model':
        modbasepat += '.gz'
    if add_gz:
        basepat += '.gz'

    scaled = 0
    if scaledir is None:
        scaledir = imagedir
    if zoom < nativescale:
        scaled = (nativescale - zoom)
        scaled = np.clip(scaled, 1, maxscale)
        #debug('Scaled-down:', scaled)
        dirnm = os.path.join(basedir, 'scaled', scaledir)
        if scalepat is None:
            scalepat = os.path.join(dirnm, '%(scale)i%(band)s',
                                    '%(brickname).3s',
                                    imagetag + '-%(brickname)s-%(band)s.fits')

    if decals is None:
        from map.views import _get_survey
        D = _get_survey(name=drname)
    else:
        D = decals
    if bricks is None:
        B = D.get_bricks_readonly()
    else:
        B = bricks

    rlo, d = wcs.pixelxy2radec(W, H / 2)[-2:]
    rhi, d = wcs.pixelxy2radec(1, H / 2)[-2:]
    r, d1 = wcs.pixelxy2radec(W / 2, 1)[-2:]
    r, d2 = wcs.pixelxy2radec(W / 2, H)[-2:]

    dlo = min(d1, d2)
    dhi = max(d1, d2)
    I = D.bricks_touching_radec_box(B, rlo, rhi, dlo, dhi)
    debug(len(I), 'bricks touching zoom', zoom, 'x,y', x, y, 'RA', rlo, rhi,
          'Dec', dlo, dhi)

    if len(I) == 0:
        if get_images:
            return None
        from django.http import HttpResponseRedirect
        if forcecache and symlink_blank:
            # create symlink to blank.jpg!
            trymakedirs(tilefn)
            src = os.path.join(settings.STATIC_ROOT, 'blank.jpg')
            if os.path.exists(tilefn):
                os.unlink(tilefn)
            os.symlink(src, tilefn)
            debug('Symlinked', tilefn, '->', src)
        return HttpResponseRedirect(settings.STATIC_URL + 'blank.jpg')

    r, d = wcs.pixelxy2radec([1, 1, 1, W / 2, W, W, W, W / 2],
                             [1, H / 2, H, H, H, H / 2, 1, 1])[-2:]
    foundany = False
    rimgs = []
    for band in bands:
        rimg = np.zeros((H, W), np.float32)
        rn = np.zeros((H, W), np.uint8)
        for i, brickname in zip(I, B.brickname[I]):
            has = getattr(B, 'has_%s' % band, None)
            if has is not None and not has[i]:
                # No coverage for band in this brick.
                debug('Brick', brickname, 'has no', band, 'band')
                continue

            fnargs = dict(band=band, brickname=brickname)

            if imagetag == 'resid':
                #basefn = basepat % fnargs

                basefn = D.find_file('image', brick=brickname, band=band)

                modbasefn = D.find_file('model', brick=brickname, band=band)
                #modbasefn = modbasepat % fnargs
                #modbasefn = modbasefn.replace('resid', 'model')
                #if model_gz:
                #    modbasefn += '.gz'

                if scalepat is None:
                    imscalepat = None
                    modscalepat = None
                else:
                    imscalepat = scalepat.replace('resid', 'image')
                    modscalepat = scalepat.replace('resid', 'model')
                imbasefn = basefn.replace('resid', 'image')
                debug('resid.  imscalepat, imbasefn', imscalepat, imbasefn)
                debug('resid.  modscalepat, modbasefn', modscalepat, modbasefn)
                imfn = get_scaled(imscalepat, fnargs, scaled, imbasefn)
                modfn = get_scaled(modscalepat, fnargs, scaled, modbasefn)
                debug('resid.  im', imfn, 'mod', modfn)
                fn = imfn

            else:
                basefn = D.find_file(imagetag, brick=brickname, band=band)
                fn = get_scaled(scalepat, fnargs, scaled, basefn)

            if fn is None:
                debug('not found: brick', brickname, 'band', band,
                      'with basefn', basefn)
                savecache = False
                continue
            if not os.path.exists(fn):
                debug('Does not exist:', fn)
                savecache = False
                continue
            try:
                bwcs = read_tan_wcs(fn, 0)
            except:
                print('Failed to read WCS:', fn)
                savecache = False
                import traceback
                import sys
                traceback.print_exc(None, sys.stdout)
                continue

            foundany = True
            debug('Reading', fn)
            ok, xx, yy = bwcs.radec2pixelxy(r, d)
            xx = xx.astype(np.int)
            yy = yy.astype(np.int)
            imW, imH = int(bwcs.get_width()), int(bwcs.get_height())
            M = 10
            xlo = np.clip(xx.min() - M, 0, imW)
            xhi = np.clip(xx.max() + M, 0, imW)
            ylo = np.clip(yy.min() - M, 0, imH)
            yhi = np.clip(yy.max() + M, 0, imH)
            if xlo >= xhi or ylo >= yhi:
                continue

            subwcs = bwcs.get_subimage(xlo, ylo, xhi - xlo, yhi - ylo)
            slc = slice(ylo, yhi), slice(xlo, xhi)
            try:
                f = fitsio.FITS(fn)[0]
                img = f[slc]
                del f

                if imagetag == 'resid':
                    f = fitsio.FITS(modfn)[0]
                    mod = f[slc]
                    del f
                    img = img - mod

            except:
                print('Failed to read image and WCS:', fn)
                savecache = False
                import traceback
                import sys
                traceback.print_exc(None, sys.stdout)
                continue

            try:
                Yo, Xo, Yi, Xi, nil = resample_with_wcs(wcs, subwcs, [], 3)
            except OverlapError:
                debug('Resampling exception')
                continue
            rimg[Yo, Xo] += img[Yi, Xi]

            # try:
            #     Yo,Xo,Yi,Xi,[rim] = resample_with_wcs(wcs, subwcs, [img], 3)
            # except OverlapError:
            #     debug('Resampling exception')
            #     continue
            # rimg[Yo,Xo] += rim

            rn[Yo, Xo] += 1
        rimg /= np.maximum(rn, 1)
        rimgs.append(rimg)

    if return_if_not_found and not savecache:
        return

    if get_images and not write_jpeg:
        return rimgs

    if rgbfunc is None:
        from legacypipe.common import get_rgb
        rgbfunc = get_rgb

    rgb = rgbfunc(rimgs, bands, **rgbkwargs)

    if forcecache:
        savecache = True

    if savecache:
        trymakedirs(tilefn)
    else:
        import tempfile
        f, tilefn = tempfile.mkstemp(suffix='.jpg')
        os.close(f)

    # no jpeg output support in matplotlib in some installations...
    if hack_jpeg:
        save_jpeg(tilefn, rgb)
        debug('Wrote', tilefn)
    else:
        import pylab as plt
        plt.imsave(tilefn, rgb)
        debug('Wrote', tilefn)

    if get_images:
        return rimgs

    return send_file(tilefn,
                     'image/jpeg',
                     unlink=(not savecache),
                     filename=filename)
Beispiel #3
0
    wcs = Tan(*[
        float(x) for x in [
            194.954, 27.980, (W + 1) / 2., (H + 1) /
            2., -pixscale, 0, 0, pixscale, W, H
        ]
    ])
    gri = map_sdss(None,
                   1,
                   1,
                   1,
                   1,
                   get_images=True,
                   wcs=wcs,
                   forcescale=0,
                   bestOnly=True)
    #print 'Got', gri
    g, r, i = gri
    print('g', g.shape)

    hdr = fitsio.FITSHDR()
    wcs.add_to_header(hdr)

    fitsio.write('coma-g.fits', g, header=hdr, clobber=True)
    fitsio.write('coma-r.fits', r, header=hdr, clobber=True)
    fitsio.write('coma-i.fits', i, header=hdr, clobber=True)

    bands = 'gri'
    rgb = sdss_rgb(gri, bands)
    save_jpeg('coma.jpg', rgb)