def do_plot_facet_offsets(t,regfile,savefig=None):
    ''' convenience function to plot offsets '''
    if savefig is not None and os.path.isfile(savefig):
        warn('Figure file %s exists, not re-making it' % savefig)
    else:
        cra,cdec=get_centpos()
        r=RegPoly(regfile,cra,cdec)
        if isinstance(t,str):
            t=Table.read(t)
        if 'Facet' not in t.columns:
            r.add_facet_labels(t)
        plot_offsets(t,r.clist,'red')
        if savefig is not None:
            plt.savefig(savefig)
Exemple #2
0
 def read_regfile(self,regfile):
     cra,cdec=get_centpos()
     self.r=RegPoly(regfile,cra,cdec)
     self.polys=self.r.oclist
     self.labels=self.r.ollist
     self.plab=self.r.plab
     self.pli=self.r.plab_int
Exemple #3
0
def convert_regionfile_to_poly(inregfile):
    cra, cdec = get_centpos()
    r = RegPoly(inregfile, cra, cdec)
    polystringlist = []
    for p in sorted(list(set(r.plab_int))):
        polylist = []
        for i, poly in enumerate(r.oclist):
            if r.plab_int[i] == p:
                polylist.append(poly)
        # now polylist contains all the polygons in this direction, in order
        polystring = 'fk5;'
        for poly in polylist:
            polystring += polylist_to_string(poly) + ';'
        polystringlist.append(polystring[:-1])
    return polystringlist
