Beispiel #1
0
def patchPrior(im, beta, patchPriorFile='naturalPrior.mat', patchSize=8):

    # load data
    ldata = scipy.io.loadmat(patchPriorFile)

    # reassign and reshape data
    nmodels = ldata['nmodels'].ravel()
    nmodels = nmodels[0]
    mixweights = ldata['mixweights'].ravel()
    covs = np.array(ldata['covs'])
    means = np.array(ldata['means'])

    # reshape image
    img = np.reshape(im.imvec, (im.ydim, im.xdim))

    I1, counts = cleanImage(img, beta, nmodels, covs, mixweights, means,
                            patchSize)

    if not all(counts[0][0] == item for item in np.reshape(counts, (-1))):
        raise TypeError(
            "The counts are not the same for every pixel in the image")

    I1 = I1 / counts[0][0]
    out = image.Image(I1,
                      im.psize,
                      im.ra,
                      im.dec,
                      rf=im.rf,
                      source=im.source,
                      mjd=im.mjd,
                      pulse=im.pulse)

    return (out, counts[0][0])
Beispiel #2
0
    def Ensemble_Average_Blur(self, im, wavelength_cm = None, ker = None):
        """Blurs an input Image with the ensemble-average scattering kernel.

           Args:
                im (Image): The unscattered image.
                wavelength_cm (float): The observing wavelength for the scattering kernel in cm. If unspecified, this will default to the wavelength of the input image.
                ker (2D ndarray): The user can optionally pass a pre-computed ensemble-average blurring kernel.

           Returns:
               out (Image): The ensemble-average scattered image.
            """

        # Inputs an unscattered image and an ensemble-average blurring kernel (2D array); returns the ensemble-average image
        # The pre-computed kernel can optionally be specified (ker)

        if wavelength_cm == None:
            wavelength_cm = C/im.rf*100.0 #Observing wavelength [cm]

        if ker is None:
            ker = self.Ensemble_Average_Kernel(im, wavelength_cm)

        Iim = Wrapped_Convolve((im.imvec).reshape(im.ydim, im.xdim), ker)
        out = image.Image(Iim, im.psize, im.ra, im.dec, rf=C/(wavelength_cm/100.0), source=im.source, mjd=im.mjd, pulse=im.pulse)
        if len(im.qvec):
            Qim = Wrapped_Convolve((im.qvec).reshape(im.ydim, im.xdim), ker)
            Uim = Wrapped_Convolve((im.uvec).reshape(im.ydim, im.xdim), ker)
            out.add_qu(Qim, Uim)
        if len(im.vvec):
            Vim = Wrapped_Convolve((im.vvec).reshape(im.ydim, im.xdim), ker)
            out.add_v(Vim)

        return out
Beispiel #3
0
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 = (ftmatrix(currImage.psize,
                   currImage.xdim,
                   currImage.ydim,
                   uv1,
                   pulse=currImage.pulse),
          ftmatrix(currImage.psize,
                   currImage.xdim,
                   currImage.ydim,
                   uv2,
                   pulse=currImage.pulse),
          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 image.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)
