Example #1
0
# Image total flux with the bispectrum
flux = np.sum(im.imvec)
#out = mx.maxen_amp_cphase(obs, gaussprior, gaussprior, flux, maxit=50, alpha_clphase=1000, alpha_visamp=1000)

out = mx.maxen_bs(obs, gaussprior, gaussprior, flux, maxit=25, alpha=5000)
 
# Blur the image with a circular beam and image again to help convergance
out = mx.blur_circ(out, res)
out = mx.maxen_bs(obs, out, out, flux, maxit=100, alpha=500, entropy="tv")
out = mx.blur_circ(out, res/2)
out = mx.maxen_bs(obs, out, out, flux, maxit=100, alpha=100, entropy="tv")
out = mx.blur_circ(out, res/2)
out = mx.maxen_bs(obs, out, out, flux, maxit=100, alpha=50, entropy="tv")

# Blur the final image with 1/2 the clean beam
outblur = vb.blur_gauss(out, beamparams, 0.5)
out.display()

# Image Polarization
# out = mx.maxen_m(obs, out, beta=100, maxit=250, polentropy="hw")


# Save the images
outname = "test"
out.save_txt(outname + '.txt')
out.save_fits(outname + '.fits')
outblur.save_txt(outname + '_blur.txt')
outblur.save_fits(outname + '_blur.fits')


Example #2
0
def Scatter(Unscattered_Image, Epsilon_Screen=np.array([]), DisplayPhi=False, DisplayImage=False): 
    #This module takes an unscattered image and Fourier components of the phase screen to produce a scattered image
    #Epsilon_Screen represents the normalized complex spectral values for the phase screen

    #Note: an odd image dimension is required

    # First some preliminary definitions
    wavelength = C/Unscattered_Image.rf*100.0 #Observing wavelength [cm]
    wavelengthbar = wavelength/(2.0*np.pi) #lambda/(2pi) [cm]
    D_dist = 8.023*10**21 #Observer-Scattering distance [cm]
    R_dist = 1.790*10**22 #Source-Scattering distance [cm]
    Mag = D_dist/R_dist
    r0_maj = (wavelength/0.13)**-1.0*3.134*10**8 #Phase coherence length [cm]
    r0_min = (wavelength/0.13)**-1.0*6.415*10**8 #Phase coherence length [cm]
    rF = (wavelength/0.13)**0.5*1.071*10**10 #Fresnel scale [cm]
    r_in = 1000*10**5 #inner scale [km]
    r_out = 10**20 #outer scale [km]
    scatt_alpha = 5.0/3.0 #power-law index
    FOV = Unscattered_Image.psize * Unscattered_Image.xdim * D_dist #Field of view, in cm, at the scattering screen

    def Q(qx, qy): #Power spectrum of phase fluctuations
        #x is aligned with the major axis; y is aligned with the minor axis
        qmin = 2.0*np.pi/r_out
        qmax = 2.0*np.pi/r_in
        #rotate qx and qy as needed
        PA = (90 - vb.POS_ANG) * np.pi/180.0
        qx_rot =  qx*np.cos(PA) + qy*np.sin(PA)
        qy_rot = -qx*np.sin(PA) + qy*np.cos(PA)
        return 2.0**scatt_alpha * np.pi * scatt_alpha * scipy.special.gamma(1.0 + scatt_alpha/2.0)/scipy.special.gamma(1.0 - scatt_alpha/2.0)*wavelengthbar**-2.0*(r0_maj*r0_min)**-(scatt_alpha/2.0) * ( (r0_maj/r0_min)*qx_rot**2.0 + (r0_min/r0_maj)*qy_rot**2.0 + qmin**2.0)**(-(scatt_alpha+2.0)/2.0) * np.exp(-((qx_rot**2.0 + qy_rot**2.0)/qmax**2.0)**0.5)


    #First we need to calculate the ensemble-average image by blurring the unscattered image with the correct kernel
    EA_Image = vb.blur_gauss(Unscattered_Image, vb.sgra_kernel_params(Unscattered_Image.rf), frac=1.0, frac_pol=0)

    if Epsilon_Screen.shape[0] == 0:
        return EA_Image
    else:
        Nx = Epsilon_Screen.shape[1]
        Ny = Epsilon_Screen.shape[0]

        #Next, we need the gradient of the ensemble-average image
        EA_Gradient = Wrapped_Gradient((EA_Image.imvec/(FOV/Nx)).reshape(EA_Image.ydim, EA_Image.xdim))    
        #The gradient signs don't actually matter, but let's make them match intuition (i.e., right to left, bottom to top)
        EA_Gradient_x = -EA_Gradient[1]
        EA_Gradient_y = -EA_Gradient[0]
    
        #Now we'll calculate the phase screen gradient
        sqrtQ = np.zeros((Ny,Nx)) #just to get the dimensions correct
        dq = 2.0*np.pi/FOV #this is the spacing in wavenumber

        for x in range(0, Nx):
            for y in range(0, Ny):
                x2 = x
                y2 = y
                if x2 > (Nx-1)/2:
                    x2 = x2 - Nx
                if y2 > (Ny-1)/2:
                    y2 = y2 - Ny 
                sqrtQ[y][x] = Q(dq*x2,dq*y2)**0.5    
        sqrtQ[0][0] = 0.0 #A DC offset doesn't affect scattering

        #We'll now calculate the phase screen. We could calculate the gradient directly, but this is more bulletproof for now
        phi = np.real(wavelengthbar/FOV*Epsilon_Screen.shape[0]*Epsilon_Screen.shape[1]*np.fft.ifft2( sqrtQ*Epsilon_Screen))
        phi_Image = vb.Image(phi, EA_Image.psize, EA_Image.ra, EA_Image.dec, rf=EA_Image.rf, source=EA_Image.source, mjd=EA_Image.mjd)
    
        if DisplayPhi:
            phi_Image.display()

        #Next, we need the gradient of the ensemble-average image
        phi_Gradient = Wrapped_Gradient(phi/(FOV/Nx))    

        #The gradient signs don't actually matter, but let's make them match intuition (i.e., right to left, bottom to top)
        phi_Gradient_x = -phi_Gradient[1]
        phi_Gradient_y = -phi_Gradient[0]

        #Now we can patch together the average image
        AI = (EA_Image.imvec).reshape(Ny,Nx) + rF**2.0 * ( EA_Gradient_x*phi_Gradient_x + EA_Gradient_y*phi_Gradient_y )

        #Optional: eliminate negative flux
        #AI = abs(AI)

        #Make it into a proper image format
        AI_Image = vb.Image(AI, EA_Image.psize, EA_Image.ra, EA_Image.dec, rf=EA_Image.rf, source=EA_Image.source, mjd=EA_Image.mjd)

        if DisplayImage:
            plot_scatt(Unscattered_Image.imvec, EA_Image.imvec, AI_Image.imvec, phi_Image.imvec, Unscattered_Image, 0, 0, ipynb=False)

        return AI_Image