Exemple #4
0
class Offsets(object):
    def __init__(self,
                 prefix,
                 n=45,
                 cellsize=1.5,
                 imroot=None,
                 fitmethod='mcmc'):
        self.prefix = prefix
        self.n = n
        self.chains = []
        self.cellsize = cellsize
        self.imroot = imroot
        self.fitmethod = fitmethod
        if imroot is not None:
            self.read_regfile(imroot + '.tessel.reg')

    def read_regfile(self, regfile):
        cra, cdec = get_centpos()
        self.r = RegPoly(regfile, cra, cdec)
        self.polys = self.r.oclist
        self.labels = self.r.ollist
        self.plab = self.r.plab
        self.pli = self.r.plab_int

    def find_offsets(self, tf, ot, sep=1.0):
        self.dral = []
        self.ddecl = []
        self.lofar_table = tf
        for f in range(self.n):
            t = tf[tf['Facet'] == f]
            if len(t) == 0:
                print 'No sources in facet', f
                self.dral.append(None)
                self.ddecl.append(None)
                continue
            minra = np.min(t['RA'])
            maxra = np.max(t['RA'])
            mindec = np.min(t['DEC'])
            maxdec = np.max(t['DEC'])
            otf = ot[(ot['ra'] >= (minra - sep / 60.0))
                     & (ot['ra'] <= (maxra + sep / 60.0)) &
                     (ot['dec'] >=
                      (mindec - sep / 60.0)) & (ot['dec'] <=
                                                (maxdec + sep / 60.0))]
            print 'Facet %2i has %4i LOFAR sources and %6i comparison sources' % (
                f, len(t), len(otf))

            dral = []
            ddecl = []

            for r in t:
                ra = r['RA']
                dec = r['DEC']
                dra = 3600.0 * (ra - otf['ra']) * np.cos(dec * np.pi / 180.0)
                ddec = 3600.0 * (dec - otf['dec'])
                d2d = np.sqrt(dra**2.0 + ddec**2.0)

                d2dmask = d2d < sep * 60.0

                dral += list(dra[d2dmask])
                ddecl += list(ddec[d2dmask])

            self.dral.append((np.array(dral)).flatten())
            self.ddecl.append((np.array(ddecl)).flatten())

    def save_offsets(self):
        for i in range(self.n):
            np.save(self.prefix + '/dra-' + str(f) + '.npy', self.dral[i])
            np.save(self.prefix + '/ddec-' + str(f) + '.npy', self.ddecl[i])

    def load_offsets(self):
        self.dral = []
        self.ddecl = []
        for i in range(self.n):
            self.dral.append(np.load(self.prefix + '/dra-' + str(i) + '.npy'))
            self.ddecl.append(np.load(self.prefix + '/ddec-' + str(i) +
                                      '.npy'))

    def fit_chi2(self, h):
        height = np.median(h)
        norm = np.max(h) - height
        peak = self.bcenter[np.argmax(h)]
        popt, pcov = curve_fit(model, self.bcenter, h,
                               [norm, 0.5, peak, height],
                               1.0 + np.sqrt(h + 0.75))
        return popt, np.sqrt(np.diagonal(pcov))

    def lnlike(self, X, h):
        if X[0] < 0 or X[3] < 0 or X[1] < 0:
            return -np.inf
        mv = model(self.bcenter, *X)
        # Eq A3 of 3C305 paper; mv is mu, h is n
        lv = h * np.log(mv) - mv - gammaln(h + 1)
        return np.sum(lv)

    def lnpost(self, parms, h):
        return self.lnprior(parms) + self.lnlike(parms, h)

    def lnprior(self, X):
        # gaussian norm, sigma, offset; baseline norm
        if X[0] < 0 or X[3] < 0 or X[1] < 0:
            return -np.inf
        if X[1] > 5:
            return -np.inf
        if np.abs(X[2]) > 5:
            return -np.inf
        #return -np.log(X[0])-np.log(X[3])
        return 0

    def fit_emcee(self, h):
        import emcee
        height = np.median(h)
        norm = np.max(h) - height
        peak = self.bcenter[np.argmax(h)]
        if np.abs(peak) > 3.0:
            peak = 0.0
        nwalkers = 24
        ndim = 4
        parms = []
        for i in range(nwalkers):
            parms.append([
                norm + np.random.normal(0, 0.5),
                0.5 + np.random.normal(0, 0.05),
                peak + np.random.normal(0, 0.1),
                height + np.random.normal(0, 2.0)
            ])
        parms = np.array(parms)
        for i in (0, 1, 3):
            parms[:, i] = np.abs(parms[:, i])
        sampler = emcee.EnsembleSampler(nwalkers,
                                        ndim,
                                        self.lnpost,
                                        args=(h, ))

        sampler.run_mcmc(parms, 1000)
        chain = sampler.chain
        # find initial errors
        samples = chain[:, 200:, :].reshape((-1, ndim))
        samplest = samples.transpose()
        prange = np.percentile(samplest, (10, 90), axis=1)
        wanted = []
        for k in range(nwalkers):
            wparms = np.mean(chain[k, 200:, :], axis=0)
            if np.all(wparms > prange[0]) and np.all(wparms < prange[1]):
                wanted.append(k)

        # now use only the walkers that didn't get lost
        chain = chain[wanted, :, :]
        samples = chain[:, 200:, :].reshape((-1, ndim))
        samplest = samples.transpose()

        self.chains.append(chain)
        means = np.mean(samplest, axis=1)
        errors = np.percentile(samplest, (16, 84), axis=1) - means
        err = (errors[1] - errors[0]) / 2.0
        return means, err

    def fit_offsets(self, minv=-40, maxv=40, nbins=150):
        if self.fitmethod == 'mcmc':
            fitfn = self.fit_emcee
        elif self.fitmethod == 'chi2':
            fitfn = self.fit_chi2
        else:
            raise NotImplementedError('Fit method ' + self.fitmethod)
        self.bins = np.linspace(minv, maxv, nbins + 1)
        self.bcenter = 0.5 * (self.bins[:-1] + self.bins[1:])
        self.rar = []
        self.decr = []
        self.rae = []
        self.dece = []
        self.rah = []
        self.dech = []
        for i in range(self.n):
            print 'Facet', i
            if self.dral[i] is None:
                print 'Not fitting, no data'
                self.rar.append([0, 0, 0, 0])
                self.rae.append([100, 100, 100, 100])
                self.decr.append([0, 0, 0, 0])
                self.dece.append([100, 100, 100, 100])
                pass
            else:
                h, _ = np.histogram(self.dral[i], self.bins)
                self.rah.append(h)
                p, perr = fitfn(h)
                print 'RA Offset is ', p[2], '+/-', perr[2]
                self.rar.append(p)
                self.rae.append(perr)
                h, _ = np.histogram(self.ddecl[i], self.bins)
                self.dech.append(h)
                p, perr = fitfn(h)
                self.decr.append(p)
                self.dece.append(perr)
                print 'DEC Offset is ', p[2], '+/-', perr[2]
        self.rar = np.array(self.rar)
        self.rae = np.array(self.rae)
        self.decr = np.array(self.decr)
        self.dece = np.array(self.dece)

    def save_fits(self):
        np.save(
            self.prefix + '-facet_offsets.npy',
            np.array([
                self.rar[:, 2], self.decr[:, 2], self.rae[:, 2], self.dece[:,
                                                                           2]
            ]).T)

    def plot_fits(self, pdffile):
        from matplotlib.backends.backend_pdf import PdfPages
        import matplotlib.pyplot as plt
        with PdfPages(pdffile) as pdf:
            for i in range(self.n):
                plt.subplot(2, 1, 1)
                plt.plot(self.bcenter, self.rah[i])
                plt.plot(self.bcenter, model(self.bcenter, *self.rar[i]))
                plt.subplot(2, 1, 2)
                plt.plot(self.bcenter, self.dech[i])
                plt.plot(self.bcenter, model(self.bcenter, *self.decr[i]))
                plt.suptitle('Facet ' + str(i))
                pdf.savefig()
                plt.close()

    def plot_chains(self, pdffile):
        from matplotlib.backends.backend_pdf import PdfPages
        import matplotlib.pyplot as plt
        with PdfPages(pdffile) as pdf:
            for j, c in enumerate(self.chains):
                labels = ['norm', 'sigma', 'offset', 'bline']
                ndim = len(labels)
                for i in range(len(labels)):
                    plt.subplot(ndim, 1, i + 1)
                    plt.plot(c[:, :, i].transpose())
                    plt.ylabel(labels[i])
                    plt.xlabel('Samples')
                facet = j / 2
                chain = j % 2
                plt.suptitle('Facet %i chain %i' % (facet, chain))
                pdf.savefig()
                plt.close()

    def plot_offsets(self, lofar_table=None):
        import matplotlib.pyplot as plt
        if lofar_table is not None:
            self.lofar_table = Table.read(lofar_table)
        tf = self.lofar_table

        poly, labels = self.polys, self.labels

        basesize = 10
        rarange = (np.min(tf['RA']), np.max(tf['RA']))
        decrange = (np.min(tf['DEC']), np.max(tf['DEC']))
        mdec = np.mean(decrange)
        xstrue = (rarange[1] - rarange[0]) * np.cos(mdec * np.pi / 180.0)
        ystrue = decrange[1] - decrange[0]
        plt.figure(figsize=(basesize * xstrue / ystrue, basesize))
        plt.xlim(rarange)
        plt.ylim(decrange)
        plt.xlabel('RA')
        plt.ylabel('DEC')
        plt.title('Offsets with method ' + self.prefix)

        for p in poly:
            x = [pt[0] for pt in p]
            y = [pt[1] for pt in p]
            plt.plot(x, y, color='black', ls=':')

        mra = []
        mdec = []
        mdra = []
        mddec = []
        for f in range(self.n):
            t = tf[tf['Facet'] == f]
            if len(t) > 0:
                mra.append(np.mean(t['RA']))
                mdec.append(np.mean(t['DEC']))
                plt.text(mra[-1], mdec[-1], str(f), color='blue')
                mdra.append(self.rar[f, 2])
                mddec.append(self.decr[f, 2])
                print f, len(t), mra[-1], mdec[-1], mdra[-1], mddec[-1]

                plt.gca().invert_xaxis()
                plt.quiver(mra,
                           mdec,
                           mdra,
                           mddec,
                           units='xy',
                           angles='xy',
                           scale=1.0,
                           color='red')
                plt.quiver(np.mean(tf['RA']),
                           np.mean(tf['DEC']),
                           1.0,
                           0.0,
                           units='xy',
                           angles='xy',
                           scale=1.0,
                           color='green')
                plt.text(np.mean(tf['RA']),
                         np.mean(tf['DEC']),
                         '1 arcsec',
                         color='green')

        plt.savefig('SKO-' + self.prefix + '.png')

    def offsets_to_facetshift(self, filename):

        cellsize = self.cellsize
        outfile = open(filename, 'w')
        lines = open('%s.facetCoord.txt' % self.imroot).readlines()
        for l in lines:
            bits = [b.strip() for b in l.split(',')]
            rar = float(bits[2])
            ra = rar / degtorad
            decr = float(bits[3])
            dec = decr / degtorad
            number = self.r.which_poly(ra, dec)
            #print 'Direction',pli[number]
            direction = self.pli[number]
            print >> outfile, rar, decr, -self.rar[
                direction, 2] / cellsize, self.decr[direction, 2] / cellsize
        outfile.close()

    def make_astrometry_map(self, outname, factor):
        # factor tells us how much bigger than cellsize the pixels will be
        hdus = fits.open(self.imroot + '.app.restored.fits')
        _, _, yd, xd = hdus[0].data.shape
        yd /= factor
        xd /= factor
        hdus[0].header['CDELT1'] *= factor
        hdus[0].header['CDELT2'] *= factor
        hdus[0].header['CRPIX1'] /= factor
        hdus[0].header['CRPIX2'] /= factor
        w = WCS(hdus[0].header)
        rmap = np.ones((1, 1, yd, xd)) * np.nan
        # this would be faster with use of e.g. PIL
        for y in range(yd):
            print '.',
            sys.stdout.flush()
            xv = np.array(range(xd))
            yv = y * np.ones_like(xv)
            ra, dec, _, _ = w.wcs_pix2world(xv, yv, 0, 0, 0)
            dra, ddec = self.r.coordconv(ra, dec)[1]
            for i, x in enumerate(xv):
                number = self.r.which_poly(dra[i], ddec[i], convert=False)
                if number is not None:
                    direction = self.pli[number]
                    rmap[0, 0, y, x] = np.sqrt(self.rae[direction, 2]**2.0 +
                                               self.dece[direction, 2]**2.0)
        print
        hdus[0].data = rmap
        hdus.writeto(outname, clobber=True)

    def save(self, filename):
        f = file(filename, 'wb')
        pickle.dump(self, f, pickle.HIGHEST_PROTOCOL)
        f.close()

    @staticmethod
    def load(filename):
        with file(filename, 'rb') as f:
            return pickle.load(f)