Beispiel #4
0
    def MakePhaseScreen(self, EpsilonScreen, Reference_Image, obs_frequency_Hz=0.0, Vx_km_per_s=50.0, Vy_km_per_s=0.0, t_hr=0.0, sqrtQ_init=None):
        """Create a refractive phase screen from standardized Fourier components (the EpsilonScreen).
           All lengths should be specified in centimeters
           If the observing frequency (obs_frequency_Hz) is not specified, then it will be taken to be equal to the frequency of the Reference_Image
           Note: an odd image dimension is required!

           Args:
                EpsilonScreen (2D ndarray): Optionally, the scattering screen can be specified. If none is given, a random one will be generated.
                Reference_Image (Image): The reference image.
                obs_frequency_Hz (float): The observing frequency, in Hz. By default, it will be taken to be equal to the frequency of the Unscattered_Image.
                Vx_km_per_s (float): Velocity of the scattering screen in the x direction (toward East) in km/s.
                Vy_km_per_s (float): Velocity of the scattering screen in the y direction (toward North) in km/s.
                t_hr (float): The current time of the scattering in hours.
                ea_ker (2D ndarray): The used can optionally pass a precomputed array of the ensemble-average blurring kernel.
                sqrtQ_init (2D ndarray): The used can optionally pass a precomputed array of the square root of the power spectrum.

           Returns:
               phi_Image (Image): The phase screen.
            """

        #Observing wavelength
        if obs_frequency_Hz == 0.0:
            obs_frequency_Hz = Reference_Image.rf

        wavelength = C/obs_frequency_Hz*100.0 #Observing wavelength [cm]
        wavelengthbar = wavelength/(2.0*np.pi) #lambda/(2pi) [cm]

        #Derived parameters
        FOV = Reference_Image.psize * Reference_Image.xdim * self.observer_screen_distance #Field of view, in cm, at the scattering screen
        rF  = self.rF(wavelength)
        Nx = EpsilonScreen.shape[1]
        Ny = EpsilonScreen.shape[0]

        if Nx%2 == 0:
            print("The image dimension should really be odd...")

        #Now we'll calculate the power spectrum for each pixel in Fourier space
        screen_x_offset_pixels = (Vx_km_per_s*1.e5) * (t_hr*3600.0) / (FOV/float(Nx))
        screen_y_offset_pixels = (Vy_km_per_s*1.e5) * (t_hr*3600.0) / (FOV/float(Nx))

        if sqrtQ_init is None:
            sqrtQ = self.sqrtQ_Matrix(Reference_Image, Vx_km_per_s=Vx_km_per_s, Vy_km_per_s=Vy_km_per_s, t_hr=t_hr)
        else:
            #If a matrix for sqrtQ_init is passed, we still need to potentially rotate it

            if screen_x_offset_pixels != 0.0 or screen_y_offset_pixels != 0.0:
                s, t = np.meshgrid(np.fft.fftfreq(Nx, d=1.0/Nx), np.fft.fftfreq(Ny, d=1.0/Ny))
                sqrtQ = sqrtQ_init * np.exp(2.0*np.pi*1j*(s*screen_x_offset_pixels +
                                                          t*screen_y_offset_pixels)/float(Nx))
            else:
                sqrtQ = sqrtQ_init

        #Now calculate the phase screen
        phi = np.real(wavelengthbar/FOV*EpsilonScreen.shape[0]*EpsilonScreen.shape[1]*np.fft.ifft2(sqrtQ*EpsilonScreen))
        phi_Image = image.Image(phi, Reference_Image.psize, Reference_Image.ra, Reference_Image.dec, rf=Reference_Image.rf, source=Reference_Image.source, mjd=Reference_Image.mjd)

        return phi_Image
Beispiel #5
0
        def get_frame(j):
            if type(Unscattered_Movie) == movie.Movie:
                im = image.Image(Unscattered_Movie.frames[j].reshape((N,N)), psize, ra, dec, rf, pulse, source, mjd)
                if len(Unscattered_Movie.qframes) > 0:
                    im.add_qu(Unscattered_Movie.qframes[j].reshape((N,N)), Unscattered_Movie.uframes[j].reshape((N,N)))

                return im
            elif type(Unscattered_Movie) == list:
                return Unscattered_Movie[j]
            else:
                return Unscattered_Movie
Beispiel #6
0
    def get_frame(self, frame_num):
        """Return one movie frame as an image object"""
        import ehtim.image as image

        if frame_num < 0 or frame_num > len(self.frames):
            raise Exception("Invalid frame number!")

        im = image.Image(
            self.frames[frame_num].reshape((self.ydim, self.xdim)), self.psize,
            self.ra, self.dec, self.rf, self.pulse, self.source, self.mjd)
        if len(self.qframes) > 0:
            im.add_qu(self.qframes[frame_num].reshape((self.ydim, self.xdim)),
                      self.uframes[frame_num].reshape((self.ydim, self.xdim)))
        if len(self.vframes) > 0:
            im.add_v(self.vframes[frame_num].reshape((self.ydim, self.xdim)))

        return im
