def match_kdtree_catalog(wcs, catfn): from astrometry.libkd.spherematch import ( tree_open, tree_close, tree_build_radec, tree_free, trees_match, tree_permute, ) from astrometry.libkd import spherematch_c from astrometry.util.starutil_numpy import deg2dist, xyztoradec import numpy as np import sys rc, dc = wcs.get_center() rr = wcs.get_radius() kd = tree_open(catfn) kd2 = tree_build_radec(np.array([rc]), np.array([dc])) r = deg2dist(rr) I, J, nil = trees_match(kd, kd2, r, permuted=False) # HACK # I2,J,d = trees_match(kd, kd2, r) xyz = spherematch_c.kdtree_get_positions(kd, I.astype(np.uint32)) # print 'I', I I2 = tree_permute(kd, I) # print 'I2', I2 tree_free(kd2) tree_close(kd) tra, tdec = xyztoradec(xyz) return tra, tdec, I2
def other_passes(self, tile, tiles): ''' Given tile number *tile*, return the obstatus rows for the other passes on this tile center. Returns: *otherpasses*, table object ''' if tiles != self.tiles: from astrometry.libkd.spherematch import match_radec # Could also use the fact that the passes are offset from each other # by a fixed index (15872 for decam)... # Max separation is about 0.6 degrees for DECam... #### FIXME for Mosaic this is much smaller... and the three passes #### for a tile are not necessarily relatively close to each other. I,J,d = match_radec(tile.ra, tile.dec, tiles.ra, tiles.dec, 1.) # Omit 'tile' itself... K = np.flatnonzero(tiles.tileid[J] != tile.tileid) J = J[K] return tiles[J] if self.tiletree is None: from astrometry.libkd.spherematch import tree_build_radec self.tiletree = tree_build_radec(self.tiles.ra, self.tiles.dec) from astrometry.libkd.spherematch import tree_search_radec J = tree_search_radec(self.tiletree, tile.ra, tile.dec, 1.0) # Omit 'tile' itself... K = np.flatnonzero(tiles.tileid[J] != tile.tileid) J = J[K] return tiles[J]
def _match_tile(X): tid, tile_ra, tile_dec, tile_obstime, tile_theta, tile_obsha, match_radius = X loc_ra, loc_dec = xy2radec(hw, tile_ra, tile_dec, tile_obstime, tile_theta, tile_obsha, stuck_x, stuck_y, False, 0) kd = tree_build_radec(loc_ra, loc_dec) I, J, d = trees_match(starkd, kd, match_radius) print('Tile', tid, 'matched', len(I), 'stars') if len(I): res = tid, I, loc_ra[J], loc_dec[J], stuck_loc[J], np.rad2deg( d) * 3600. else: res = None return res
def match_kdtree_catalog(wcs, catfn): from astrometry.libkd.spherematch import tree_open, tree_close, tree_build_radec, tree_free, trees_match, tree_permute from astrometry.libkd import spherematch_c from astrometry.util.starutil_numpy import deg2dist, xyztoradec import numpy as np import sys rc,dc = wcs.get_center() rr = wcs.get_radius() kd = tree_open(catfn) kd2 = tree_build_radec(np.array([rc]), np.array([dc])) r = deg2dist(rr) I,J,nil = trees_match(kd, kd2, r, permuted=False) del kd2 xyz = kd.get_data(I.astype(np.uint32)) I = kd.permute(I) del kd tra,tdec = xyztoradec(xyz) return tra, tdec, I
def bricks_touching_radec_box(self, bricks, ralo, rahi, declo, dechi): ''' Returns an index vector of the bricks that touch the given RA,Dec box. ''' if bricks is None: bricks = self.get_bricks_readonly() if self.cache_tree and bricks == self.bricks: from astrometry.libkd.spherematch import tree_build_radec, tree_search_radec # Use kdtree if self.bricktree is None: self.bricktree = tree_build_radec(bricks.ra, bricks.dec) # brick size radius = np.sqrt(2.)/2. * self.bricksize # + RA,Dec box size radius = radius + degrees_between(ralo, declo, rahi, dechi) / 2. dec = (dechi + declo) / 2. c = (np.cos(np.deg2rad(rahi)) + np.cos(np.deg2rad(ralo))) / 2. s = (np.sin(np.deg2rad(rahi)) + np.sin(np.deg2rad(ralo))) / 2. ra = np.rad2deg(np.arctan2(s, c)) J = tree_search_radec(self.bricktree, ra, dec, radius) I = J[np.nonzero((bricks.ra1[J] <= rahi ) * (bricks.ra2[J] >= ralo) * (bricks.dec1[J] <= dechi) * (bricks.dec2[J] >= declo))[0]] return I if rahi < ralo: # Wrap-around print('In Dec slice:', len(np.flatnonzero((bricks.dec1 <= dechi) * (bricks.dec2 >= declo)))) print('Above RAlo=', ralo, ':', len(np.flatnonzero(bricks.ra2 >= ralo))) print('Below RAhi=', rahi, ':', len(np.flatnonzero(bricks.ra1 <= rahi))) print('In RA slice:', len(np.nonzero(np.logical_or(bricks.ra2 >= ralo, bricks.ra1 <= rahi)))) I, = np.nonzero(np.logical_or(bricks.ra2 >= ralo, bricks.ra1 <= rahi) * (bricks.dec1 <= dechi) * (bricks.dec2 >= declo)) print('In RA&Dec slice', len(I)) else: I, = np.nonzero((bricks.ra1 <= rahi ) * (bricks.ra2 >= ralo) * (bricks.dec1 <= dechi) * (bricks.dec2 >= declo)) return I
def match_kdtree_catalog(wcs, catfn): from astrometry.libkd.spherematch import tree_open, tree_close, tree_build_radec, tree_free, trees_match, tree_permute from astrometry.libkd import spherematch_c from astrometry.util.starutil_numpy import deg2dist, xyztoradec import numpy as np import sys rc, dc = wcs.get_center() rr = wcs.get_radius() kd = tree_open(catfn) kd2 = tree_build_radec(np.array([rc]), np.array([dc])) r = deg2dist(rr) I, J, nil = trees_match(kd, kd2, r, permuted=False) # HACK #I2,J,d = trees_match(kd, kd2, r) xyz = spherematch_c.kdtree_get_positions(kd, I.astype(np.uint32)) #print 'I', I I2 = tree_permute(kd, I) #print 'I2', I2 tree_free(kd2) tree_close(kd) tra, tdec = xyztoradec(xyz) return tra, tdec, I2
def plot_wcs_outline(wcsfn, plotfn, W=256, H=256, width=36, zoom=True, zoomwidth=3.6, grid=10, hd=False, hd_labels=False, tycho2=False): anutil.log_init(3) #anutil.log_set_level(3) wcs = anutil.Tan(wcsfn, 0) ra, dec = wcs.radec_center() plot = ps.Plotstuff(outformat='png', size=(W, H), rdw=(ra, dec, width)) plot.linestep = 1. plot.color = 'verydarkblue' plot.plot('fill') plot.fontsize = 12 #plot.color = 'gray' # dark gray plot.rgb = (0.3, 0.3, 0.3) if grid is not None: plot.plot_grid(*([grid] * 4)) plot.rgb = (0.4, 0.6, 0.4) ann = plot.annotations ann.NGC = ann.bright = ann.HD = 0 ann.constellations = 1 ann.constellation_labels = 1 ann.constellation_labels_long = 1 plot.plot('annotations') plot.stroke() ann.constellation_labels = 0 ann.constellation_labels_long = 0 ann.constellation_lines = 0 ann.constellation_markers = 1 plot.markersize = 3 plot.rgb = (0.4, 0.6, 0.4) plot.plot('annotations') plot.fill() ann.constellation_markers = 0 ann.bright_labels = False ann.bright = True plot.markersize = 2 if zoom >= 2: ann.bright_labels = True plot.plot('annotations') ann.bright = False ann.bright_labels = False plot.fill() if hd: ann.HD = True ann.HD_labels = hd_labels ps.plot_annotations_set_hd_catalog(ann, settings.HENRY_DRAPER_CAT) plot.plot('annotations') plot.stroke() ann.HD = False ann.HD_labels = False if tycho2 and settings.TYCHO2_KD: from astrometry.libkd.spherematch import tree_open, tree_close, tree_build_radec, tree_free, trees_match from astrometry.libkd import spherematch_c from astrometry.util.starutil_numpy import deg2dist, xyztoradec import numpy as np import sys kd = tree_open(settings.TYCHO2_KD) # this is a bit silly: build a tree with a single point, then do match() kd2 = tree_build_radec(np.array([ra]), np.array([dec])) r = deg2dist(width * np.sqrt(2.) / 2.) #r = deg2dist(wcs.radius()) I, nil, nil = trees_match(kd, kd2, r, permuted=False) del nil #print 'Matched', len(I) xyz = spherematch_c.kdtree_get_positions(kd, I) del I tree_free(kd2) tree_close(kd) #print >>sys.stderr, 'Got', xyz.shape, xyz tra, tdec = xyztoradec(xyz) #print >>sys.stderr, 'RA,Dec', ra,dec plot.apply_settings() for r, d in zip(tra, tdec): plot.marker_radec(r, d) plot.fill() ann.NGC = 1 plot.plot('annotations') ann.NGC = 0 plot.color = 'white' plot.lw = 3 out = plot.outline out.wcs_file = wcsfn plot.plot('outline') if zoom: # MAGIC width, height are arbitrary zoomwcs = anutil.anwcs_create_box(ra, dec, zoomwidth, 1000, 1000) out.wcs = zoomwcs plot.lw = 1 plot.dashed(3) plot.plot('outline') plot.write(plotfn)
print('Kd bounding-box:', spherematch.tree_bbox(kd)) print('Kd bounding-box:', kd.bbox) print('Kd data:', spherematch.tree_data(kd, np.array([0,3,5]).astype(np.uint32))) print('Kd data:', kd.get_data(np.array([0,3,5]).astype(np.uint32))) print('Permute:', spherematch.tree_permute(kd, np.array([3,5,7]).astype(np.int32))) print('Permute:', kd.permute(np.array([0,99,199]).astype(np.int32))) ra,dec = np.meshgrid(np.arange(0, 360), np.arange(-90, 91, 1)) ra1 = ra.ravel() dec1 = dec.ravel() rdkd1 = spherematch.tree_build_radec(ra1, dec1) print('RdKd:', rdkd1.n, rdkd1.bbox) ra2 = np.random.uniform(-10, 10, size=1000) dec2 = np.random.uniform(-10, 10, size=1000) rdkd2 = spherematch.tree_build_radec(ra2, dec2) I = spherematch.tree_search_radec(rdkd1, ra2[0], dec2[0], 2.) print('search_radec:', I) I,J,d = spherematch.match_radec(ra1, dec1, ra2, dec2, 1.) print('Matches:', len(I)) I,J,d = spherematch.match_radec(ra1, dec1, ra2, dec2, 1., nearest=True) print('Nearest matches:', len(I))
for i in range(len(T)): if not plot.wcs.is_inside(T.ra[i], T.dec[i]): continue ann.add_target(T.ra[i], T.dec[i], 'Abell %i' % T.aco[i]) if opt.t2cat: from astrometry.libkd.spherematch import tree_open, tree_close, tree_build_radec, tree_free, trees_match from astrometry.libkd import spherematch_c from astrometry.util.starutil_numpy import deg2dist, xyztoradec import numpy as np import sys wcs = plot.wcs rc,dc = wcs.get_center() rr = wcs.get_radius() kd = tree_open(opt.t2cat) kd2 = tree_build_radec(np.array([rc]), np.array([dc])) r = deg2dist(rr) I,J,d = trees_match(kd, kd2, r, permuted=False) # HACK I2,J,d = trees_match(kd, kd2, r) xyz = spherematch_c.kdtree_get_positions(kd, I) tree_free(kd2) tree_close(kd) tra,tdec = xyztoradec(xyz) T = fits_table(opt.t2cat, hdu=6) for r,d,t1,t2,t3 in zip(tra,tdec, T.tyc1[I2], T.tyc2[I2], T.tyc3[I2]): if not plot.wcs.is_inside(r, d): continue ann.add_target(r, d, 'Tycho-2 %i-%i-%i' % (t1,t2,t3))
def map_decam_depth(req, ver, zoom, x, y, savecache=False, band=None, ignoreCached=False): global Tdepth global Tdepthkd if band is None: band = req.GET.get('band') if not band in ['g', 'r', 'z']: raise RuntimeError('Invalid band') tag = 'decam-depth-%s' % band 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: print('Cached:', tilefn) return send_file(tilefn, 'image/jpeg', expires=oneyear, modsince=req.META.get('HTTP_IF_MODIFIED_SINCE')) from astrometry.util.util import Tan from astrometry.libkd.spherematch import match_radec from astrometry.libkd.spherematch import tree_build_radec, tree_search_radec from astrometry.util.fits import fits_table from astrometry.util.starutil_numpy import degrees_between import numpy as np import fitsio try: wcs, W, H, zoomscale, zoom, x, y = get_tile_wcs(zoom, x, y) except RuntimeError as e: return HttpResponse(e.strerror) 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:] r, d = wcs.pixelxy2radec(W / 2, H / 2)[-2:] rad = max(degrees_between(r, d, rlo, d1), degrees_between(r, d, rhi, d2)) if Tdepth is None: T = fits_table(os.path.join(basedir, 'decals-zpt-nondecals.fits'), columns=[ 'ccdra', 'ccddec', 'arawgain', 'avsky', 'ccdzpt', 'filter', 'crpix1', 'crpix2', 'crval1', 'crval2', 'cd1_1', 'cd1_2', 'cd2_1', 'cd2_2', 'naxis1', 'naxis2', 'exptime', 'fwhm' ]) T.rename('ccdra', 'ra') T.rename('ccddec', 'dec') Tdepth = {} Tdepthkd = {} for b in ['g', 'r', 'z']: Tdepth[b] = T[T.filter == b] Tdepthkd[b] = tree_build_radec(Tdepth[b].ra, Tdepth[b].dec) T = Tdepth[band] Tkd = Tdepthkd[band] #I,J,d = match_radec(T.ra, T.dec, r, d, rad + 0.2) I = tree_search_radec(Tkd, r, d, rad + 0.2) print(len(I), 'CCDs in range') if len(I) == 0: from django.http import HttpResponseRedirect return HttpResponseRedirect(settings.STATIC_URL + 'blank.jpg') depthiv = np.zeros((H, W), np.float32) for t in T[I]: twcs = Tan(*[ float(x) for x in [ t.crval1, t.crval2, t.crpix1, t.crpix2, t.cd1_1, t.cd1_2, t.cd2_1, t.cd2_2, t.naxis1, t.naxis2 ] ]) w, h = t.naxis1, t.naxis2 r, d = twcs.pixelxy2radec([1, 1, w, w], [1, h, h, 1]) ok, x, y = wcs.radec2pixelxy(r, d) #print 'x,y coords of CCD:', x, y x0 = int(x.min()) x1 = int(x.max()) y0 = int(y.min()) y1 = int(y.max()) if y1 < 0 or x1 < 0 or x0 >= W or y0 >= H: continue readnoise = 10. # e-; 7.0 to 15.0 according to DECam Data Handbook skysig = np.sqrt(t.avsky * t.arawgain + readnoise**2) / t.arawgain zpscale = 10.**((t.ccdzpt - 22.5) / 2.5) * t.exptime sig1 = skysig / zpscale psf_sigma = t.fwhm / 2.35 # point-source depth psfnorm = 1. / (2. * np.sqrt(np.pi) * psf_sigma) detsig1 = sig1 / psfnorm #print '5-sigma point-source depth:', NanoMaggies.nanomaggiesToMag(detsig1 * 5.) div = 1 / detsig1**2 depthiv[max(y0, 0):min(y1, H), max(x0, 0):min(x1, W)] += div ptsrc = -2.5 * (np.log10(np.sqrt(1. / depthiv) * 5) - 9) ptsrc[depthiv == 0] = 0. if savecache: trymakedirs(tilefn) else: import tempfile f, tilefn = tempfile.mkstemp(suffix='.jpg') os.close(f) import pylab as plt plt.imsave(tilefn, ptsrc, vmin=22., vmax=25., cmap='hot') #nipy_spectral') return send_file(tilefn, 'image/jpeg', unlink=(not savecache))
def plot_wcs_outline(wcsfn, plotfn, W=256, H=256, width=36, zoom=True, zoomwidth=3.6, grid=10, hd=False, hd_labels=False, tycho2=False): anutil.log_init(3) #anutil.log_set_level(3) wcs = anutil.Tan(wcsfn, 0) ra,dec = wcs.radec_center() plot = ps.Plotstuff(outformat='png', size=(W, H), rdw=(ra,dec,width)) plot.linestep = 1. plot.color = 'verydarkblue' plot.plot('fill') plot.fontsize = 12 #plot.color = 'gray' # dark gray plot.rgb = (0.3,0.3,0.3) if grid is not None: plot.plot_grid(*([grid]*4)) plot.rgb = (0.4, 0.6, 0.4) ann = plot.annotations ann.NGC = ann.bright = ann.HD = 0 ann.constellations = 1 ann.constellation_labels = 1 ann.constellation_labels_long = 1 plot.plot('annotations') plot.stroke() ann.constellation_labels = 0 ann.constellation_labels_long = 0 ann.constellation_lines = 0 ann.constellation_markers = 1 plot.markersize = 3 plot.rgb = (0.4, 0.6, 0.4) plot.plot('annotations') plot.fill() ann.constellation_markers = 0 ann.bright_labels = False ann.bright = True plot.markersize = 2 if zoom >= 2: ann.bright_labels = True plot.plot('annotations') ann.bright = False ann.bright_labels = False plot.fill() if hd: ann.HD = True ann.HD_labels = hd_labels ps.plot_annotations_set_hd_catalog(ann, settings.HENRY_DRAPER_CAT) plot.plot('annotations') plot.stroke() ann.HD = False ann.HD_labels = False if tycho2: from astrometry.libkd.spherematch import tree_open, tree_close, tree_build_radec, tree_free, trees_match from astrometry.libkd import spherematch_c from astrometry.util.starutil_numpy import deg2dist, xyztoradec import numpy as np import sys kd = tree_open(settings.TYCHO2_KD) # this is a bit silly: build a tree with a single point, then do match() kd2 = tree_build_radec(np.array([ra]), np.array([dec])) r = deg2dist(width * np.sqrt(2.) / 2.) #r = deg2dist(wcs.radius()) I,J,d = trees_match(kd, kd2, r, permuted=False) del J del d #print 'Matched', len(I) xyz = spherematch_c.kdtree_get_positions(kd, I) del I tree_free(kd2) tree_close(kd) #print >>sys.stderr, 'Got', xyz.shape, xyz tra,tdec = xyztoradec(xyz) #print >>sys.stderr, 'RA,Dec', ra,dec plot.apply_settings() for r,d in zip(tra,tdec): plot.marker_radec(r,d) plot.fill() ann.NGC = 1 plot.plot('annotations') ann.NGC = 0 plot.color = 'white' plot.lw = 3 out = plot.outline out.wcs_file = wcsfn plot.plot('outline') if zoom: # MAGIC width, height are arbitrary zoomwcs = anutil.anwcs_create_box(ra, dec, zoomwidth, 1000,1000) out.wcs = zoomwcs plot.lw = 1 plot.dashed(3) plot.plot('outline') plot.write(plotfn)
def get_healpix_tree(self, healpix): from astrometry.util.fits import fits_table fname = self.fnpattern % dict(hp=healpix) tab = fits_table(fname, columns=self.columns) kd = tree_build_radec(tab.ra, tab.dec) return (kd, tab)
wcs.write_to(base + '-wcs.fits') #bomb() fns = keepfns names = [fn.replace('-bright.fits', '') for fn in fns] outlines = [getwcsoutline(wcs) for wcs in WCS] overlaps, areas = find_overlaps(outlines) print('Reading tables...') TT = [fits_table(fn) for fn in fns] print('Building trees...') kds = [tree_build_radec(T.ra, T.dec) for T in TT] for T, name in zip(TT, names): T.name = np.array([name] * len(T)) allra = np.hstack([T.ra for T in TT]) alldec = np.hstack([T.dec for T in TT]) minra = np.min(allra) maxra = np.max(allra) mindec = np.min(alldec) maxdec = np.max(alldec) print('RA,Dec range:', minra, maxra, mindec, maxdec) plothist(allra, alldec) plt.axis([maxra, minra, mindec, maxdec])
def map_decam_depth(req, ver, zoom, x, y, savecache=False, band=None, ignoreCached=False): global Tdepth global Tdepthkd if band is None: band = req.GET.get('band') if not band in ['g','r','z']: raise RuntimeError('Invalid band') tag = 'decam-depth-%s' % band 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: print 'Cached:', tilefn return send_file(tilefn, 'image/jpeg', expires=oneyear, modsince=req.META.get('HTTP_IF_MODIFIED_SINCE')) from astrometry.util.util import Tan from astrometry.libkd.spherematch import match_radec from astrometry.libkd.spherematch import tree_build_radec, tree_search_radec from astrometry.util.fits import fits_table from astrometry.util.starutil_numpy import degrees_between import numpy as np import fitsio try: wcs, W, H, zoomscale, zoom,x,y = get_tile_wcs(zoom, x, y) except RuntimeError as e: return HttpResponse(e.strerror) 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:] r,d = wcs.pixelxy2radec(W/2, H/2)[-2:] rad = max(degrees_between(r, d, rlo, d1), degrees_between(r, d, rhi, d2)) if Tdepth is None: T = fits_table(os.path.join(basedir, 'decals-zpt-nondecals.fits'), columns=['ccdra','ccddec','arawgain', 'avsky', 'ccdzpt', 'filter', 'crpix1','crpix2', 'crval1','crval2','cd1_1','cd1_2', 'cd2_1','cd2_2', 'naxis1', 'naxis2', 'exptime', 'fwhm']) T.rename('ccdra', 'ra') T.rename('ccddec', 'dec') Tdepth = {} Tdepthkd = {} for b in ['g','r','z']: Tdepth[b] = T[T.filter == b] Tdepthkd[b] = tree_build_radec(Tdepth[b].ra, Tdepth[b].dec) T = Tdepth[band] Tkd = Tdepthkd[band] #I,J,d = match_radec(T.ra, T.dec, r, d, rad + 0.2) I = tree_search_radec(Tkd, r, d, rad + 0.2) print len(I), 'CCDs in range' if len(I) == 0: from django.http import HttpResponseRedirect return HttpResponseRedirect(settings.STATIC_URL + 'blank.jpg') depthiv = np.zeros((H,W), np.float32) for t in T[I]: twcs = Tan(*[float(x) for x in [ t.crval1, t.crval2, t.crpix1, t.crpix2, t.cd1_1, t.cd1_2, t.cd2_1, t.cd2_2, t.naxis1, t.naxis2]]) w,h = t.naxis1, t.naxis2 r,d = twcs.pixelxy2radec([1,1,w,w], [1,h,h,1]) ok,x,y = wcs.radec2pixelxy(r, d) #print 'x,y coords of CCD:', x, y x0 = int(x.min()) x1 = int(x.max()) y0 = int(y.min()) y1 = int(y.max()) if y1 < 0 or x1 < 0 or x0 >= W or y0 >= H: continue readnoise = 10. # e-; 7.0 to 15.0 according to DECam Data Handbook skysig = np.sqrt(t.avsky * t.arawgain + readnoise**2) / t.arawgain zpscale = 10.**((t.ccdzpt - 22.5)/2.5) * t.exptime sig1 = skysig / zpscale psf_sigma = t.fwhm / 2.35 # point-source depth psfnorm = 1./(2. * np.sqrt(np.pi) * psf_sigma) detsig1 = sig1 / psfnorm #print '5-sigma point-source depth:', NanoMaggies.nanomaggiesToMag(detsig1 * 5.) div = 1 / detsig1**2 depthiv[max(y0,0):min(y1,H), max(x0,0):min(x1,W)] += div ptsrc = -2.5 * (np.log10(np.sqrt(1./depthiv) * 5) - 9) ptsrc[depthiv == 0] = 0. if savecache: trymakedirs(tilefn) else: import tempfile f,tilefn = tempfile.mkstemp(suffix='.jpg') os.close(f) import pylab as plt plt.imsave(tilefn, ptsrc, vmin=22., vmax=25., cmap='hot')#nipy_spectral') return send_file(tilefn, 'image/jpeg', unlink=(not savecache))
def map_sdss(req, ver, zoom, x, y, savecache=None, tag='sdss', get_images=False, ignoreCached=False, wcs=None, forcecache=False, forcescale=None, **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 bands = 'gri' 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] 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))
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))
def find_alignments(fns, wcsfns, gaia_fn, aff_fn, aligned_fn): from astrometry.libkd.spherematch import tree_build_radec, trees_match from astrometry.libkd.spherematch import match_radec from astrometry.util.plotutils import plothist from astrometry.util.util import Tan import fitsio from astrom_common import getwcsoutline from singles import find_overlaps if True: WCS = [] for fn in wcsfns: wcs = Tan(fn) WCS.append(wcs) names = [fn.replace('-bright.fits', '') for fn in fns] outlines = [getwcsoutline(wcs) for wcs in WCS] overlaps, areas = find_overlaps(outlines) print('Reading tables...') TT = [fits_table(fn) for fn in fns] print('Building trees...') kds = [tree_build_radec(T.ra, T.dec) for T in TT] for T, name in zip(TT, names): T.name = np.array([name] * len(T)) allra = np.hstack([T.ra for T in TT]) alldec = np.hstack([T.dec for T in TT]) minra = np.min(allra) maxra = np.max(allra) mindec = np.min(alldec) maxdec = np.max(alldec) print('RA,Dec range:', minra, maxra, mindec, maxdec) plothist(allra, alldec) plt.axis([maxra, minra, mindec, maxdec]) plt.xlabel('RA (deg)') plt.ylabel('Dec (deg)') plt.savefig('match-all.png') Tref = fits_table(gaia_fn) r_arcsec = 0.2 I, J, d = match_radec(Tref.ra, Tref.dec, allra, alldec, r_arcsec / 3600.) dec = alldec[J] cosdec = np.cos(np.deg2rad(dec)) dr = (Tref.ra[I] - allra[J]) * cosdec * 3600. dd = (Tref.dec[I] - alldec[J]) * 3600. plt.clf() rr = (-r_arcsec * 1000, +r_arcsec * 1000) plothist(dr * 1000., dd * 1000., nbins=100, range=(rr, rr)) plt.xlabel('dRA (milli-arcsec)') plt.ylabel('dDec (milli-arcsec)') plt.savefig('match-all-ref-before.png') # Initial matching of all stars r_arcsec = 0.2 I, J, d = match_radec(allra, alldec, allra, alldec, r_arcsec / 3600., notself=True) dec = alldec[I] cosdec = np.cos(np.deg2rad(dec)) dr = (allra[I] - allra[J]) * cosdec * 3600. dd = (alldec[I] - alldec[J]) * 3600. plt.clf() rr = (-r_arcsec * 1000, +r_arcsec * 1000) plothist(dr * 1000., dd * 1000., nbins=100, range=(rr, rr)) plt.xlabel('dRA (milli-arcsec)') plt.ylabel('dDec (milli-arcsec)') plt.savefig('match-all-before.png') hulls = [] from scipy.spatial import ConvexHull for T in TT: hull = ConvexHull(np.vstack((T.ra, T.dec)).T) ra = T.ra[hull.vertices] ra = np.append(ra, ra[0]) dec = T.dec[hull.vertices] dec = np.append(dec, dec[0]) hulls.append((ra, dec)) aligns = {} #for i in []: for i in range(len(kds)): for j in range(i + 1, len(kds)): print('Matching trees', i, 'and', j) r_arcsec = 0.2 radius = np.deg2rad(r_arcsec / 3600) I, J, d2 = trees_match(kds[i], kds[j], radius) print(len(I), 'matches') if len(I) == 0: continue Ti = TT[i] Tj = TT[j] dec = Ti[I].dec cosdec = np.cos(np.deg2rad(dec)) dr = (Ti[I].ra - Tj[J].ra) * cosdec * 3600. dd = (Ti[I].dec - Tj[J].dec) * 3600. if False: al = Alignment(Ti, Tj, searchradius=r_arcsec) print('Aligning...') if not al.shift(): print('Failed to find Alignment between fields') continue aligns[(i, j)] = al plt.clf() plotalignment(al) plt.savefig('match-align-%02i-%02i.png' % (i, j)) plt.clf() #plothist(np.append(Ti.ra, Tj.ra), np.append(Ti.dec, Tj.dec), docolorbar=False, doclf=False, dohot=False, # imshowargs=dict(cmap=antigray)) plothist(Ti.ra[I], Ti.dec[I], docolorbar=False, doclf=False) r, d = hulls[i] plt.plot(r, d, 'r-') r, d = hulls[j] plt.plot(r, d, 'b-') mra = Ti.ra[I] mdec = Ti.dec[I] mnra = np.min(mra) mxra = np.max(mra) mndec = np.min(mdec) mxdec = np.max(mdec) plt.plot([mnra, mnra, mxra, mxra, mnra], [mndec, mxdec, mxdec, mndec, mndec], 'g-') plt.axis([maxra, minra, mindec, maxdec]) plt.xlabel('RA (deg)') plt.ylabel('Dec (deg)') plt.savefig('match-radec-%02i-%02i.png' % (i, j)) plt.clf() rr = (-r_arcsec, +r_arcsec) plothist(dr, dd, nbins=100, range=(rr, rr)) plt.xlabel('dRA (arcsec)') plt.ylabel('dDec (arcsec)') plt.savefig('match-dradec-%02i-%02i.png' % (i, j)) #for roundi,(Nk,R) in enumerate(NkeepRads): refrad = 0.15 targetrad = 0.005 ps = PlotSequence('shift') from astrom_intra import intrabrickshift from singles import plot_all_alignments #Rads = [0.25, 0.1] Rads = [0.2, 0.050, 0.020] #Rads = [0.1] affs = None # this is the reference point around which rotations take place, NOT reference catalog stars. refrd = None for roundi, R in enumerate(Rads): if roundi > 0: refrad = 0.050 TT1 = TT nb = int(np.ceil(R / targetrad)) nb = max(nb, 5) if nb % 2 == 0: nb += 1 print('Round', roundi + 1, ': matching with radius', R) print('Nbins:', nb) # kwargs to pass to intrabrickshift ikwargs = {} minoverlap = 0.01 tryoverlaps = (overlaps > minoverlap) ikwargs.update( do_affine=True, #mp=mp, #alignplotargs=dict(bins=25), alignplotargs=dict(bins=50), overlaps=tryoverlaps) ikwargs.update(ref=Tref, refrad=refrad) # kwargs to pass to Alignment akwargs = {} i1 = intrabrickshift(TT1, matchradius=R, refradecs=refrd, align_kwargs=dict(histbins=nb, **akwargs), **ikwargs) refrd = i1.get_reference_radecs() filts = ['' for n in names] ap = i1.alplotgrid Nk = 100000 plot_all_alignments(ap, R * 1000, refrad * 1000, roundi + 1, names, filts, ps, overlaps, outlines, Nk) for T, aff in zip(TT, i1.affines): T.ra, T.dec = aff.apply(T.ra, T.dec) if affs is None: affs = i1.affines else: for a, a2 in zip(affs, i1.affines): a.add(a2) from astrom_common import Affine T = Affine.toTable(affs) T.filenames = fns #T.flt = fltfns #T.gst = gstfns #T.chip = chips # FAKE -- used as a name in alignment_plots T.gst = np.array([n + '.gst.fits' for n in names]) T.writeto(aff_fn) # Final matching of all stars allra = np.hstack([T.ra for T in TT]) alldec = np.hstack([T.dec for T in TT]) r_arcsec = 0.2 I, J, d = match_radec(allra, alldec, allra, alldec, r_arcsec / 3600., notself=True) dec = alldec[I] cosdec = np.cos(np.deg2rad(dec)) dr = (allra[I] - allra[J]) * cosdec * 3600. dd = (alldec[I] - alldec[J]) * 3600. plt.clf() rr = (-r_arcsec * 1000, +r_arcsec * 1000) plothist(dr * 1000., dd * 1000., nbins=100, range=(rr, rr)) plt.xlabel('dRA (milli-arcsec)') plt.ylabel('dDec (milli-arcsec)') plt.savefig('match-all-after.png') I, J, d = match_radec(Tref.ra, Tref.dec, allra, alldec, r_arcsec / 3600.) dec = alldec[J] cosdec = np.cos(np.deg2rad(dec)) dr = (Tref.ra[I] - allra[J]) * cosdec * 3600. dd = (Tref.dec[I] - alldec[J]) * 3600. plt.clf() rr = (-r_arcsec * 1000, +r_arcsec * 1000) plothist(dr * 1000., dd * 1000., nbins=100, range=(rr, rr)) plt.xlabel('dRA (milli-arcsec)') plt.ylabel('dDec (milli-arcsec)') plt.savefig('match-all-ref-after.png') r_arcsec = 0.02 I, J, d = match_radec(allra, alldec, allra, alldec, r_arcsec / 3600., notself=True) dec = alldec[I] cosdec = np.cos(np.deg2rad(dec)) dr = (allra[I] - allra[J]) * cosdec * 3600. dd = (alldec[I] - alldec[J]) * 3600. plt.clf() rr = (-r_arcsec * 1000, +r_arcsec * 1000) plothist(dr * 1000., dd * 1000., nbins=100, range=(rr, rr)) plt.xlabel('dRA (milli-arcsec)') plt.ylabel('dDec (milli-arcsec)') plt.savefig('match-all-after2.png') T = fits_table() T.ra = allra T.dec = alldec for col in [ 'f814w_vega', 'f475w_vega', 'f336w_vega', 'f275w_vega', 'f110w_vega', 'f160w_vega', 'name' ]: T.set(col, np.hstack([t.get(col) for t in TT])) T.writeto(aligned_fn) if False: from singles import alignment_plots dataset = 'M31' Nkeep = 100000 R = 0.1 minoverlap = 0.01 perfield = False nocache = True from astrometry.util.multiproc import multiproc mp = multiproc() filts = ['F475W' for n in names] chips = [-1] * len(names) exptimes = [1] * len(names) Nall = [0] * len(names) rd = (minra, maxra, mindec, maxdec) cnames = names meta = (chips, names, cnames, filts, exptimes, Nall, rd) alignment_plots(afffn, dataset, Nkeep, 0, R, minoverlap, perfield, nocache, mp, 0, tables=(TT, outlines, meta), lexsort=False)
def main(): os.environ['DESIMODEL'] = '/global/homes/d/dstn/desimodel-data' global hw global stuck_x global stuck_y global stuck_loc global starkd hw = load_hardware() # From fiberassign/stucksky.py: find X,Y positions of stuck positioners. # (grab the hw dictionaries once -- these are python wrappers over C++ so not simple accessors) state = hw.state devtype = hw.loc_device_type stuck_loc = [ loc for loc in hw.locations if (((state[loc] & (FIBER_STATE_STUCK | FIBER_STATE_BROKEN) ) == FIBER_STATE_STUCK) and (devtype[loc] == 'POS')) ] print(len(stuck_loc), 'stuck positioners') theta_pos = hw.loc_theta_pos theta_off = hw.loc_theta_offset phi_pos = hw.loc_phi_pos phi_off = hw.loc_phi_offset stuck_theta = [theta_pos[loc] + theta_off[loc] for loc in stuck_loc] stuck_phi = [phi_pos[loc] + phi_off[loc] for loc in stuck_loc] curved_mm = hw.loc_pos_curved_mm theta_arm = hw.loc_theta_arm phi_arm = hw.loc_phi_arm theta_min = hw.loc_theta_min theta_max = hw.loc_theta_max phi_min = hw.loc_phi_min phi_max = hw.loc_phi_max # Convert positioner angle orientations to curved focal surface X / Y (not CS5) # Note: we could add some methods to the python bindings to vectorize this or make it less clunky... stuck_x = np.zeros(len(stuck_loc)) stuck_y = np.zeros(len(stuck_loc)) for iloc, (loc, theta, phi) in enumerate(zip(stuck_loc, stuck_theta, stuck_phi)): loc_x, loc_y = hw.thetaphi_to_xy(curved_mm[loc], theta, phi, theta_arm[loc], phi_arm[loc], theta_off[loc], phi_off[loc], theta_min[loc], phi_min[loc], theta_max[loc], phi_max[loc], True) stuck_x[iloc] = loc_x stuck_y[iloc] = loc_y tiles = Table.read( '/global/cfs/cdirs/desi/target/surveyops/ops/tiles-main.ecsv') print(len(tiles), 'tiles') # Deduplicate tiles with same RA,Dec center tilera = tiles['RA'] tiledec = tiles['DEC'] tileid = tiles['TILEID'] rdtile = {} tilemap = {} for tid, r, d in zip(tileid, tilera, tiledec): key = r, d if key in rdtile: # already seen a tile with this RA,Dec; point to it tilemap[tid] = rdtile[key] else: rdtile[key] = tid del rdtile tnow = datetime.now() tile_obstime = tnow.isoformat(timespec='seconds') mjd = Time(tnow).mjd stars = fits_table( '/global/cfs/cdirs/cosmo/data/legacysurvey/dr9/masking/gaia-mask-dr9.fits.gz' ) print(len(stars), 'stars for masking') print('Moving to MJD', mjd) ra, dec = radec_at_mjd(stars.ra, stars.dec, stars.ref_epoch.astype(float), stars.pmra, stars.pmdec, stars.parallax, mjd) assert (np.all(np.isfinite(ra))) assert (np.all(np.isfinite(dec))) stars.ra = ra stars.dec = dec print('Building kd-tree...') starkd = tree_build_radec(stars.ra, stars.dec) match_radius = deg2dist(30. / 3600.) stuck_loc = np.array(stuck_loc) allresults = {} mp = multiproc(32) print('Building arg lists...') args = [] for tid, tile_ra, tile_dec, tile_obsha in zip(tileid, tilera, tiledec, tiles['DESIGNHA']): # skip duplicate tiles if tid in tilemap: continue # "fieldrot" tile_theta = field_rotation_angle(tile_ra, tile_dec, mjd) args.append((tid, tile_ra, tile_dec, tile_obstime, tile_theta, tile_obsha, match_radius)) print('Matching', len(args), 'unique tile RA,Decs in parallel...') res = mp.map(_match_tile, args) print('Organizing results...') T = fits_table() T.tileid = [] T.loc = [] T.petal = [] T.device = [] T.fiber = [] T.pos_ra = [] T.pos_dec = [] T.star_ra = [] T.star_dec = [] T.dist_arcsec = [] T.mask_mag = [] loc_to_petal = hw.loc_petal loc_to_device = hw.loc_device loc_to_fiber = hw.loc_fiber for vals in res: if vals is None: continue tileid, I, pos_ra, pos_dec, pos_loc, dists = vals T.tileid.extend([tileid] * len(I)) T.loc.extend(pos_loc) for loc in pos_loc: T.petal.append(loc_to_petal[loc]) T.device.append(loc_to_device[loc]) T.fiber.append(loc_to_fiber[loc]) T.pos_ra.extend(pos_ra) T.pos_dec.extend(pos_dec) T.star_ra.extend(stars.ra[I]) T.star_dec.extend(stars.dec[I]) T.dist_arcsec.extend(dists) T.mask_mag.extend(stars.mask_mag[I]) T.to_np_arrays() T.writeto('stuck-on-stars.fits')