beamparams = obs.fit_beam()
res = 1 / np.max(obs.unpack('uvdist')['uvdist'])
print beamparams 
print res

out_cl = mx.maxen_onlyclosure(obs, gaussprior, flux = 1.0, maxit=50, alpha_clphase=10, alpha_clamp=10, gamma=500, delta=1e10, entropy="simple", stop=1e-15, grads=True)
out_cl = mx.maxen_onlyclosure(obs, mx.blur_circ(out_cl, 1e-10), flux = 1.0, maxit=100, alpha_clphase=10, alpha_clamp=10, gamma=500, delta=1e10, entropy="tv", stop=1e-10, grads=True)
out_cl = mx.maxen_onlyclosure(obs, mx.blur_circ(out_cl, 1e-10), flux = 1.0, maxit=100, alpha_clphase=5, alpha_clamp=5, gamma=500, delta=1e10, entropy="tv", stop=1e-10, grads=True)
out_cl = mx.maxen_onlyclosure(obs, mx.blur_circ(out_cl, 1e-10), flux = 1.0, maxit=100, alpha_clphase=5, alpha_clamp=5, gamma=500, delta=1e10, entropy="tv", stop=1e-10, grads=True)
out_cl = mx.maxen_onlyclosure(obs, mx.blur_circ(out_cl, 1e-10), flux = 1.0, maxit=100, alpha_clphase=5, alpha_clamp=5, gamma=500, delta=1e10, entropy="tv", stop=1e-10, grads=True)

mx.blur_circ(out_cl, 0.5e-10).display()

im.save_txt("Truth_MAD-Disk.txt")
vb.blur_gauss(im, beamparams, 0.5, frac_pol=0).save_txt("Truth_MAD-Disk_halfCLEAN.txt")
out_cl.save_txt("ClosureOnly_MAD-Disk_EHT2017wKP_wRedundant.txt")
vb.blur_gauss(out_cl, beamparams, 0.5, frac_pol=0).save_txt("ClosureOnly_MAD-Disk_EHT2017wKP_wRedundant_halfCLEAN.txt")




mx.blur_circ(out_cl, 0.5e-10).display()




out_cl = mx.maxen_onlyclosure(obs, mx.blur_circ(out_cl, 1e-10), flux = 1.0, maxit=100, alpha_clphase=10, alpha_clamp=10, gamma=500, delta=500, entropy="simple", stop=1e-10)