Exemple #5
0
class Offsets(object):
    def __init__(self,prefix,n=45,cellsize=1.5,imroot=None,fitmethod='mcmc'):
        self.prefix=prefix
        self.n=n
        self.chains=[]
        self.cellsize=cellsize
        self.imroot=imroot
        self.fitmethod=fitmethod
        if imroot is not None:
            self.read_regfile(imroot+'.tessel.reg')

    def read_regfile(self,regfile):
        cra,cdec=get_centpos()
        self.r=RegPoly(regfile,cra,cdec)
        self.polys=self.r.oclist
        self.labels=self.r.ollist
        self.plab=self.r.plab
        self.pli=self.r.plab_int

    def find_offsets(self,tf,ot,sep=1.0):
        self.dral=[]
        self.ddecl=[]
        self.lofar_table=tf
        for f in range(self.n):
            t=tf[tf['Facet']==f]
            if len(t)==0:
                print 'No sources in facet',f
                self.dral.append(None)
                self.ddecl.append(None)
                continue
            minra=np.min(t['RA'])
            maxra=np.max(t['RA'])
            mindec=np.min(t['DEC'])
            maxdec=np.max(t['DEC'])
            otf=ot[(ot['ra']>=(minra-sep/60.0)) & (ot['ra']<=(maxra+sep/60.0)) &
                   (ot['dec']>=(mindec-sep/60.0)) & (ot['dec']<=(maxdec+sep/60.0))]
            print 'Facet %2i has %4i LOFAR sources and %6i comparison sources' % (f,len(t),len(otf))

            dral=[]
            ddecl=[]

            for r in t:
                ra=r['RA']
                dec=r['DEC']
                dra=3600.0*(ra-otf['ra'])*np.cos(dec*np.pi/180.0)
                ddec=3600.0*(dec-otf['dec'])
                d2d=np.sqrt(dra**2.0+ddec**2.0)

                d2dmask = d2d<sep*60.0

                dral+=list(dra[d2dmask])
                ddecl+=list(ddec[d2dmask])

            self.dral.append((np.array(dral)).flatten())
            self.ddecl.append((np.array(ddecl)).flatten())

    def save_offsets(self):
        for i in range(self.n):
            np.save(self.prefix+'/dra-'+str(f)+'.npy',self.dral[i])
            np.save(self.prefix+'/ddec-'+str(f)+'.npy',self.ddecl[i])

    def load_offsets(self):
        self.dral=[]
        self.ddecl=[]
        for i in range(self.n):
            self.dral.append(np.load(self.prefix+'/dra-'+str(i)+'.npy'))
            self.ddecl.append(np.load(self.prefix+'/ddec-'+str(i)+'.npy'))
            
    def fit_chi2(self,h):
        height=np.median(h)
        norm=np.max(h)-height
        peak=self.bcenter[np.argmax(h)]
        popt,pcov=curve_fit(model,self.bcenter,h,[norm,0.5,peak,height],1.0+np.sqrt(h+0.75))
        return popt,np.sqrt(np.diagonal(pcov))

    def lnlike(self,X,h):
        if X[0]<0 or X[3]<0 or X[1]<0:
            return -np.inf
        mv=model(self.bcenter,*X)
        # Eq A3 of 3C305 paper; mv is mu, h is n
        lv=h*np.log(mv)-mv-gammaln(h+1)
        return np.sum(lv)

    def lnpost(self,parms,h):
        return self.lnprior(parms)+self.lnlike(parms,h)

    def lnprior(self,X):
        # gaussian norm, sigma, offset; baseline norm
        if X[0]<0 or X[3]<0 or X[1]<0:
            return -np.inf
        if X[1]>5:
            return -np.inf
        if np.abs(X[2])>5:
            return -np.inf
        #return -np.log(X[0])-np.log(X[3])
        return 0

    def fit_emcee(self,h):
        import emcee
        height=np.median(h)
        norm=np.max(h)-height
        peak=self.bcenter[np.argmax(h)]
        if np.abs(peak)>3.0:
            peak=0.0
        nwalkers=24
        ndim=4
        parms=[]
        for i in range(nwalkers):
            parms.append([norm+np.random.normal(0,0.5),0.5+np.random.normal(0,0.05),peak+np.random.normal(0,0.1),height+np.random.normal(0,2.0)])
        parms=np.array(parms)
        for i in (0,1,3):
            parms[:,i]=np.abs(parms[:,i])
        sampler = emcee.EnsembleSampler(nwalkers, ndim, self.lnpost, args=(h,))
        
        sampler.run_mcmc(parms,1000)
        chain=sampler.chain
        # find initial errors
        samples=chain[:, 200:, :].reshape((-1, ndim))
        samplest=samples.transpose()
        prange=np.percentile(samplest,(10,90),axis=1)
        wanted=[]
        for k in range(nwalkers):
            wparms=np.mean(chain[k,200:,:],axis=0)
            if np.all(wparms>prange[0]) and np.all(wparms<prange[1]):
                wanted.append(k)
        
        # now use only the walkers that didn't get lost
        chain=chain[wanted, :, :]
        samples=chain[:, 200:, :].reshape((-1, ndim))
        samplest=samples.transpose()

        self.chains.append(chain)
        means=np.mean(samplest,axis=1)
        errors=np.percentile(samplest,(16,84),axis=1)-means
        err=(errors[1]-errors[0])/2.0
        return means,err

    def fit_offsets(self,minv=-40,maxv=40,nbins=150):
        if self.fitmethod=='mcmc':
            fitfn=self.fit_emcee
        elif self.fitmethod=='chi2':
            fitfn=self.fit_chi2
        else:
            raise NotImplementedError('Fit method '+self.fitmethod)
        self.bins=np.linspace(minv,maxv,nbins+1)
        self.bcenter=0.5*(self.bins[:-1]+self.bins[1:])
        self.rar=[]
        self.decr=[]
        self.rae=[]
        self.dece=[]
        self.rah=[]
        self.dech=[]
        for i in range(self.n):
            print 'Facet',i
            if self.dral[i] is None:
                print 'Not fitting, no data'
                self.rar.append([0,0,0,0])
                self.rae.append([100,100,100,100])
                self.decr.append([0,0,0,0])
                self.dece.append([100,100,100,100])
                pass
            else:
                h,_=np.histogram(self.dral[i],self.bins)
                self.rah.append(h)
                p,perr=fitfn(h)
                print 'RA Offset is ',p[2],'+/-',perr[2]
                self.rar.append(p)
                self.rae.append(perr)
                h,_=np.histogram(self.ddecl[i],self.bins)
                self.dech.append(h)
                p,perr=fitfn(h)
                self.decr.append(p)
                self.dece.append(perr)
                print 'DEC Offset is ',p[2],'+/-',perr[2]
        self.rar=np.array(self.rar)
        self.rae=np.array(self.rae)
        self.decr=np.array(self.decr)
        self.dece=np.array(self.dece)

    def save_fits(self):
        np.save(self.prefix+'-facet_offsets.npy',np.array([self.rar[:,2],self.decr[:,2],self.rae[:,2],self.dece[:,2]]).T)

    def plot_fits(self,pdffile):
        from matplotlib.backends.backend_pdf import PdfPages
        import matplotlib.pyplot as plt
        with PdfPages(pdffile) as pdf:
            for i in range(self.n):
                plt.subplot(2,1,1)
                plt.plot(self.bcenter,self.rah[i])
                plt.plot(self.bcenter,model(self.bcenter,*self.rar[i]))
                plt.subplot(2,1,2)
                plt.plot(self.bcenter,self.dech[i])
                plt.plot(self.bcenter,model(self.bcenter,*self.decr[i]))
                plt.suptitle('Facet '+str(i))
                pdf.savefig()
                plt.close()

    def plot_chains(self,pdffile):
        from matplotlib.backends.backend_pdf import PdfPages
        import matplotlib.pyplot as plt
        with PdfPages(pdffile) as pdf:
            for j,c in enumerate(self.chains):
                labels=['norm','sigma','offset','bline']
                ndim=len(labels)
                for i in range(len(labels)):
                    plt.subplot(ndim,1,i+1)
                    plt.plot(c[:,:,i].transpose())
                    plt.ylabel(labels[i])
                    plt.xlabel('Samples')
                facet=j/2
                chain=j%2
                plt.suptitle('Facet %i chain %i' % (facet,chain))
                pdf.savefig()
                plt.close()

    def plot_offsets(self,lofar_table=None):
        import matplotlib.pyplot as plt
        if lofar_table is not None:
            self.lofar_table=Table.read(lofar_table)
        tf=self.lofar_table

        poly,labels=self.polys,self.labels

        basesize=10
        rarange=(np.min(tf['RA']),np.max(tf['RA']))
        decrange=(np.min(tf['DEC']),np.max(tf['DEC']))
        mdec=np.mean(decrange)
        xstrue=(rarange[1]-rarange[0])*np.cos(mdec*np.pi/180.0)
        ystrue=decrange[1]-decrange[0]
        plt.figure(figsize=(basesize*xstrue/ystrue, basesize))
        plt.xlim(rarange)
        plt.ylim(decrange)
        plt.xlabel('RA')
        plt.ylabel('DEC')
        plt.title('Offsets with method '+self.prefix)

        for p in poly:
            x=[pt[0] for pt in p]
            y=[pt[1] for pt in p]
            plt.plot(x,y,color='black',ls=':')

        mra=[]
        mdec=[]
        mdra=[]
        mddec=[]
        for f in range(self.n):
            t=tf[tf['Facet']==f]
            if len(t)>0:
                mra.append(np.mean(t['RA']))
                mdec.append(np.mean(t['DEC']))
                plt.text(mra[-1],mdec[-1],str(f),color='blue')
                mdra.append(self.rar[f,2])
                mddec.append(self.decr[f,2])
                print f,len(t),mra[-1],mdec[-1],mdra[-1],mddec[-1]

                plt.gca().invert_xaxis()
                plt.quiver(mra,mdec,mdra,mddec,units = 'xy', angles='xy', scale=1.0,color='red')
                plt.quiver(np.mean(tf['RA']),np.mean(tf['DEC']),1.0,0.0,units = 'xy', angles='xy', scale=1.0,color='green')
                plt.text(np.mean(tf['RA']),np.mean(tf['DEC']),'1 arcsec',color='green')

        plt.savefig('SKO-'+self.prefix+'.png')

    def offsets_to_facetshift(self,filename):

        cellsize=self.cellsize
        outfile=open(filename,'w')
        lines=open('%s.facetCoord.txt'%self.imroot).readlines()
        for l in lines:
            bits=[b.strip() for b in l.split(',')]
            rar=float(bits[2])
            ra=rar/degtorad
            decr=float(bits[3])
            dec=decr/degtorad
            number=self.r.which_poly(ra,dec)
            #print 'Direction',pli[number]
            direction=self.pli[number]
            print >>outfile, rar,decr,-self.rar[direction,2]/cellsize,self.decr[direction,2]/cellsize
        outfile.close()

    def make_astrometry_map(self,outname,factor):
        # factor tells us how much bigger than cellsize the pixels will be
        hdus=fits.open(self.imroot+'.app.restored.fits')
        _,_,yd,xd=hdus[0].data.shape
        yd/=factor
        xd/=factor
        hdus[0].header['CDELT1']*=factor
        hdus[0].header['CDELT2']*=factor
        hdus[0].header['CRPIX1']/=factor
        hdus[0].header['CRPIX2']/=factor
        w=WCS(hdus[0].header)
        rmap=np.ones((1,1,yd,xd))*np.nan
        # this would be faster with use of e.g. PIL
        for y in range(yd):
            print '.',
            sys.stdout.flush()
            xv=np.array(range(xd))
            yv=y*np.ones_like(xv)
            ra,dec,_,_=w.wcs_pix2world(xv,yv,0,0,0)
            dra,ddec=self.r.coordconv(ra,dec)[1]
            for i,x in enumerate(xv):
                number=self.r.which_poly(dra[i],ddec[i],convert=False)
                if number is not None:
                    direction=self.pli[number]
                    rmap[0,0,y,x]=np.sqrt(self.rae[direction,2]**2.0+self.dece[direction,2]**2.0)
        print
        hdus[0].data=rmap
        hdus.writeto(outname,clobber=True)

    def save(self,filename):
        f = file(filename, 'wb')
        pickle.dump(self, f, pickle.HIGHEST_PROTOCOL)
        f.close()

    @staticmethod
    def load(filename):
        with file(filename, 'rb') as f:
            return pickle.load(f)