Beispiel #7
0
    def Scatter(self,
                Unscattered_Image,
                Epsilon_Screen=np.array([]),
                obs_frequency_Hz=0.0,
                Vx_km_per_s=50.0,
                Vy_km_per_s=0.0,
                t_hr=0.0,
                ea_ker=None,
                sqrtQ=None,
                Linearized_Approximation=False,
                DisplayImage=False,
                Force_Positivity=False,
                use_approximate_form=True):
        """Scatter an image using the specified epsilon screen.
           All lengths should be specified in centimeters
           If the observing frequency (obs_frequency_Hz) is not specified, then it will be taken to be equal to the frequency of the Unscattered_Image
           Note: an odd image dimension is required!

           Args:
                Unscattered_Image (Image): The unscattered image.
                Epsilon_Screen (2D ndarray): Optionally, the scattering screen can be specified. If none is given, a random one will be generated.
                obs_frequency_Hz (float): The observing frequency, in Hz. By default, it will be taken to be equal to the frequency of the Unscattered_Image.
                Vx_km_per_s (float): Velocity of the scattering screen in the x direction (toward East) in km/s.
                Vy_km_per_s (float): Velocity of the scattering screen in the y direction (toward North) in km/s.
                t_hr (float): The current time of the scattering in hours.
                ea_ker (2D ndarray): The used can optionally pass a precomputed array of the ensemble-average blurring kernel.
                sqrtQ (2D ndarray): The used can optionally pass a precomputed array of the square root of the power spectrum.
                Linearized_Approximation (bool): If True, uses a linearized approximation for the scattering (Eq. 10 of Johnson & Narayan 2016). If False, uses Eq. 9 of that paper.
                DisplayImage (bool): If True, show a plot of the unscattered, ensemble-average, and scattered images as well as the phase screen.
                Force_Positivity (bool): If True, eliminates negative flux from the scattered image from the linearized approximation.
                Return_Image_List (bool): If True, returns a list of the scattered frames. If False, returns a movie object.

           Returns:
               AI_Image (Image): The scattered image.
            """

        # Observing wavelength
        if obs_frequency_Hz == 0.0:
            obs_frequency_Hz = Unscattered_Image.rf

        wavelength = C / obs_frequency_Hz * 100.0  # Observing wavelength [cm]
        wavelengthbar = wavelength / (2.0 * np.pi)  # lambda/(2pi) [cm]

        # Derived parameters
        FOV = Unscattered_Image.psize * Unscattered_Image.xdim * \
            self.observer_screen_distance  # Field of view, in cm, at the scattering screen
        rF = self.rF(wavelength)
        Nx = Unscattered_Image.xdim
        Ny = Unscattered_Image.ydim

        # First we need to calculate the ensemble-average image by blurring the
        # unscattered image with the correct kernel
        EA_Image = self.Ensemble_Average_Blur(
            Unscattered_Image,
            wavelength,
            ker=ea_ker,
            use_approximate_form=use_approximate_form)

        # If no epsilon screen is specified, then generate a random realization
        if Epsilon_Screen.shape[0] == 0:
            Epsilon_Screen = MakeEpsilonScreen(Nx, Ny)

        # We'll now calculate the phase screen.
        phi_Image = self.MakePhaseScreen(Epsilon_Screen,
                                         Unscattered_Image,
                                         obs_frequency_Hz,
                                         Vx_km_per_s=Vx_km_per_s,
                                         Vy_km_per_s=Vy_km_per_s,
                                         t_hr=t_hr,
                                         sqrtQ_init=sqrtQ)
        phi = phi_Image.imvec.reshape(Ny, Nx)

        # 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]

        # Use Equation 10 of Johnson & Narayan (2016)
        if Linearized_Approximation:
            # Calculate 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 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)
            if len(Unscattered_Image.qvec):
                # Scatter the Q image
                EA_Gradient = Wrapped_Gradient(
                    (EA_Image.qvec / (FOV / Nx)).reshape(
                        EA_Image.ydim, EA_Image.xdim))
                EA_Gradient_x = -EA_Gradient[1]
                EA_Gradient_y = -EA_Gradient[0]
                AI_Q = (EA_Image.qvec).reshape(Ny, Nx) + rF**2.0 * \
                    (EA_Gradient_x * phi_Gradient_x + EA_Gradient_y * phi_Gradient_y)
                # Scatter the U image
                EA_Gradient = Wrapped_Gradient(
                    (EA_Image.uvec / (FOV / Nx)).reshape(
                        EA_Image.ydim, EA_Image.xdim))
                EA_Gradient_x = -EA_Gradient[1]
                EA_Gradient_y = -EA_Gradient[0]
                AI_U = (EA_Image.uvec).reshape(Ny, Nx) + rF**2.0 * \
                    (EA_Gradient_x * phi_Gradient_x + EA_Gradient_y * phi_Gradient_y)
            if len(Unscattered_Image.vvec):
                # Scatter the V image
                EA_Gradient = Wrapped_Gradient(
                    (EA_Image.vvec / (FOV / Nx)).reshape(
                        EA_Image.ydim, EA_Image.xdim))
                EA_Gradient_x = -EA_Gradient[1]
                EA_Gradient_y = -EA_Gradient[0]
                AI_V = (EA_Image.vvec).reshape(Ny, Nx) + rF**2.0 * \
                    (EA_Gradient_x * phi_Gradient_x + EA_Gradient_y * phi_Gradient_y)
        else:  # Use Equation 9 of Johnson & Narayan (2016)
            EA_im = (EA_Image.imvec).reshape(Ny, Nx)
            AI = np.copy((EA_Image.imvec).reshape(Ny, Nx))
            if len(Unscattered_Image.qvec):
                AI_Q = np.copy((EA_Image.imvec).reshape(Ny, Nx))
                AI_U = np.copy((EA_Image.imvec).reshape(Ny, Nx))
                EA_im_Q = (EA_Image.qvec).reshape(Ny, Nx)
                EA_im_U = (EA_Image.uvec).reshape(Ny, Nx)
            if len(Unscattered_Image.vvec):
                AI_V = np.copy((EA_Image.imvec).reshape(Ny, Nx))
                EA_im_V = (EA_Image.vvec).reshape(Ny, Nx)
            for rx in range(Nx):
                for ry in range(Ny):
                    # Annoyingly, the signs here must be negative to match the
                    # other approximation. I'm not sure which is correct, but
                    # it really shouldn't matter anyway because -phi has the
                    # same power spectrum as phi. However, getting the
                    # *relative* sign for the x- and y-directions correct is
                    # important.
                    rxp = int(
                        np.round(rx - rF**2.0 * phi_Gradient_x[ry, rx] /
                                 self.observer_screen_distance /
                                 Unscattered_Image.psize)) % Nx
                    ryp = int(
                        np.round(ry - rF**2.0 * phi_Gradient_y[ry, rx] /
                                 self.observer_screen_distance /
                                 Unscattered_Image.psize)) % Ny
                    AI[ry, rx] = EA_im[ryp, rxp]
                    if len(Unscattered_Image.qvec):
                        AI_Q[ry, rx] = EA_im_Q[ryp, rxp]
                        AI_U[ry, rx] = EA_im_U[ryp, rxp]
                    if len(Unscattered_Image.vvec):
                        AI_V[ry, rx] = EA_im_V[ryp, rxp]

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

        # Make it into a proper image format
        AI_Image = image.Image(AI,
                               EA_Image.psize,
                               EA_Image.ra,
                               EA_Image.dec,
                               rf=EA_Image.rf,
                               source=EA_Image.source,
                               mjd=EA_Image.mjd)
        if len(Unscattered_Image.qvec):
            AI_Image.add_qu(AI_Q, AI_U)
        if len(Unscattered_Image.vvec):
            AI_Image.add_v(AI_V)

        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