def linearizedSol_bs(Obsdata, currImage, Prior, alpha=100, beta=100, reg="patch"): # note what beta is # normalize the prior # TODO: SHOULD THIS BE DONE?? zbl = np.max(np.abs(Obsdata.unpack(['vis'])['vis'])) nprior = zbl * Prior.imvec / np.sum(Prior.imvec) if reg == "patch": linRegTerm, constRegTerm = spatchlingrad(currImage.imvec, nprior) # Get bispectra data biarr = Obsdata.bispectra(mode="all", count="max") uv1 = np.hstack((biarr['u1'].reshape(-1,1), biarr['v1'].reshape(-1,1))) uv2 = np.hstack((biarr['u2'].reshape(-1,1), biarr['v2'].reshape(-1,1))) uv3 = np.hstack((biarr['u3'].reshape(-1,1), biarr['v3'].reshape(-1,1))) bispec = biarr['bispec'] sigs = biarr['sigmab'] # Compute the fourier matrices A3 = (vb.ftmatrix(currImage.psize, currImage.xdim, currImage.ydim, uv1, pulse=currImage.pulse), vb.ftmatrix(currImage.psize, currImage.xdim, currImage.ydim, uv2, pulse=currImage.pulse), vb.ftmatrix(currImage.psize, currImage.xdim, currImage.ydim, uv3, pulse=currImage.pulse) ) Alin, blin = computeLinTerms_bi(currImage.imvec, A3, bispec, sigs, currImage.xdim*currImage.ydim, alpha=alpha, reg=reg) out = np.linalg.solve(Alin + beta*linRegTerm, blin + beta*constRegTerm); return vb.Image(out.reshape((currImage.ydim, currImage.xdim)), currImage.psize, currImage.ra, currImage.dec, rf=currImage.rf, source=currImage.source, mjd=currImage.mjd, pulse=currImage.pulse)
def self_cal_scan(scan, im, method="both"): """Self-calibrate a scan""" # calculating image true visibs (beware no scattering here..) uv = np.hstack((scan["u"].reshape(-1, 1), scan["v"].reshape(-1, 1))) A = vb.ftmatrix(im.psize, im.xdim, im.ydim, uv, pulse=im.pulse) V = np.dot(A, im.imvec) sites = list(set(scan["t1"]).union(set(scan["t2"]))) tkey = {b: a for a, b in enumerate(sites)} tidx1 = [tkey[row["t1"]] for row in scan] tidx2 = [tkey[row["t2"]] for row in scan] sigma_inv = 1.0 / scan["sigma"] def errfunc(gpar): g = gpar.astype(np.float64).view(dtype=np.complex128) # all the forward site gains (complex) if method == "phase": g = g / np.abs(g) if method == "amp": g = np.abs(g) Verr = scan["vis"] - g[tidx1] * g[tidx2].conj() * V chisq = np.sum((Verr.real * sigma_inv) ** 2) + np.sum((Verr.imag * sigma_inv) ** 2) return chisq gpar_guess = np.ones(len(sites), dtype=np.complex128).view(dtype=np.float64) optdict = {"maxiter": 1000} # minimizer params res = opt.minimize(errfunc, gpar_guess, method="Powell", options=optdict) g_fit = res.x.view(np.complex128) if method == "phase": g_fit = g_fit / np.abs(g_fit) if method == "amp": g_fit = np.abs(g_fit) gij_inv = (g_fit[tidx1] * g_fit[tidx2].conj()) ** (-1) print np.abs(gij_inv) scan["vis"] = gij_inv * scan["vis"] scan["qvis"] = gij_inv * scan["qvis"] scan["uvis"] = gij_inv * scan["uvis"] scan["sigma"] = np.abs(gij_inv) * scan["sigma"] return scan
def observe_same(self, obs, sgrscat=False, repeat=False): """Observe the movie on the same baselines as an existing observation object if sgrscat==True, the visibilites will be blurred by the Sgr A* scattering kernel Does NOT add noise """ # Check for agreement in coordinates and frequency if (self.ra!= obs.ra) or (self.dec != obs.dec): raise Exception("Image coordinates are not the same as observtion coordinates!") if (self.rf != obs.rf): raise Exception("Image frequency is not the same as observation frequency!") mjdstart = self.mjd mjdend = self.mjd + (len(self.frames)*self.framedur) / 86400.0 #!AC use astropy date conversion # Get data obslist = obs.tlist() # Observation MJDs in range? # !AC use astropy date conversion!! obsmjds = np.array([(np.floor(obs.mjd) + (obsdata[0]['time'])/24.0) for obsdata in obslist]) if (not repeat) and ((obsmjds < mjdstart) + (obsmjds > mjdend)).any(): raise Exception("Obs times outside of movie range of MJD %f - %f" % (mjdstart, mjdend)) # Observe nearest frame obsdata_out = [] for i in xrange(len(obslist)): obsdata = obslist[i] # Frame number mjd = obsmjds[i] n = int(np.floor((mjd - mjdstart) * 86400.0 / self.framedur)) if (n >= len(self.frames)): if repeat: n = np.mod(n, len(self.frames)) else: raise Exception("Obs times outside of movie range of MJD %f - %f" % (mjdstart, mjdend)) # Extract uv data & perform DFT uv = obsdata[['u','v']].view(('f8',2)) mat = vb.ftmatrix(self.psize, self.xdim, self.ydim, uv, pulse=self.pulse) vis = np.dot(mat, self.frames[n]) # If there are polarized images, observe them: qvis = np.zeros(len(vis)) uvis = np.zeros(len(vis)) if len(self.qframes): qvis = np.dot(mat, self.qframes[n]) uvis = np.dot(mat, self.uframes[n]) # Scatter the visibilities with the SgrA* kernel if sgrscat: for i in range(len(vis)): ker = sgra_kernel_uv(self.rf, uv[i,0], uv[i,1]) vis[i] *= ker qvis[i] *= ker uvis[i] *= ker # Put the visibilities back in the obsdata array obsdata['vis'] = vis obsdata['qvis'] = qvis obsdata['uvis'] = uvis if len(obsdata_out): obsdata_out = np.hstack((obsdata_out, obsdata)) else: obsdata_out = obsdata # Return observation object obs_no_noise = vb.Obsdata(self.ra, self.dec, self.rf, obs.bw, obsdata_out, obs.tarr, source=self.source, mjd=self.mjd) return obs_no_noise
def maxen_dynamic_bs(Obsdata_List, Prior_List, Flux_List, maxit=100, alpha=100, gamma=500, delta=500, beta=5, beta_blur=5, entropy="simple", stop=1e-10, ipynb=False, refresh_interval = 1000): """Run maximum entropy with the bispectrum Uses I = exp(I') change of variables. Obsdata is an Obsdata object, and Prior is an Image object. Returns Image object. The lagrange multiplier alpha is not a free parameter """ print "Dynamic Imaging with the bispectrum. . ." gauss = np.array([[np.exp(-1.0*i**2/(2*beta_blur**2) - 1.0*j**2/(2.*beta_blur**2)) for i in np.linspace((Prior_List[0].xdim-1)/2., -(Prior_List[0].xdim-1)/2., num=Prior_List[0].xdim)] for j in np.linspace((Prior_List[0].ydim-1)/2., -(Prior_List[0].ydim-1)/2., num=Prior_List[0].ydim)]) #linespace makes thing symmetric gauss = gauss[0:Prior_List[0].ydim, 0:Prior_List[0].xdim] gauss = gauss / np.sum(gauss) # normalize to 1 N_frame = len(Obsdata_List) N_pixel = Prior_List[0].xdim #pixel dimension # Catch problem if uvrange < largest baseline uvrange = 1./Prior_List[0].psize maxbl = np.max(Obsdata_List[0].unpack(['uvdist'])['uvdist']) if uvrange < maxbl: raise Exception("pixel spacing is larger than smallest spatial wavelength!") logprior_List = [Prior_List[i].imvec for i in range(N_frame)] nprior_List = [Prior_List[i].imvec for i in range(N_frame)] A_List = [Prior_List[i].imvec for i in range(N_frame)] bi_List = [None,] * N_frame sigma_List = [None,] * N_frame for i in range(N_frame): # Normalize prior image to total flux nprior_List[i] = Flux_List[i] * Prior_List[i].imvec / np.sum(Prior_List[i].imvec) logprior_List[i] = np.log(nprior_List[i]) # Data biarr = Obsdata_List[i].bispectra(mode="all", count="min") bi_List[i] = biarr['bispec'] sigma_List[i] = biarr['sigmab'] # Compute the Fourier matrix uv1 = np.hstack((biarr['u1'].reshape(-1,1), biarr['v1'].reshape(-1,1))) uv2 = np.hstack((biarr['u2'].reshape(-1,1), biarr['v2'].reshape(-1,1))) uv3 = np.hstack((biarr['u3'].reshape(-1,1), biarr['v3'].reshape(-1,1))) A3 = ( vb.ftmatrix(Prior_List[i].psize, Prior_List[i].xdim, Prior_List[i].ydim, uv1), vb.ftmatrix(Prior_List[i].psize, Prior_List[i].xdim, Prior_List[i].ydim, uv2), vb.ftmatrix(Prior_List[i].psize, Prior_List[i].xdim, Prior_List[i].ydim, uv3) ) A_List[i] = A3 # Define the objective function and gradient def objfunc(logim): Frames = np.exp(logim.reshape((-1, N_pixel, N_pixel))) if entropy == "simple": s = np.sum(-mx.ssimple(Frames[i].ravel(), nprior_List[i]) for i in range(N_frame)) elif entropy == "l1": s = np.sum(-mx.sl1(Frames[i].ravel(), nprior_List[i]) for i in range(N_frame)) elif entropy == "gs": s = np.sum(-mx.sgs(Frames[i].ravel(), nprior_List[i]) for i in range(N_frame)) elif entropy == "tv": s = np.sum(-mx.stv(Frames[i].ravel(), Prior_List[0].xdim, Prior_List[0].ydim) for i in range(N_frame)) chisq_total = np.sum(mx.chisq_bi(Frames[i].ravel(), A_List[i], bi_List[i], sigma_List[i]) for i in range(N_frame))/N_frame s_dynamic = dynamic_regularizer(Frames, gauss) t = np.sum( [ gamma * (np.sum(Frames[i].ravel()) - Flux_List[i])**2 for i in range(N_frame)] )/N_frame return s + beta * s_dynamic + alpha * (chisq_total - 1.) + t def objgrad(logim): Frames = np.exp(logim.reshape((-1, N_pixel, N_pixel))) if entropy == "simple": s = np.concatenate([-mx.ssimplegrad(Frames[i].ravel(), nprior_List[i])*Frames[i].ravel() for i in range(N_frame)]) elif entropy == "l1": s = np.concatenate([-mx.sl1grad(Frames[i].ravel(), nprior_List[i])*Frames[i].ravel() for i in range(N_frame)]) elif entropy == "gs": s = np.concatenate([-mx.sgsgrad(Frames[i].ravel(), nprior_List[i])*Frames[i].ravel() for i in range(N_frame)]) elif entropy == "tv": s = np.concatenate([-mx.stvgrad(Frames[i].ravel(), Prior_List[0].xdim, Prior_List[0].ydim)*Frames[i].ravel() for i in range(N_frame)]) chisq_total_grad = np.concatenate([mx.chisqgrad_bi(Frames[i].ravel(), A_List[i], bi_List[i], sigma_List[i])*Frames[i].ravel()/N_frame for i in range(N_frame)]) s_dynamic_grad = dynamic_regularizer_gradient(Frames, gauss) t = np.concatenate( [ 2.0 * gamma * (np.sum(Frames[i].ravel()) - Flux_List[i]) * Frames[i].ravel()/N_frame for i in range(N_frame)] ) return (s + beta * s_dynamic_grad + alpha * chisq_total_grad + t) def objgrad_numeric(x): #This calculates the gradient numerically #dx = 10.0**-8 J0 = objfunc(x) Jgrad = np.copy(x) for i in range(len(x)): xp = np.copy(x) dx = xp[i]*10.0**-8#+10.0**-8 xp[i] = xp[i] + dx J1 = objfunc(xp) Jgrad[i] = (J1-J0)/dx return Jgrad # Plotting function for each iteration global nit nit = 0 def plotcur(logim_step): global nit nit += 1 if nit%10 == 0: print "iteration %d" % nit Frames = np.exp(logim_step.reshape((-1, N_pixel, N_pixel))) chi2 = np.sum(mx.chisq_bi(Frames[i].ravel(), A_List[i], bi_List[i], sigma_List[i]) for i in range(N_frame))/N_frame s = np.sum(-mx.ssimple(Frames[i].ravel(), nprior_List[i]) for i in range(N_frame)) s_dynamic = dynamic_regularizer(Frames, gauss) print "chi2: %f" % chi2 print "s: %f" % s print "s_dynamic: %f" % s_dynamic #plot_i(Frames[0], Prior_List[0], nit, chi2, ipynb=ipynb) if nit%refresh_interval == 0: plot_i_dynamic(Frames[::5], Prior_List[0], nit, chi2, s, s_dynamic, ipynb=ipynb) if 1==0: numeric_gradient = objgrad_numeric(logim_step) analytic_gradient = objgrad(logim_step) print "Numeric Gradient:" print numeric_gradient print "Analytic Gradient:" print analytic_gradient print "Max Fractional Difference in gradients:" print max(abs((numeric_gradient - analytic_gradient)/numeric_gradient)) # Plot the prior #print(logprior_List.flatten().shape) logprior = np.hstack(logprior_List).flatten() plotcur(logprior) # Minimize optdict = {'maxiter':maxit, 'ftol':stop, 'maxcor':NHIST} # minimizer params tstart = time.time() res = opt.minimize(objfunc, logprior, method='L-BFGS-B', jac=objgrad, options=optdict, callback=plotcur) tstop = time.time() #out = np.exp(res.x) Frames = np.exp(res.x.reshape((-1, N_pixel, N_pixel))) # Print stats print "time: %f s" % (tstop - tstart) print "J: %f" % res.fun #print "Chi^2: %f" % mx.chisq(out, A, vis, sigma) print res.message #Return Frames outim = [vb.Image(Frames[i].reshape(Prior_List[0].ydim, Prior_List[0].xdim), Prior_List[0].psize, Prior_List[0].ra, Prior_List[0].dec, rf=Prior_List[0].rf, source=Prior_List[0].source, mjd=Prior_List[0].mjd) for i in range(N_frame)] return outim