def __init__(self, wcs, hdu=0): ''' Creates a new ``FitsWcs`` given a :class:`~astrometry.util.util.Tan` object. To create one of these from a filename and FITS HDU extension, :: from astrometry.util.util import Tan fn = 'my-file.fits' ext = 0 TanWcs(Tan(fn, ext)) To create one from WCS parameters, tanwcs = Tan(crval1, crval2, crpix1, crpix2, cd11, cd12, cd21, cd22, imagew, imageh) TanWcs(tanwcs) ''' if hasattr(self, 'x0'): print('TanWcs has an x0 attr:', self.x0) self.x0 = 0 self.y0 = 0 if isinstance(wcs, basestring): from astrometry.util.util import Tan wcs = Tan(wcs, hdu) super(TanWcs, self).__init__(wcs) # ParamList keeps its params in a list; we don't want to do that. del self.vals
def read_tan_wcs(sourcefn, ext, hdr=None, W=None, H=None, fitsfile=None): from astrometry.util.util import Tan if not os.path.exists(sourcefn): return None wcs = read_tansip_wcs(sourcefn, ext, hdr=hdr, W=W, H=H, tansip=Tan) if wcs is None: import fitsio # maybe gzipped; try fitsio header. if hdr is None: hdr = fitsio.read_header(sourcefn, ext) if W is None or H is None: if fitsfile is None: F = fitsio.FITS(sourcefn) else: F = fitsfile info = F[ext].get_info() H,W = info['dims'] # PS1 wonky WCS if (not 'CD1_1' in hdr) and ('PC001001' in hdr): cdelt1 = hdr['CDELT1'] cdelt2 = hdr['CDELT2'] # ???? cd11 = hdr['PC001001'] * cdelt1 cd12 = hdr['PC001002'] * cdelt1 cd21 = hdr['PC002001'] * cdelt2 cd22 = hdr['PC002002'] * cdelt2 else: cd11,cd12,cd21,cd22 = hdr['CD1_1'], hdr['CD1_2'], hdr['CD2_1'], hdr['CD2_2'], wcs = Tan(*[float(x) for x in [ hdr['CRVAL1'], hdr['CRVAL2'], hdr['CRPIX1'], hdr['CRPIX2'], cd11, cd12, cd21, cd22, W, H]]) return wcs
def unwise_tile_wcs(ra, dec, W=2048, H=2048, pixscale=2.75): ''' Returns a Tan WCS object at the given RA,Dec center, axis aligned, with the given pixel W,H and pixel scale in arcsec/pixel. ''' cowcs = Tan(ra, dec, (W + 1) / 2., (H + 1) / 2., -pixscale / 3600., 0., 0., pixscale / 3600., W, H) return cowcs
def read_pv_wcs(self): '''extract wcs from fits header directly''' hdr = fitsio.read_header(self.imgfn, self.hdu) H,W = self.get_image_shape() wcs= Tan(hdr['CRVAL1'], hdr['CRVAL2'],hdr['CRPIX1'],hdr['CRPIX2'],\ hdr['CD1_1'],hdr['CD1_2'],hdr['CD2_1'],hdr['CD2_2'],\ float(W),float(H)) return wcs
def ccds_touching_wcs(targetwcs, ccds, ccdrad=0.17, polygons=True): ''' targetwcs: wcs object describing region of interest ccds: fits_table object of CCDs ccdrad: radius of CCDs, in degrees. Default 0.17 is for DECam. #If None, computed from T. Returns: index array I of CCDs within range. ''' trad = targetwcs.radius() if ccdrad is None: ccdrad = max( np.sqrt(np.abs(ccds.cd1_1 * ccds.cd2_2 - ccds.cd1_2 * ccds.cd2_1)) * np.hypot(ccds.width, ccds.height) / 2.) rad = trad + ccdrad r, d = targetwcs.radec_center() I, = np.nonzero(np.abs(ccds.dec - d) < rad) I = I[np.atleast_1d(degrees_between(ccds.ra[I], ccds.dec[I], r, d) < rad)] if not polygons: return I # now check actual polygon intersection tw, th = targetwcs.imagew, targetwcs.imageh targetpoly = [(0.5, 0.5), (tw + 0.5, 0.5), (tw + 0.5, th + 0.5), (0.5, th + 0.5)] cd = targetwcs.get_cd() tdet = cd[0] * cd[3] - cd[1] * cd[2] if tdet > 0: targetpoly = list(reversed(targetpoly)) targetpoly = np.array(targetpoly) keep = [] for i in I: W, H = ccds.width[i], ccds.height[i] wcs = Tan(*[ float(x) for x in [ ccds.crval1[i], ccds.crval2[i], ccds.crpix1[i], ccds.crpix2[i], ccds.cd1_1[i], ccds.cd1_2[i], ccds.cd2_1[i], ccds.cd2_2[i], W, H ] ]) cd = wcs.get_cd() wdet = cd[0] * cd[3] - cd[1] * cd[2] poly = [] for x, y in [(0.5, 0.5), (W + 0.5, 0.5), (W + 0.5, H + 0.5), (0.5, H + 0.5)]: rr, dd = wcs.pixelxy2radec(x, y) ok, xx, yy = targetwcs.radec2pixelxy(rr, dd) poly.append((xx, yy)) if wdet > 0: poly = list(reversed(poly)) poly = np.array(poly) if polygons_intersect(targetpoly, poly): keep.append(i) I = np.array(keep) return I
def galex_tractor_image(tile, band, galex_dir, radecbox, bandname): from tractor import (NanoMaggies, Image, LinearPhotoCal, ConstantFitsWcs, ConstantSky) assert(band in ['n','f']) #nicegbands = ['NUV', 'FUV'] #zps = dict(n=20.08, f=18.82) #zp = zps[band] imfn = os.path.join(galex_dir, tile.tilename.strip(), '%s-%sd-intbgsub.fits.gz' % (tile.visitname.strip(), band)) gwcs = Tan(*[float(f) for f in [tile.crval1, tile.crval2, tile.crpix1, tile.crpix2, tile.cdelt1, 0., 0., tile.cdelt2, 3840., 3840.]]) (r0,r1,d0,d1) = radecbox H,W = gwcs.shape ok,xx,yy = gwcs.radec2pixelxy([r0,r0,r1,r1], [d0,d1,d1,d0]) #print('GALEX WCS pixel positions of RA,Dec box:', xx, yy) if np.any(np.logical_not(ok)): return None x0 = np.clip(np.floor(xx-1).astype(int).min(), 0, W-1) x1 = np.clip(np.ceil (xx-1).astype(int).max(), 0, W) if x1-x0 <= 1: return None y0 = np.clip(np.floor(yy-1).astype(int).min(), 0, H-1) y1 = np.clip(np.ceil (yy-1).astype(int).max(), 0, H) if y1-y0 <= 1: return None debug('Reading GALEX subimage x0,y0', x0,y0, 'size', x1-x0, y1-y0) gwcs = gwcs.get_subimage(x0, y0, x1 - x0, y1 - y0) twcs = ConstantFitsWcs(gwcs) roislice = (slice(y0, y1), slice(x0, x1)) fitsimg = fitsio.FITS(imfn)[0] hdr = fitsimg.read_header() img = fitsimg[roislice] inverr = np.ones_like(img) inverr[img == 0.] = 0. zp = tile.get('%s_zpmag' % band) photocal = LinearPhotoCal(NanoMaggies.zeropointToScale(zp), band=bandname) tsky = ConstantSky(0.) name = 'GALEX ' + hdr['OBJECT'] + ' ' + band psfimg = galex_psf(band, galex_dir) tpsf = PixelizedPSF(psfimg) tim = Image(data=img, inverr=inverr, psf=tpsf, wcs=twcs, sky=tsky, photocal=photocal, name=name) tim.roi = [x0,x1,y0,y1] return tim
def example(): pixscale = 0.25 # [arcsec/pix] radius = 45.0 # [arcsec] ra, dec = 120.0, 15.0 # [degrees] diam = np.ceil(radius / pixscale).astype('int16') # [pixels] wcs = Tan(ra, dec, diam / 2 + 0.5, diam / 2 + 0.5, -pixscale / 3600.0, 0.0, 0.0, pixscale / 3600.0, float(diam), float(diam)) return wcs
def dither_sequence(start, ending): dither = fits_table() dither.expnum = [] dither.gfa_ra = [] dither.gfa_dec = [] dither.gfa05_ra = [] dither.gfa05_dec = [] dither.gfa27_ra = [] dither.gfa27_dec = [] dither.gfa38_ra = [] dither.gfa38_dec = [] dither.gfa_all_ra = [] dither.gfa_all_dec = [] dither.sky_ra = [] dither.sky_dec = [] headers = [] for expnum in range(start, ending): fns = glob('/global/cscratch1/sd/dstn/gfa-wcs/gfa-%i-GUIDE?.wcs' % expnum) if len(fns) != 6: #print('Do not have', expnum) continue #print('Got', expnum) fns.sort() rr, dd = [], [] for fn in fns: print('Reading', fn) wcs = Tan(fn) rr.append(wcs.crval[0]) dd.append(wcs.crval[1]) fn = gfa_filename(expnum) hdr = fitsio.read_header(fn, ext=1) dither.expnum.append(expnum) headers.append(hdr) r, d = average_radec(rr, dd) dither.gfa_ra.append(r) dither.gfa_dec.append(d) r, d = average_radec([rr[0], rr[3]], [dd[0], dd[3]]) dither.gfa05_ra.append(r) dither.gfa05_dec.append(d) r, d = average_radec([rr[1], rr[4]], [dd[1], dd[4]]) dither.gfa27_ra.append(r) dither.gfa27_dec.append(d) r, d = average_radec([rr[2], rr[5]], [dd[2], dd[5]]) dither.gfa38_ra.append(r) dither.gfa38_dec.append(d) dither.gfa_all_ra.append(rr) dither.gfa_all_dec.append(dd) dither.sky_ra.append(hdr['SKYRA']) dither.sky_dec.append(hdr['SKYDEC']) dither.to_np_arrays() dither.headers = headers return dither
def get_wcs(self, hdr): # Older images have ZPX, newer TPV. if hdr['CTYPE1'] == 'RA---TPV': from astrometry.util.util import wcs_pv2sip_hdr wcs = wcs_pv2sip_hdr(hdr) else: from astrometry.util.util import Tan hdr['CTYPE1'] = 'RA---TAN' hdr['CTYPE2'] = 'DEC--TAN' wcs = Tan(hdr) return wcs
def __init__(self, name, **kwargs): import fitsio from astrometry.util.util import Tan #from astrometry.util.util import anwcs_open_wcslib super(PhatLayer, self).__init__(name, **kwargs) self.nativescale = 17 self.pixscale = 0.05 fn = os.path.join(settings.DATA_DIR, 'm31_full.fits') self.fits = fitsio.FITS(fn)[0] #self.wcs = anwcs_open_wcslib(fn, 0) self.wcs = Tan(fn, 0)
def wcs_for_brick(b, W=3600, H=3600, pixscale=0.262): ''' b: row from decals-bricks.fits file W,H: size in pixels pixscale: pixel scale in arcsec/pixel. Returns: Tan wcs object ''' pixscale = pixscale / 3600. return Tan(b.ra, b.dec, W/2.+0.5, H/2.+0.5, -pixscale, 0., 0., pixscale, float(W), float(H))
def read_astrans(fn, hdu, hdr=None, W=None, H=None, fitsfile=None): from astrometry.sdss import AsTransWrapper, AsTrans from astrometry.util.util import Tan, fit_sip_wcs_py from astrometry.util.starutil_numpy import radectoxyz import numpy as np astrans = AsTrans.read(fn, F=fitsfile, primhdr=hdr) # Approximate as SIP. if hdr is None and fn.endswith('.bz2'): import fitsio hdr = fitsio.read_header(fn, 0) if hdr is not None: tan = Tan(*[ float(hdr[k]) for k in [ 'CRVAL1', 'CRVAL2', 'CRPIX1', 'CRPIX2', 'CD1_1', 'CD1_2', 'CD2_1', 'CD2_2', 'NAXIS1', 'NAXIS2' ] ]) else: # Frame files include a TAN header... start there. tan = Tan(fn) # Evaluate AsTrans on a pixel grid... h, w = tan.shape xx = np.linspace(1, w, 20) yy = np.linspace(1, h, 20) xx, yy = np.meshgrid(xx, yy) xx = xx.ravel() yy = yy.ravel() rr, dd = astrans.pixel_to_radec(xx, yy) xyz = radectoxyz(rr, dd) fieldxy = np.vstack((xx, yy)).T sip_order = 5 inv_order = 7 sip = fit_sip_wcs_py(xyz, fieldxy, None, tan, sip_order, inv_order) return sip
def sdss_image(req, calid=None, size='full'): cal = get_object_or_404(Calibration, pk=calid) key = 'sdss_size%s_cal%i' % (size, cal.id) df = CachedFile.get(key) if df is None: wcsfn = cal.get_wcs_file() from astrometry.util.util import Tan wcs = Tan(wcsfn) if size == 'display': image = cal.job.user_image scale = float( image.image.get_display_image().width) / image.image.width wcs = wcs.scale(scale) else: scale = 1.0 urlargs = urlencode( dict(crval1='%.6f' % wcs.crval[0], crval2='%.6f' % wcs.crval[1], crpix1='%.2f' % wcs.crpix[0], crpix2='%.2f' % wcs.crpix[1], cd11='%.6g' % wcs.cd[0], cd12='%.6g' % wcs.cd[1], cd21='%.6g' % wcs.cd[2], cd22='%.6g' % wcs.cd[3], imagew='%i' % int(wcs.imagew), imageh='%i' % int(wcs.imageh))) url = 'http://legacysurvey.org/viewer/cutout-wcs/?layer=sdssco&' + urlargs return HttpResponseRedirect(url) #print('Retrieving:', url) #f = urlopen(url) #plotfn = get_temp_file() #plotfn, headers = urlretrieve(url, plotfn) #print('Headers:', headers) #plot_sdss_image(wcsfn, plotfn, scale) # cache # logmsg('Caching key "%s"' % key) # df = CachedFile.add(key, plotfn) else: logmsg('Cache hit for key "%s" -> %s' % (key, df.get_path())) f = open(df.get_path(), 'rb') res = HttpResponse(f) res['Content-Type'] = 'image/jpeg' return res
def __init__(self, name, **kwargs): ## HACK -- don't call the PhatLayer constructor! #super(M33Layer, self).__init__(name, **kwargs) super(PhatLayer, self).__init__(name, **kwargs) self.nativescale = 17 self.pixscale = 0.035 #fn = self.get_base_filname(None, None) #self.fits = fitsio.FITS(fn)[0] #fn = os.path.join(settings.DATA_DIR, 'm33', 'F475W_wcs.fits') #fn = os.path.join(settings.DATA_DIR, 'm33', 'm33-wcs.fits') fn = os.path.join(settings.DATA_DIR, 'm33', 'm33-wcs814.fits') #self.wcs = anwcs_open_wcslib(fn, 0) from astrometry.util.util import Tan self.wcs = Tan(fn, 0) print('M33 WCS: center', self.wcs.radec_center())
def plot_into_wcs(wcsfn, plotfn, wcsext=0, basedir='.', scale=1.0): wcs = Tan(wcsfn, wcsext) ra, dec = wcs.radec_center() radius = wcs.radius() # The "index.fits" table has RA,Dec center and file paths. T = fits_table(os.path.join(basedir, 'index.fits')) # MAGIC 1: the GALEX fields are all smaller than 1 degree (~0.95) in radius, # so add that to the search r = radius + 1. # find rows in "T" that are within range. J = points_within_radius(ra, dec, r, T.ra, T.dec) T = T[J] debug(len(T), 'GALEX fields within range of RA,Dec = ', ra, dec, 'radius', radius) size = [int(scale * wcs.imagew), int(scale * wcs.imageh)] plot = ps.Plotstuff(outformat='png', wcsfn=wcsfn, wcsext=wcsext, size=size) plot.scale_wcs(scale) #debug('WCS:', str(plot.wcs)) #plot.wcs.write_to('/tmp/wcs.fits') img = plot.image img.format = ps.PLOTSTUFF_FORMAT_JPG img.resample = 1 if len(T): paths = [fn.strip() for fn in T.path] else: paths = [] plot.color = 'black' plot.plot('fill') for jpegfn in paths: jpegfn = os.path.join(basedir, jpegfn) imwcsfn = jpegfn.replace('.jpg', '.wcs') debug(' Plotting GALEX fields', jpegfn, imwcsfn) #debug('jpeg "%s"' % jpegfn) #debug('wcs "%s"' % imwcsfn) img.set_wcs_file(imwcsfn, 0) img.set_file(jpegfn) # convert black to transparent ps.plot_image_read(plot.pargs, img) ps.plot_image_make_color_transparent(img, 0, 0, 0) plot.plot('image') plot.write(plotfn) debug('wrote', plotfn)
def sdss_image(req, calid=None, size='full'): cal = get_object_or_404(Calibration, pk=calid) key = 'sdss_size%s_cal%i' % (size, cal.id) df = CachedFile.get(key) if df is None: wcsfn = cal.get_wcs_file() #plotfn = get_temp_file() from astrometry.util.util import Tan wcs = Tan(wcsfn) if size == 'display': image = cal.job.user_image scale = float( image.image.get_display_image().width) / image.image.width wcs = wcs.scale(scale) else: scale = 1.0 url = 'http://legacysurvey.org/viewer-dev/sdss-wcs/?crval1=%.6f&crval2=%.6f&crpix1=%.2f&crpix2=%.2f&cd11=%.6g&cd12=%.6g&cd21=%.6g&cd22=%.6g&imagew=%i&imageh=%i' % ( wcs.crval[0], wcs.crval[1], wcs.crpix[0], wcs.crpix[1], wcs.cd[0], wcs.cd[1], wcs.cd[2], wcs.cd[3], int(wcs.imagew), int(wcs.imageh)) print('Retrieving:', url) import urllib plotfn, headers = urllib2.urlretrieve(url) # jwcs = json.dumps(dict( # crval1=wcs.crval[0], crval2=wcs.crval[1], # crpix1=wcs.crpix[0], crpix2=wcs.crpix[1], # cd11=wcs.cd[0], cd12=wcs.cd[1], cd21=wcs.cd[2], cd22=wcs.cd[3], # imagew=wcs.imagew, imageh=wcs.imageh)) # plot_sdss_image(wcsfn, plotfn, scale) # cache logmsg('Caching key "%s"' % key) df = CachedFile.add(key, plotfn) else: logmsg('Cache hit for key "%s"' % key) f = open(df.get_path()) res = HttpResponse(f) res['Content-Type'] = 'image/jpeg' return res
def forwards(self, orm): "Write your forwards methods here." for calib in orm.Calibration.objects.all(): wcsfn = os.path.join(JOBDIR, '%08i' % calib.job.id) wcsfn = os.path.join(wcsfn, 'wcs.fits') wcs = Tan(str(wcsfn), 0) ra,dec = wcs.radec_center() radius = (wcs.pixel_scale() * math.hypot(wcs.imagew, wcs.imageh)/2. / 3600.) # Find cartesian coordinates ra *= math.pi/180 dec *= math.pi/180 tempr = math.cos(dec) calib.x = tempr*math.cos(ra) calib.y = tempr*math.sin(ra) calib.z = math.sin(dec) calib.r = radius/180*math.pi calib.save()
def get_wcs(hdr, tpv_to_sip=True): # Thanks Dstn :) # https://github.com/legacysurvey/legacypipe/blob/master/py/legacypipe/cpimage.py#102 width = hdr['NAXIS1'] height = hdr['NAXIS2'] if not (tpv_to_sip): # extract wcs from fits header directly wcs= Tan(hdr['CRVAL1'], hdr['CRVAL2'],hdr['CRPIX1'],hdr['CRPIX2'],\ hdr['CD1_1'],hdr['CD1_2'],hdr['CD2_1'],hdr['CD2_2'],\ float(width),float(height)) else: # Make sure the PV-to-SIP converter samples enough points for small # images stepsize = 0 if min(width, height) < 600: stepsize = min(width, height) / 10. wcs = wcs_pv2sip_hdr(hdr, stepsize=stepsize) # Dstn adds an offset correction i.e. # Correction: ccd,ccdraoff, decoff from zeropoints file # Should I do this? return wcs
def gettractor(): W, H = 200, 200 image = np.zeros((H, W)) invvar = np.zeros_like(image) + 1. ra, dec = 0, 0 # arcsec/pix pixscale = 1. wcs1 = Tan(ra, dec, W / 2, H / 2, -pixscale / 3600., 0, 0, -pixscale / 3600., W, H) wcs = FitsWcs(wcs1) photocal = NullPhotoCal() psf = NCircularGaussianPSF([1.], [1.]) sky = ConstantSky(0.) img = Image(data=image, invvar=invvar, psf=psf, wcs=wcs, sky=sky, photocal=photocal) tractor = SDSSTractor([img]) return tractor, wcs
def create_tractor(opt): """ Brittle function to read Groves data sample and make the things we need for fitting. # issues: - Need to read the WCS too. - Need, for each image, to construct the rectangular nearest-neighbor interpolation indices to image 0. - Can I just blow up the SPIRE images with interpolation? """ dataList = [ ('m31_brick15_PACS100.fits', 'PACS 100', 7.23, 7.7), ('m31_brick15_PACS160.fits', 'PACS 160', 3.71, 12.0), ('m31_brick15_SPIRE250.fits', 'SPIRE 250', None, 18.0), ('m31_brick15_SPIRE350.fits', 'SPIRE 350', None, 25.0), ('m31_brick15_SPIRE500.fits', 'SPIRE 500', None, 37.0), ] # From Groves via Rix: # PSF FWHMs: 6.97, 11.01, 18.01, 24.73, 35.98 # Within the region Ive selected I found temperatures between 15 # and 21 K, averaging 17 K, and Beta= 1.5 to 2.5 (with a larger # uncertainty), averaging around 2.0. if opt.no100: dataList = dataList[1:] print('Reading images...') tims = [] for i, (fn, nm, noise, fwhm) in enumerate(dataList): print() print('Reading', fn) P = pyfits.open(fn) image = P[0].data.astype(np.float32) #wcs = Tan(fn, 0) H,W = image.shape hdr = P[0].header wcs = Tan(hdr['CRVAL1'], hdr['CRVAL2'], hdr['CRPIX1'], hdr['CRPIX2'], hdr['CDELT1'], 0., 0., hdr['CDELT2'], W, H) assert(hdr['CROTA2'] == 0.) if noise is None: noise = float(hdr['NOISE']) print('Noise', noise) print('Median image value', np.median(image)) inverr = np.ones_like(image) / noise skyval = np.percentile(image, 5) sky = ConstantSky(skyval) lam = float(hdr['FILTER']) print('Lambda', lam) # calibrated, yo assert(hdr['BUNIT'] == 'MJy/Sr') # "Filter" is in *microns* in the headers; convert to *m* here, to match "lam0" pcal = DustPhotoCal(lam * 1e-6, wcs.pixel_scale()) #nm = '%s %i' % (hdr['INSTRUME'], lam) #nm = fn.replace('.fits', '') #zr = noise * np.array([-3, 10]) + skyval zr = np.array([np.percentile(image.ravel(), p) for p in [1, 99]]) print('Pixel scale:', wcs.pixel_scale()) # meh sigma = fwhm / wcs.pixel_scale() / 2.35 print('PSF sigma', sigma, 'pixels') psf = NCircularGaussianPSF([sigma], [1.]) twcs = ConstantFitsWcs(wcs) tim = Image(data=image, inverr=inverr, psf=psf, wcs=twcs, sky=sky, photocal=pcal, name=nm) print('created', tim) tim.zr = zr tims.append(tim) # plt.clf() # plt.hist(image.ravel(), 100) # plt.title(nm) # plt.savefig('im%i-hist.png' % i) radecbounds = [] for tim in tims: H,W = tim.shape twcs = tim.getWcs() rds = [] for x,y in [(0.5,0.5),(W+0.5,0.5),(W+0.5,H+0.5),(0.5,H+0.5),(0.5,0.5)]: rd = twcs.pixelToPosition(x-1, y-1) rds.append(rd) rds = np.array(rds) radecbounds.append(rds) rd = np.vstack(radecbounds) #print 'rd', rd.shape ramin,decmin = rd.min(axis=0) ramax,decmax = rd.max(axis=0) dr,dd = ramax-ramin, decmax-decmin plotrange = (ramin - 0.05*dr, ramax + 0.05*dr, decmin - 0.05*dd, decmax + 0.05*dd) plt.clf() for rds,c in zip(radecbounds, ['b','g','y',(1,0.5,0),'r']): plt.plot(rds[:,0], rds[:,1], '-', color=c, lw=2, alpha=0.5) setRadecAxes(*plotrange) plt.savefig('radec1%s.png' % opt.suffix) print('Creating dust sheet...') N = opt.gridn # Build a WCS for the dust sheet to match the first image # (assuming it's square and axis-aligned) #wcs = tims[0].getWcs().wcs #r,d = wcs.radec_center() #H,W = tims[0].shape #scale = wcs.pixel_scale() #scale *= float(W)/max(1, N-1) / 3600. #c = float(N)/2. + 0.5 #dwcs = Tan(r, d, c, c, scale, 0, 0, scale, N, N) # Build an axis-aligned WCS that contains all the images. r,d = (ramin + ramax) / 2., (decmin + decmax) / 2. # HACK -- ignore pole issues scale = max((ramax - ramin) * np.cos(np.deg2rad(d)), decmax - decmin) / float(N) scale *= float(N) / float(max(1, N-1)) scale *= (1. / opt.zoom) cpix = float(N)/2. + 0.5 dwcs = Tan(r, d, cpix, cpix, scale, 0, 0, scale, N, N) pixscale = dwcs.pixel_scale() logsa = np.log(1e-3) H,W = N,N logsa = np.zeros((H,W)) + logsa logt = np.zeros((H,W)) + np.log(17.) emis = np.zeros((H,W)) + 2. ds = DustSheet(logsa, logt, emis, dwcs) rds = ds.getRaDecCorners(0.5) plt.plot(rds[:,0], rds[:,1], 'k-', lw=1, alpha=1) setRadecAxes(*plotrange) plt.savefig('radec2%s.png' % opt.suffix) # plot grid of sample points. rds = [] H,W = N,N for y in range(N): for x in range(N): r,d = dwcs.pixelxy2radec(x+1, y+1) rds.append((r,d)) rds = np.array(rds) plt.plot(rds[:,0], rds[:,1], 'k.', lw=1, alpha=0.5) setRadecAxes(*plotrange) plt.savefig('radec3%s.png' % opt.suffix) #print 'DustSheet:', ds #print 'np', ds.numberOfParams() #print 'pn', ds.getParamNames() #print 'p', ds.getParams() # print 'PriorChi:', ds.getLogPriorChi() # ra,ca,va,pb = ds.getLogPriorChi() # print 'ra', ra # print 'ca', ca # print 'va', va # print 'pb', pb # for ri,ci,vi,bi in zip(ra,ca,va,pb): # print # print 'ri', ri # print 'ci', ci # print 'vi', vi # print 'bi', bi cat = Catalog() cat.append(ds) tractor = Tractor(Images(*tims), cat) return tractor
def _computeTransformation(self, img, ylo=0, yhi=-1): ''' Pre-compute the "grid-spread function" transformation matrix for this parameter grid to the given image pixels. The result is a home-brewed sparse matrix representation: a dictionary mapping from model grid pixel indices (integers) to the tuple (I, G, nz, NZI), where: I: numpy index array (integers) in the image G: grid weights for those pixels nz = ((x0,y0), (h,w)): the subimage with non-zero weights NZI: numpy index array (integers) within the "nz" subimage ''' imwcs = img.getWcs() H,W = self.shape if yhi == -1: yhi = H Ngrid = W*H iH,iW = img.shape Nim = iW*iH Lorder = 2 S = (Lorder * 2 + 3) if False: i0 = S/2 else: print('Image', img.name) print('Image PSF', img.getPsf()) psfw = img.getPsf().getRadius() scale = img.getWcs().pixel_scale() / self.wcs.pixel_scale() print('Image pixel scale', img.getWcs().pixel_scale()) print('Model pixel scale', self.wcs.pixel_scale()) print('PSF extent', psfw, 'pixels') print('pixel scale factor', scale) print('->', psfw * scale, 'model pixels') print('Increasing S from', S) S += int(np.ceil(psfw*scale)) * 2 print('to', S) i0 = S/2 cmock = np.zeros((S,S), np.float32) cmock[i0,i0] = 1. if True: spsf = img.getPsf().scale(scale) print('Scaled PSF', spsf) cmock = spsf.applyTo(cmock) #print 'cmock' #print cmock cwcs = Tan(self.wcs) cwcs.set_imagesize(S, S) cx0,cy0 = self.wcs.crpix[0], self.wcs.crpix[1] rim = np.zeros((iH,iW), np.float32) X = {} for i in range(ylo, yhi): print('Precomputing matrix for image', img.name, 'model row', i) for j in range(W): #print 'Precomputing matrix for grid pixel', j,i cwcs.set_crpix(cx0 - j + i0, cy0 - i + i0) rim[:,:] = 0 ## weighted = 1 res = tan_wcs_resample(cwcs, imwcs.wcs, cmock, rim, weighted, Lorder) assert(res == 0) if False: outimg = img.getPsf().applyTo(rim).ravel() else: outimg = rim.ravel() I = np.flatnonzero((outimg > 0) * (img.getInvError().ravel() > 0)) if len(I) == 0: continue #if True: # sumr.ravel()[I] += outimg[I] xx,yy = (I % iW), (I / iW) x0,y0 = xx.min(), yy.min() nzh,nzw = 1 + yy.max() - y0, 1 + xx.max() - x0 NZ = ((x0, y0), (nzh, nzw)) NZI = (xx - x0) + (yy - y0) * nzw X[i*W+j] = (I, outimg[I], NZ, NZI) # if True: # print 'sumr range', sumr.min(), sumr.max() # sumr[sumr == 0] = 1. # mn,mx = 0.,0. # for (I, outim, NZ, NZI) in X.values(): # outim /= sumr.ravel()[I] # mx = max(outim.max(), mx) # mn = max(outim.min(), mn) # print 'Min,Max grid-spread function:', mn,mx return X
def check_priors(): np.seterrcall(np_err_handler) np.seterr(all='call') import logging import sys lvl = logging.DEBUG log_init(3) logging.basicConfig(level=lvl, format='%(message)s', stream=sys.stdout) if True: # Check two-pixel priors: smoothness. H,W = 1,2 logsa = np.zeros((H,W)) + np.log(1e-3) logt = np.zeros((H,W)) + np.log(17.) emis = np.zeros((H,W)) + 2. dwcs = Tan(11.2, 41.9, 1, 1, 1e-3, 0, 0, 1e-3, W, H) ds = DustSheet(logsa, logt, emis, dwcs) cat = Catalog() cat.append(ds) tractor = Tractor() tractor.setCatalog(cat) p0 = tractor.getParams() print('lnp0', tractor.getLogProb()) if True: # check getLogProb() for j,xx in enumerate([ np.linspace(np.log(1e-5), np.log(1e-1), 20), np.linspace(np.log(1e-5), np.log(1e-1), 20), np.linspace(np.log(10.), np.log(20.), 20), np.linspace(np.log(10.), np.log(20.), 20), np.linspace(0., 4., 20), np.linspace(0., 4., 20), ]): pp = [] for x in xx: tractor.setParam(j, x) p = tractor.getLogProb() pp.append(p) tractor.setParam(j, p0[j]) plt.clf() plt.plot(xx, pp, 'ro-') plt.title(ds.getParamNames()[j]) plt.savefig('p%i.png' % (20 + j)) # set the absolute priors to have little effect and repeat. ds.prior_logt_std = np.log(100.) ds.prior_emis_std = np.log(100.) for j,xx in enumerate([ np.linspace(np.log(1e-5), np.log(1e-1), 20), np.linspace(np.log(1e-5), np.log(1e-1), 20), np.linspace(np.log(10.), np.log(20.), 20), np.linspace(np.log(10.), np.log(20.), 20), np.linspace(0., 4., 20), np.linspace(0., 4., 20), ]): pp = [] for x in xx: tractor.setParam(j, x) p = tractor.getLogProb() pp.append(p) tractor.setParam(j, p0[j]) plt.clf() plt.plot(xx, pp, 'ro-') plt.title(ds.getParamNames()[j]) plt.savefig('p%i.png' % (30 + j)) # revert the priors ds.prior_logt_std = np.log(1.2) ds.prior_emis_std = np.log(0.5) # check getLogPriorChi. for j,(ip,val) in enumerate([ (0, np.log(1e-1)), (1, np.log(1e-5)), (2, np.log(5.)), (3, np.log(5.)), (2, np.log(30.)), (3, np.log(30.)), (4, 1.), (5, 1.), (4, 3.), (5, 3.), ]): print() print() print('Setting', ds.getParamNames()[ip], 'from', p0[ip], 'to', val) tractor.setParams(p0) tractor.setParam(ip, val) xx = [val] xxall = [tractor.getParams()] pp = [tractor.getLogProb()] for i in range(10): tractor.optimize()#damp=1e-3) xx.append(tractor.getParams()[ip]) pp.append(tractor.getLogProb()) xxall.append(tractor.getParams()) plt.clf() plt.plot(xx, pp, 'ro-') plt.axvline(val, color='r', lw=2, alpha=0.5) plt.title(ds.getParamNames()[ip]) plt.savefig('p%i.png' % (j+40)) plt.clf() xxall = np.vstack(xxall) print('xxall', xxall.shape) for i in range(6): #plt.subplot(1,3,(i/2)+1) #plt.plot(xxall[:,i], pp, 'ro-') #if i == ip: # plt.axvline(xxall[0,i], color='r', lw=2, alpha=0.5) #plt.title(ds.getParamNames()[i]) plt.subplot(3,1,(i/2)+1) c = 'b' if i == ip: c = 'r' plt.plot(xxall[:,i], 'o-', color=c) plt.title(ds.getParamNames()[i]) plt.savefig('p%i.png' % (j+50)) if False: # Check single-pixel priors: getLogPrior() N = 1 H,W = N,N logsa = np.zeros((H,W)) + np.log(1e-3) logt = np.zeros((H,W)) + np.log(17.) emis = np.zeros((H,W)) + 2. dwcs = Tan(11.2, 41.9, 1, 1, 1e-3, 0, 0, 1e-3, N, N) ds = DustSheet(logsa, logt, emis, dwcs) cat = Catalog() cat.append(ds) tractor = Tractor() tractor.setCatalog(cat) p0 = tractor.getParams() print('lnp0', tractor.getLogProb()) # no prior on solid angle # N(log(17.), log(1.2)) on T # N(2, 0.5) on emis for j,xx in enumerate([ np.linspace(np.log(1e-5), np.log(1e-1), 20), np.linspace(np.log(10.), np.log(20.), 20), np.linspace(0., 4., 20), ]): pp = [] for x in xx: tractor.setParam(j, x) p = tractor.getLogProb() pp.append(p) tractor.setParam(j, p0[j]) plt.clf() plt.plot(xx, pp, 'ro-') plt.title(ds.getParamNames()[j]) plt.savefig('p%i.png' % j) # Check single-pixel priors: getPriorChi() for j,(ip,val) in enumerate([ (0, 1e-2), (1, np.log(5.)), (1, np.log(30.)), (2, 1.), (2, 3.), ]): print() print() print('Setting', ds.getParamNames()[ip], 'to', val) tractor.setParams(p0) tractor.setParam(ip, val) xx = [val] pp = [tractor.getLogProb()] for i in range(10): tractor.optimize(damp=1e-3) xx.append(tractor.getParams()[ip]) pp.append(tractor.getLogProb()) plt.clf() plt.plot(xx, pp, 'ro-') plt.title(ds.getParamNames()[ip]) plt.savefig('p%i.png' % (j+10))
def _simplewcs(gal): '''Build a simple WCS object for a single galaxy.''' diam = np.ceil(gal['RADIUS'] / PIXSCALE).astype('int16') # [pixels] galwcs = Tan(gal['RA'], gal['DEC'], diam / 2 + 0.5, diam / 2 + 0.5, -PIXSCALE, 0.0, PIXSCALE, 0.0, float(diam), float(diam)) return galwcs
def _computeTransformation(self, img, ylo=0, yhi=-1): imwcs = img.getWcs() # Pre-compute the "grid-spread function" transformation matrix... H,W = self.shape if yhi == -1: yhi = H Ngrid = W*H iH,iW = img.shape Nim = iW*iH Lorder = 2 S = (Lorder * 2 + 3) if False: i0 = S/2 else: print 'Image', img.name print 'Image PSF', img.getPsf() psfw = img.getPsf().getRadius() scale = img.getWcs().pixel_scale() / self.wcs.pixel_scale() print 'Image pixel scale', img.getWcs().pixel_scale() print 'Model pixel scale', self.wcs.pixel_scale() print 'PSF extent', psfw, 'pixels' print 'pixel scale factor', scale print '->', psfw * scale, 'model pixels' print 'Increasing S from', S S += int(np.ceil(psfw*scale)) * 2 print 'to', S i0 = S/2 cmock = np.zeros((S,S), np.float32) cmock[i0,i0] = 1. if True: spsf = img.getPsf().scale(scale) print 'Scaled PSF', spsf cmock = spsf.applyTo(cmock) #print 'cmock' #print cmock cwcs = Tan(self.wcs) cwcs.set_imagesize(S, S) cx0,cy0 = self.wcs.crpix[0], self.wcs.crpix[1] rim = np.zeros((iH,iW), np.float32) X = {} for i in range(ylo, yhi): print 'Precomputing matrix for image', img.name, 'model row', i for j in range(W): #print 'Precomputing matrix for grid pixel', j,i cwcs.set_crpix(cx0 - j + i0, cy0 - i + i0) rim[:,:] = 0 ## weighted = 1 res = tan_wcs_resample(cwcs, imwcs.wcs, cmock, rim, weighted, Lorder) assert(res == 0) if False: outimg = img.getPsf().applyTo(rim).ravel() else: outimg = rim.ravel() if sum(outimg) == 0: continue I = np.flatnonzero((outimg > 0) * (img.getInvError().ravel() > 0)) if len(I) == 0: continue #if True: # sumr.ravel()[I] += outimg[I] xx,yy = (I % iW), (I / iW) x0,y0 = xx.min(), yy.min() nzh,nzw = 1 + yy.max() - y0, 1 + xx.max() - x0 NZ = ((x0, y0), (nzh, nzw)) NZI = (xx - x0) + (yy - y0) * nzw X[i*W+j] = (I, outimg[I], NZ, NZI) # if True: # print 'sumr range', sumr.min(), sumr.max() # sumr[sumr == 0] = 1. # mn,mx = 0.,0. # for (I, outim, NZ, NZI) in X.values(): # outim /= sumr.ravel()[I] # mx = max(outim.max(), mx) # mn = max(outim.min(), mn) # print 'Min,Max grid-spread function:', mn,mx return X
from legacypipe.survey import GaiaSource, GaiaPosition from astrometry.util.util import Tan from astrometry.util.starutil_numpy import mjdtodate from tractor import TAITime #ra,dec = 357.3060, 2.3957 #ccd1 = ccds[(ccds.expnum == 563212) * (ccds.ccdname == 'N17')] ra, dec = 124.0317, 1.3028 expnum, ccdname = 393203, 'N11' survey = LegacySurveyData() W, H = 200, 200 pixscale = 0.262 cd = pixscale / 3600. targetwcs = Tan(ra, dec, W / 2., H / 2., -cd, 0., 0., cd, float(W), float(H)) rr, dd = targetwcs.pixelxy2radec([1, W, W, 1, 1], [1, 1, H, H, 1]) targetrd = np.vstack((rr, dd)).T ccds = survey.ccds_touching_wcs(targetwcs) print(len(ccds), 'CCDs touching WCS') print('MJDs', ccds.mjd_obs) ccds.writeto('test-ccds.fits') ccd1 = ccds[(ccds.expnum == expnum) * (ccds.ccdname == ccdname)] print('CCD1:', ccd1) im1 = survey.get_image_object(ccd1[0]) print('Im:', im1)
def main(): ps = PlotSequence('cov') survey = LegacySurveyData() ra, dec = 242.0, 10.2 fn = 'coverage-ccds.fits' if not os.path.exists(fn): ccds = survey.get_ccds() ccds.cut(ccds.filter == 'r') ccds.cut(ccds.propid == '2014B-0404') ccds.cut(np.hypot(ccds.ra_bore - ra, ccds.dec_bore - dec) < 2.5) print(np.unique(ccds.expnum), 'unique exposures') print('propids', np.unique(ccds.propid)) ccds.writeto(fn) else: ccds = fits_table(fn) plt.clf() for e in np.unique(ccds.expnum): I = np.flatnonzero(ccds.expnum == e) plt.plot(ccds.ra[I], ccds.dec[I], '.') ps.savefig() degw = 3.0 pixscale = 10. W = degw * 3600 / 10. H = W hi = 6 cmap = cmap_discretize('jet', hi + 1) wcs = Tan(ra, dec, W / 2. + 0.5, H / 2. + 0.5, -pixscale / 3600., 0., 0., pixscale / 3600., float(W), float(H)) r0, d0 = wcs.pixelxy2radec(1, 1) r1, d1 = wcs.pixelxy2radec(W, H) extent = [min(r0, r1), max(r0, r1), min(d0, d1), max(d0, d1)] for expnums in [ [348666], [348666, 348710, 348686], [348659, 348667, 348658, 348666, 348665, 348669, 348668], None, [ 348683, 348687, 347333, 348686, 348685, 348692, 348694, 348659, 348667, 348658, 348666, 348665, 348669, 348668, 348707, 348709, 348708, 348710, 348711, 348716, 348717 ], ]: nexp = np.zeros((H, W), np.uint8) for ccd in ccds: if expnums is not None and not ccd.expnum in expnums: continue ccdwcs = survey.get_approx_wcs(ccd) r, d = ccdwcs.pixelxy2radec(1, 1) ok, x0, y0 = wcs.radec2pixelxy(r, d) r, d = ccdwcs.pixelxy2radec(ccd.width, ccd.height) ok, x1, y1 = wcs.radec2pixelxy(r, d) xlo = np.clip(int(np.round(min(x0, x1))) - 1, 0, W - 1) xhi = np.clip(int(np.round(max(x0, x1))) - 1, 0, W - 1) ylo = np.clip(int(np.round(min(y0, y1))) - 1, 0, H - 1) yhi = np.clip(int(np.round(max(y0, y1))) - 1, 0, H - 1) nexp[ylo:yhi + 1, xlo:xhi + 1] += 1 plt.clf() plt.imshow(nexp, interpolation='nearest', origin='lower', vmin=-0.5, vmax=hi + 0.5, cmap=cmap, extent=extent) plt.colorbar(ticks=np.arange(hi + 1)) ps.savefig() O = fits_table('obstatus/decam-tiles_obstatus.fits') O.cut(np.hypot(O.ra - ra, O.dec - dec) < 2.5) for p in [1, 2, 3]: print('Pass', p, 'exposures:', O.r_expnum[O.get('pass') == p]) O.cut(O.get('pass') == 2) print(len(O), 'pass 2 nearby') d = np.hypot(O.ra - ra, O.dec - dec) print('Dists:', d) I = np.flatnonzero(d < 0.5) assert (len(I) == 1) ocenter = O[I[0]] print('Center expnum', ocenter.r_expnum) I = np.flatnonzero(d >= 0.5) O.cut(I) #center = ccds[ccds.expnum == ocenter.r_expnum] #p2 = ccds[ccds. ok, xc, yc = wcs.radec2pixelxy(ocenter.ra, ocenter.dec) xx, yy = np.meshgrid(np.arange(W) + 1, np.arange(H) + 1) c_d2 = (xc - xx)**2 + (yc - yy)**2 best = np.ones((H, W), bool) for o in O: ok, x, y = wcs.radec2pixelxy(o.ra, o.dec) d2 = (x - xx)**2 + (y - yy)**2 best[d2 < c_d2] = False del d2 del c_d2, xx, yy # plt.clf() # plt.imshow(best, interpolation='nearest', origin='lower', cmap='gray', # vmin=0, vmax=1) # ps.savefig() plt.clf() plt.imshow(nexp * best, interpolation='nearest', origin='lower', vmin=-0.5, vmax=hi + 0.5, cmap=cmap, extent=extent) plt.colorbar(ticks=np.arange(hi + 1)) ps.savefig() plt.clf() n, b, p = plt.hist(np.clip(nexp[best], 0, hi), range=(-0.5, hi + 0.5), bins=hi + 1) plt.xlim(-0.5, hi + 0.5) ps.savefig() print('b', b) print('n', n) print('fracs', np.array(n) / np.sum(n)) print('pcts', ', '.join(['%.1f' % f for f in 100. * np.array(n) / np.sum(n)]))
def main(): import argparse parser = argparse.ArgumentParser() parser.add_argument('-o', '--out', dest='outfn', help='Output filename', default='TMP/nexp.fits') parser.add_argument('--merge', action='store_true', help='Merge sub-tables') parser.add_argument('--plot', action='store_true', help='Plot results') parser.add_argument('files', metavar='nexp-file.fits.gz', nargs='+', help='List of nexp files to process') opt = parser.parse_args() fns = opt.files if opt.merge: from astrometry.util.fits import merge_tables TT = [] for fn in fns: T = fits_table(fn) print(fn, '->', len(T)) TT.append(T) T = merge_tables(TT) T.writeto(opt.outfn) print('Wrote', opt.outfn) if opt.plot: T = fits_table(opt.files[0]) import pylab as plt import matplotlib ax = [360, 0, -21, 36] def radec_plot(): plt.axis(ax) plt.xlabel('RA (deg)') plt.xticks(np.arange(0, 361, 45)) plt.ylabel('Dec (deg)') gl = np.arange(361) gb = np.zeros_like(gl) from astrometry.util.starutil_numpy import lbtoradec rr, dd = lbtoradec(gl, gb) plt.plot(rr, dd, 'k-', alpha=0.5, lw=1) rr, dd = lbtoradec(gl, gb + 10) plt.plot(rr, dd, 'k-', alpha=0.25, lw=1) rr, dd = lbtoradec(gl, gb - 10) plt.plot(rr, dd, 'k-', alpha=0.25, lw=1) plt.figure(figsize=(8, 5)) plt.subplots_adjust(left=0.1, right=0.98, top=0.93) # Map of the tile centers we want to observe... O = fits_table('obstatus/decam-tiles_obstatus.fits') O.cut(O.in_desi == 1) rr, dd = np.meshgrid(np.linspace(ax[1], ax[0], 700), np.linspace(ax[2], ax[3], 200)) from astrometry.libkd.spherematch import match_radec I, J, d = match_radec(O.ra, O.dec, rr.ravel(), dd.ravel(), 1.) desimap = np.zeros(rr.shape, bool) desimap.flat[J] = True def desi_map(): # Show the DESI tile map in the background. from astrometry.util.plotutils import antigray plt.imshow(desimap, origin='lower', interpolation='nearest', extent=[ax[1], ax[0], ax[2], ax[3]], aspect='auto', cmap=antigray, vmax=8) for band in 'grz': plt.clf() desi_map() N = T.get('nexp_%s' % band) I = np.flatnonzero(N > 0) #cm = matplotlib.cm.get_cmap('jet', 6) #cm = matplotlib.cm.get_cmap('winter', 5) cm = matplotlib.cm.viridis cm = matplotlib.cm.get_cmap(cm, 5) plt.scatter(T.ra[I], T.dec[I], c=N[I], s=2, edgecolors='none', vmin=0.5, vmax=5.5, cmap=cm) radec_plot() cax = colorbar_axes(plt.gca(), frac=0.06) plt.colorbar(cax=cax, ticks=range(6)) #plt.colorbar(ticks=range(6)) plt.title('DECaLS DR3: Number of exposures in %s' % band) plt.savefig('nexp-%s.png' % band) plt.clf() desi_map() plt.scatter(T.ra, T.dec, c=T.get('nexp_%s' % band), s=2, edgecolors='none', vmin=0, vmax=2.) radec_plot() plt.colorbar() plt.title('DECaLS DR3: PSF size, band %s' % band) plt.savefig('psfsize-%s.png' % band) return 0 for col in ['nobjs', 'npsf', 'nsimp', 'nexp', 'ndev', 'ncomp']: plt.clf() desi_map() N = T.get(col) mx = np.percentile(N, 99.5) plt.scatter(T.ra, T.dec, c=N, s=2, edgecolors='none', vmin=0, vmax=mx) radec_plot() plt.colorbar() plt.title('DECaLS DR3: Number of objects of type %s' % col[1:]) plt.savefig('nobjs-%s.png' % col[1:]) Ntot = T.nobjs for col in ['npsf', 'nsimp', 'nexp', 'ndev', 'ncomp']: plt.clf() desi_map() N = T.get(col) / Ntot.astype(np.float32) mx = np.percentile(N, 99.5) plt.scatter(T.ra, T.dec, c=N, s=2, edgecolors='none', vmin=0, vmax=mx) radec_plot() plt.colorbar() plt.title('DECaLS DR3: Fraction of objects of type %s' % col[1:]) plt.savefig('fobjs-%s.png' % col[1:]) return 0 # fnpats = opt.files # fns = [] # for pat in fnpats: # pfns = glob(pat) # fns.extend(pfns) # print('Pattern', pat, '->', len(pfns), 'files') #fns = glob('coadd/*/*/*-nexp*') #fns = glob('coadd/000/*/*-nexp*') #fns = glob('coadd/000/0001*/*-nexp*') fns.sort() print(len(fns), 'nexp files') brickset = set() bricklist = [] gn = [] rn = [] zn = [] gnhist = [] rnhist = [] znhist = [] nnhist = 6 gdepth = [] rdepth = [] zdepth = [] ibricks = [] nsrcs = [] npsf = [] nsimp = [] nexp = [] ndev = [] ncomp = [] gpsfsize = [] rpsfsize = [] zpsfsize = [] ebv = [] gtrans = [] rtrans = [] ztrans = [] bricks = fits_table('survey-bricks.fits.gz') #sfd = SFDMap() W = H = 3600 # H=3600 # xx,yy = np.meshgrid(np.arange(W), np.arange(H)) unique = np.ones((H, W), bool) tlast = 0 for fn in fns: print('File', fn) words = fn.split('/') dirprefix = '/'.join(words[:-4]) print('Directory prefix:', dirprefix) words = words[-4:] brick = words[2] print('Brick', brick) if not brick in brickset: brickset.add(brick) bricklist.append(brick) gn.append(0) rn.append(0) zn.append(0) gnhist.append([0 for i in range(nnhist)]) rnhist.append([0 for i in range(nnhist)]) znhist.append([0 for i in range(nnhist)]) index = -1 ibrick = np.nonzero(bricks.brickname == brick)[0][0] ibricks.append(ibrick) tfn = os.path.join(dirprefix, 'tractor', brick[:3], 'tractor-%s.fits' % brick) print('Tractor filename', tfn) T = fits_table(tfn, columns=[ 'brick_primary', 'type', 'decam_psfsize', 'ebv', 'decam_mw_transmission' ]) T.cut(T.brick_primary) nsrcs.append(len(T)) types = Counter([t.strip() for t in T.type]) npsf.append(types['PSF']) nsimp.append(types['SIMP']) nexp.append(types['EXP']) ndev.append(types['DEV']) ncomp.append(types['COMP']) print('N sources', nsrcs[-1]) gpsfsize.append(np.median(T.decam_psfsize[:, 1])) rpsfsize.append(np.median(T.decam_psfsize[:, 2])) zpsfsize.append(np.median(T.decam_psfsize[:, 4])) ebv.append(np.median(T.ebv)) gtrans.append(np.median(T.decam_mw_transmission[:, 1])) rtrans.append(np.median(T.decam_mw_transmission[:, 2])) ztrans.append(np.median(T.decam_mw_transmission[:, 4])) br = bricks[ibrick] print('Computing unique brick pixels...') #wcs = Tan(fn, 0) #W,H = int(wcs.get_width()), int(wcs.get_height()) pixscale = 0.262 / 3600. wcs = Tan(br.ra, br.dec, W / 2. + 0.5, H / 2. + 0.5, -pixscale, 0., 0., pixscale, float(W), float(H)) import time t0 = time.clock() unique[:, :] = True find_unique_pixels(wcs, W, H, unique, br.ra1, br.ra2, br.dec1, br.dec2) # for i in range(W/2): # allin = True # lo,hi = i, W-i-1 # # one slice per side # side = slice(lo,hi+1) # top = (lo, side) # bot = (hi, side) # left = (side, lo) # right = (side, hi) # for slc in [top, bot, left, right]: # #print('xx,yy', xx[slc], yy[slc]) # rr,dd = wcs.pixelxy2radec(xx[slc]+1, yy[slc]+1) # U = (rr >= br.ra1 ) * (rr < br.ra2 ) * (dd >= br.dec1) * (dd < br.dec2) # #print('Pixel', i, ':', np.sum(U), 'of', len(U), 'pixels are unique') # allin *= np.all(U) # unique[slc] = U # if allin: # print('Scanned to pixel', i) # break t1 = time.clock() U = np.flatnonzero(unique) t2 = time.clock() print(len(U), 'of', W * H, 'pixels are unique to this brick') # #t3 = time.clock() #rr,dd = wcs.pixelxy2radec(xx+1, yy+1) # #t4 = time.clock() # #u = (rr >= br.ra1 ) * (rr < br.ra2 ) * (dd >= br.dec1) * (dd < br.dec2) # #t5 = time.clock() # #U2 = np.flatnonzero(u) #U2 = np.flatnonzero((rr >= br.ra1 ) * (rr < br.ra2 ) * # (dd >= br.dec1) * (dd < br.dec2)) #assert(np.all(U == U2)) #assert(len(U) == len(U2)) # #t6 = time.clock() # print(len(U2), 'of', W*H, 'pixels are unique to this brick') # #print(t0-tlast, 'other time') #tlast = time.clock() #t2 #print('t1:', t1-t0, 't2', t2-t1) # #print('t4:', t4-t3, 't5', t5-t4, 't6', t6-t5) # else: index = bricklist.index(brick) assert (index == len(bricklist) - 1) index = bricklist.index(brick) assert (index == len(bricklist) - 1) filepart = words[-1] filepart = filepart.replace('.fits.gz', '') print('File:', filepart) band = filepart[-1] assert (band in 'grz') nlist, nhist = dict(g=(gn, gnhist), r=(rn, rnhist), z=(zn, znhist))[band] upix = fitsio.read(fn).flat[U] med = np.median(upix) print('Band', band, ': Median', med) nlist[index] = med hist = nhist[index] for i in range(nnhist): if i < nnhist - 1: hist[i] = np.sum(upix == i) else: hist[i] = np.sum(upix >= i) assert (sum(hist) == len(upix)) print('Number of exposures histogram:', hist) ibricks = np.array(ibricks) print('Maximum number of sources:', max(nsrcs)) T = fits_table() T.brickname = np.array(bricklist) T.ra = bricks.ra[ibricks] T.dec = bricks.dec[ibricks] T.nexp_g = np.array(gn).astype(np.int16) T.nexp_r = np.array(rn).astype(np.int16) T.nexp_z = np.array(zn).astype(np.int16) T.nexphist_g = np.array(gnhist).astype(np.int32) T.nexphist_r = np.array(rnhist).astype(np.int32) T.nexphist_z = np.array(znhist).astype(np.int32) T.nobjs = np.array(nsrcs).astype(np.int16) T.npsf = np.array(npsf).astype(np.int16) T.nsimp = np.array(nsimp).astype(np.int16) T.nexp = np.array(nexp).astype(np.int16) T.ndev = np.array(ndev).astype(np.int16) T.ncomp = np.array(ncomp).astype(np.int16) T.psfsize_g = np.array(gpsfsize).astype(np.float32) T.psfsize_r = np.array(rpsfsize).astype(np.float32) T.psfsize_z = np.array(zpsfsize).astype(np.float32) T.ebv = np.array(ebv).astype(np.float32) T.trans_g = np.array(gtrans).astype(np.float32) T.trans_r = np.array(rtrans).astype(np.float32) T.trans_z = np.array(ztrans).astype(np.float32) T.writeto(opt.outfn)
def dojob(job, userimage, log=None, solve_command=None, solve_locally=None, tempfiles=None): print('dojob: tempdir:', tempfile.gettempdir()) jobdir = job.make_dir() #print('Created job dir', jobdir) #log = create_job_logger(job) #jobdir = job.get_dir() if log is None: log = create_job_logger(job) log.msg('Starting Job processing for', job) job.set_start_time() job.save() #os.chdir(dirnm) - not thread safe (working directory is global)! log.msg('Creating directory', jobdir) axyfn = 'job.axy' axypath = os.path.join(jobdir, axyfn) sub = userimage.submission log.msg('submission id', sub.id) df = userimage.image.disk_file img = userimage.image # Build command-line arguments for the augment-xylist program, which # detects sources in the image and adds processing arguments to the header # to produce a "job.axy" file. slo, shi = sub.get_scale_bounds() # Note, this must match Job.get_wcs_file(). wcsfile = 'wcs.fits' corrfile = 'corr.fits' axyflags = [] axyargs = { '--out': axypath, '--scale-low': slo, '--scale-high': shi, '--scale-units': sub.scale_units, '--wcs': wcsfile, '--corr': corrfile, '--rdls': 'rdls.fits', '--pixel-error': sub.positional_error, '--ra': sub.center_ra, '--dec': sub.center_dec, '--radius': sub.radius, '--downsample': sub.downsample_factor, # tuning-up maybe fixed; if not, turn it off with: #'--odds-to-tune': 1e9, # Other things we might want include... # --invert # -g / --guess-scale: try to guess the image scale from the FITS headers # --crpix-x <pix>: set the WCS reference point to the given position # --crpix-y <pix>: set the WCS reference point to the given position # -w / --width <pixels>: specify the field width # -e / --height <pixels>: specify the field height # -X / --x-column <column-name>: the FITS column name # -Y / --y-column <column-name> } if hasattr(img, 'sourcelist'): # image is a source list; use --xylist axyargs['--xylist'] = img.sourcelist.get_fits_path(tempfiles=tempfiles) w, h = img.width, img.height if sub.image_width: w = sub.image_width if sub.image_height: h = sub.image_height axyargs['--width'] = w axyargs['--height'] = h else: axyargs['--image'] = df.get_path() # UGLY if sub.parity == 0: axyargs['--parity'] = 'pos' elif sub.parity == 1: axyargs['--parity'] = 'neg' if sub.tweak_order == 0: axyflags.append('--no-tweak') else: axyargs['--tweak-order'] = '%i' % sub.tweak_order if sub.use_sextractor: axyflags.append('--use-source-extractor') if sub.crpix_center: axyflags.append('--crpix-center') if sub.invert: axyflags.append('--invert') cmd = 'augment-xylist ' for (k, v) in list(axyargs.items()): if v: cmd += k + ' ' + str(v) + ' ' for k in axyflags: cmd += k + ' ' log.msg('running: ' + cmd) (rtn, out, err) = run_command(cmd) if rtn: log.msg('out: ' + out) log.msg('err: ' + err) logmsg('augment-xylist failed: rtn val', rtn, 'err', err) raise Exception log.msg('created axy file', axypath) # shell into compute server... logfn = job.get_log_file() # the "tar" commands both use "-C" to chdir, and the ssh command # and redirect uses absolute paths. if solve_locally is not None: cmd = (('cd %(jobdir)s && %(solvecmd)s %(jobid)s %(axyfile)s >> ' + '%(logfile)s') % dict(jobid='job-%s-%i' % (settings.sitename, job.id), solvecmd=solve_locally, axyfile=axyfn, jobdir=jobdir, logfile=logfn)) log.msg('command:', cmd) w = os.system(cmd) if not os.WIFEXITED(w): log.msg('Solver failed (sent signal?)') logmsg('Call to solver failed for job', job.id) raise Exception rtn = os.WEXITSTATUS(w) if rtn: log.msg('Solver failed with return value %i' % rtn) logmsg('Call to solver failed for job', job.id, 'with return val', rtn) raise Exception log.msg('Solver completed successfully.') else: if solve_command is None: solve_command = 'ssh -x -T %(sshconfig)s' cmd = (( '(echo %(jobid)s; ' 'tar cf - --ignore-failed-read -C %(jobdir)s %(axyfile)s) | ' + solve_command + ' 2>>%(logfile)s | ' 'tar xf - --atime-preserve -m --exclude=%(axyfile)s -C %(jobdir)s ' '>>%(logfile)s 2>&1') % dict(jobid='job-%s-%i' % (settings.sitename, job.id), axyfile=axyfn, jobdir=jobdir, sshconfig=settings.ssh_solver_config, logfile=logfn)) log.msg('command:', cmd) w = os.system(cmd) if not os.WIFEXITED(w): log.msg('Solver failed (sent signal?)') logmsg('Call to solver failed for job', job.id) raise Exception rtn = os.WEXITSTATUS(w) if rtn: log.msg('Solver failed with return value %i' % rtn) logmsg('Call to solver failed for job', job.id, 'with return val', rtn) raise Exception log.msg('Solver completed successfully.') # Solved? wcsfn = os.path.join(jobdir, wcsfile) log.msg('Checking for WCS file', wcsfn) if os.path.exists(wcsfn): log.msg('WCS file exists') # Parse the wcs.fits file wcs = Tan(wcsfn, 0) # Convert to database model... tan = TanWCS(crval1=wcs.crval[0], crval2=wcs.crval[1], crpix1=wcs.crpix[0], crpix2=wcs.crpix[1], cd11=wcs.cd[0], cd12=wcs.cd[1], cd21=wcs.cd[2], cd22=wcs.cd[3], imagew=img.width, imageh=img.height) tan.save() log.msg('Created TanWCS:', tan) # Find field's healpix nside and index ra, dec, radius = tan.get_center_radecradius() nside = anutil.healpix_nside_for_side_length_arcmin(radius * 60) nside = int(2**round(math.log(nside, 2))) nside = max(1, nside) healpix = anutil.radecdegtohealpix(ra, dec, nside) try: sky_location, created = SkyLocation.objects.get_or_create( nside=nside, healpix=healpix) except MultipleObjectsReturned: log.msg('Multiple SkyLocations for nside %i, healpix %i' % (nside, healpix)) # arbitrarily take the first one. sky_location = SkyLocation.objects.filter(nside=nside, healpix=healpix)[0] log.msg('SkyLocation:', sky_location) # Find bounds for the Calibration object. r0, r1, d0, d1 = wcs.radec_bounds() # Find cartesian coordinates ra *= math.pi / 180 dec *= math.pi / 180 tempr = math.cos(dec) x = tempr * math.cos(ra) y = tempr * math.sin(ra) z = math.sin(dec) r = radius / 180 * math.pi calib = Calibration(raw_tan=tan, ramin=r0, ramax=r1, decmin=d0, decmax=d1, x=x, y=y, z=z, r=r, sky_location=sky_location) calib.save() log.msg('Created Calibration', calib) job.calibration = calib job.save() # save calib before adding machine tags job.status = 'S' job.user_image.add_machine_tags(job) job.user_image.add_sky_objects(job) else: job.status = 'F' job.set_end_time() job.save() log.msg('Finished job', job.id) logmsg('Finished job', job.id) return job.id
def get_unwise_tractor_image(basedir, tile, band, bandname=None, masked=True, **kwargs): ''' masked: read "-m" images, or "-u"? bandname: PhotoCal band name to use: default: "w%i" % band ''' if bandname is None: bandname = 'w%i' % band mu = 'm' if masked else 'u' thisdir = get_unwise_tile_dir(basedir, tile) base = os.path.join(thisdir, 'unwise-%s-w%i-' % (tile, band)) imfn = base + 'img-%s.fits' % mu ivfn = base + 'invvar-%s.fits.gz' % mu #ppfn = base + 'std-%s.fits.gz' % mu nifn = base + 'n-%s.fits.gz' % mu print 'Reading', imfn wcs = Tan(imfn) twcs = ConstantFitsWcs(wcs) img = fitsio.FITS(imfn)[0] H, W = img.get_info()['dims'] H, W = int(H), int(W) roi, nil = interpret_roi(twcs, (H, W), **kwargs) if roi is None: # No overlap with ROI return None (x0, x1, y0, y1) = roi twcs.setX0Y0(x0, y0) roislice = (slice(y0, y1), slice(x0, x1)) img = img[roislice] print 'Reading', ivfn invvar = fitsio.FITS(ivfn)[0][roislice] #print 'Reading', ppfn #pp = fitsio.FITS(ppfn)[0][roislice] print 'Reading', nifn nims = fitsio.FITS(nifn)[0][roislice] #print 'Median # ims:', np.median(nims) good = (nims > 0) invvar[np.logical_not(good)] = 0. sig1 = 1. / np.sqrt(np.median(invvar[good])) # Load the average PSF model (generated by wise_psf.py) psffn = os.path.join(os.path.dirname(__file__), 'wise-psf-avg.fits') print 'Reading', psffn P = fits_table(psffn, hdu=band) psf = GaussianMixturePSF(P.amp, P.mean, P.var) sky = 0. tsky = ConstantSky(sky) # if opt.errfrac > 0: # nz = (iv > 0) # iv2 = np.zeros_like(invvar) # iv2[nz] = 1./(1./invvar[nz] + (img[nz] * opt.errfrac)**2) # print 'Increasing error estimate by', opt.errfrac, 'of image flux' # invvar = iv2 tim = Image(data=img, invvar=invvar, psf=psf, wcs=twcs, sky=tsky, photocal=LinearPhotoCal(1., band=bandname), name='unWISE %s W%i' % (tile, band), domask=False) tim.sig1 = sig1 tim.roi = roi tim.nims = nims return tim
# plt.plot(x, L2, 'b-') # plt.savefig('l1.png') x = np.linspace(-3.5, 4.5, 8192).astype(np.float32) L1 = np.zeros_like(x) L2 = np.zeros_like(x) lanczos3_filter(x, L1) lanczos3_filter_table(x, L2, 1) print('L2 - L1 RMS:', np.sqrt(np.mean((L2 - L1)**2))) if True: ra, dec = 0., 0., pixscale = 1e-3 W, H = 10, 1 cowcs = Tan(ra, dec, (W + 1) / 2., (H + 1) / 2., -pixscale, 0., 0., pixscale, W, H) dx, dy = 0.25, 0. wcs = Tan(ra, dec, (W + 1) / 2. + dx, (H + 1) / 2. + dy, -pixscale, 0., 0., pixscale, W, H) pix = np.zeros((H, W), np.float32) pix[0, W / 2] = 1. Yo, Xo, Yi, Xi, (cpix, ) = resample_with_wcs(cowcs, wcs, [pix], 3) print('C', cpix) Yo2, Xo2, Yi2, Xi2, (pypix, ) = resample_with_wcs(cowcs, wcs, [pix], 3, cinterp=False, table=False) print('Py', pypix)