Пример #1
0
    def objfunc_scattering(self, minvec):
        N = self.prior_next.xdim

        imvec       = minvec[:N**2]
        EpsilonList = minvec[N**2:]
        if self.transform_next == 'log':
            imvec = np.exp(imvec)

        IM = ehtim.image.Image(imvec.reshape(N,N), self.prior_next.psize, self.prior_next.ra, self.prior_next.dec, rf=self.obs_next.rf, source=self.prior_next.source, mjd=self.prior_next.mjd)
        scatt_im = self.scattering_model.Scatter(IM, Epsilon_Screen=so.MakeEpsilonScreenFromList(EpsilonList, N), ea_ker = self._ea_ker, sqrtQ=self._sqrtQ, Linearized_Approximation=True).imvec #the scattered image vector

        # Calculate the chi^2 using the scattered image
        datterm = 0.
        chi2_term_dict = self.make_chisq_dict(scatt_im)
        for dname in sorted(self.dat_term_next.keys()):
            datterm += self.dat_term_next[dname] * (chi2_term_dict[dname] - 1.)

        # Calculate the entropy using the unscattered image
        regterm = 0
        reg_term_dict = self.make_reg_dict(imvec)
        for regname in sorted(self.reg_term_next.keys()):
            regterm += self.reg_term_next[regname] * reg_term_dict[regname]

        # Scattering screen regularization term
        chisq_epsilon = sum(EpsilonList*EpsilonList)/((N*N-1.0)/2.0)
        regterm_scattering = self.alpha_phi_next * (chisq_epsilon - 1.0)

        return datterm + regterm + regterm_scattering
Пример #2
0
    def plotcur_scattering(self, minvec):
        if self._show_updates:
            N = self.prior_next.xdim

            imvec = minvec[:N**2]
            EpsilonList = minvec[N**2:]
            if self.transform_next == 'log':
                imvec = np.exp(imvec)

            IM = ehtim.image.Image(imvec.reshape(N, N),
                                   self.prior_next.psize,
                                   self.prior_next.ra,
                                   self.prior_next.dec,
                                   rf=self.obs_next.rf,
                                   source=self.prior_next.source,
                                   mjd=self.prior_next.mjd)
            #the scattered image vector
            scatt_im = self.scattering_model.Scatter(
                IM,
                Epsilon_Screen=so.MakeEpsilonScreenFromList(EpsilonList, N),
                ea_ker=self._ea_ker,
                sqrtQ=self._sqrtQ,
                Linearized_Approximation=True).imvec

            # Calculate the chi^2 using the scattered image
            datterm = 0.
            chi2_term_dict = self.make_chisq_dict(scatt_im)
            for dname in sorted(self.dat_term_next.keys()):
                datterm += self.dat_term_next[dname] * (chi2_term_dict[dname] -
                                                        1.)

            # Calculate the entropy using the unscattered image
            regterm = 0
            reg_term_dict = self.make_reg_dict(imvec)
            for regname in sorted(self.reg_term_next.keys()):
                regterm += self.reg_term_next[regname] * reg_term_dict[regname]

            # Scattering screen regularization term
            chisq_epsilon = sum(EpsilonList * EpsilonList) / (
                (N * N - 1.0) / 2.0)
            regterm_scattering = self.alpha_phi_next * (chisq_epsilon - 1.0)

            outstr = "i: %d " % self._nit

            for dname in sorted(self.dat_term_next.keys()):
                outstr += "%s : %0.2f " % (dname, chi2_term_dict[dname])
            for regname in sorted(self.reg_term_next.keys()):
                outstr += "%s : %0.2f " % (regname, reg_term_dict[regname])
            outstr += "Epsilon chi^2 : %0.2f " % (chisq_epsilon)
            outstr += "Max |Epsilon| : %0.2f " % (max(abs(EpsilonList)))
            print(outstr)

        self._nit += 1
Пример #3
0
imgr_deblur.make_image_I()
imgr_deblur.out_last().display()

# Now image using stochastic optics
imgr_so = eh.imager.Imager(obs,
                           gaussprior,
                           prior_im=gaussprior,
                           maxit=200,
                           flux=total_flux,
                           clipfloor=-1.)
imgr_so.make_image_I_stochastic_optics()
# Now look at the unscattered image, the scattered image, and replicate the scattering using the solved screen
imgr_so.out_last().display()
imgr_so.out_scattered_last().display()
imgr_so.scattering_model.Scatter(imgr_so.out_last(),
                                 Epsilon_Screen=so.MakeEpsilonScreenFromList(
                                     imgr_so.out_epsilon_last(), npix),
                                 ea_ker=imgr_so._ea_ker,
                                 sqrtQ=imgr_so._sqrtQ,
                                 Linearized_Approximation=True,
                                 DisplayImage=True)

#Note that only the scattered image will fit the measured visibilities!
eh.comp_plots.plotall_obs_im_compare(obs, imgr_so.out_last(), 'uvdist', 'amp')
eh.comp_plots.plotall_obs_im_compare(obs, imgr_so.out_scattered_last(),
                                     'uvdist', 'amp')

# Decrease the scattering regularization slightly and re-image (desired max |Epsilon| is ~2.5)
imgr_so.alpha_phi_next /= 2.0
imgr_so.init_next = imgr_so.out_last().blur_circ(obs.res())
imgr_so.epsilon_list_next = imgr_so.out_epsilon_last()
imgr_so.make_image_I_stochastic_optics()
Пример #4
0
    def make_image_I_stochastic_optics(self, grads=True, show_updates=True):
        """Reconstructs an image of total flux density using the stochastic optics scattering mitigation technique.
           Uses the scattering model of the imager. If none has been specified, it will default to a standard model for Sgr A*.
           Returns the estimated unscattered image.

           Args:
                grads (bool): Flag for whether or not to use analytic gradients.
                show_updates (bool): Flag for whether or not to show updates for each step of convergence.
           Returns:
               out (Image): The estimated *unscattered* image.
        """

        N = self.prior_next.xdim

        # Checks and initialize
        self.check_params()
        self.check_limits()
        self.init_imager_I()
        self.init_imager_scattering()

        # Generate the initial image+screen vector. By default, the screen is re-initialized to zero each time.
        if self.transform_next == 'log':
            xinit = np.log(self._ninit_I)
        else:
            xinit = self._ninit_I

        if len(self.epsilon_list_next) == 0:
            xinit = np.concatenate((xinit, np.zeros(N**2 - 1)))
        else:
            xinit = np.concatenate((xinit, self.epsilon_list_next))

        self._nit = 0

        # Print stats
        if show_updates:
            self._show_updates = True
        else:
            self._show_updates = False

        self.plotcur_scattering(xinit)

        # Minimize
        optdict = {'maxiter': self.maxit_next, 'ftol': STOP, 'maxcor': NHIST}
        tstart = time.time()
        if grads:
            res = opt.minimize(self.objfunc_scattering,
                               xinit,
                               method='L-BFGS-B',
                               jac=self.objgrad_scattering,
                               options=optdict,
                               callback=self.plotcur_scattering)
        else:
            res = opt.minimize(self.objfunc_scattering,
                               xinit,
                               method='L-BFGS-B',
                               options=optdict,
                               callback=self.plotcur_scattering)
        tstop = time.time()

        # Format output
        out = res.x[:N**2]
        if self.transform_next == 'log': out = np.exp(out)
        if np.any(np.invert(self._embed_mask)):
            raise Exception("Embedding is not currently implemented!")
            out = embed(out, self._embed_mask)

        outim = image.Image(out.reshape(N, N),
                            self.prior_next.psize,
                            self.prior_next.ra,
                            self.prior_next.dec,
                            rf=self.prior_next.rf,
                            source=self.prior_next.source,
                            mjd=self.prior_next.mjd,
                            pulse=self.prior_next.pulse)
        outep = res.x[N**2:]
        outscatt = self.scattering_model.Scatter(
            outim,
            Epsilon_Screen=so.MakeEpsilonScreenFromList(outep, N),
            ea_ker=self._ea_ker,
            sqrtQ=self._sqrtQ,
            Linearized_Approximation=True)

        # Preserving image complex polarization fractions
        if len(self.prior_next.qvec):
            qvec = self.prior_next.qvec * out / self.prior_next.imvec
            uvec = self.prior_next.uvec * out / self.prior_next.imvec
            outim.add_qu(qvec.reshape(N, N), uvec.reshape(N, N))

        # Print stats
        print("time: %f s" % (tstop - tstart))
        print("J: %f" % res.fun)
        print(res.message)

        # Append to history
        logstr = str(self.nruns) + ": make_image_I_stochastic_optics()"
        self._append_image_history(outim, logstr)
        self._out_list_epsilon.append(res.x[N**2:])
        self._out_list_scattered.append(outscatt)

        self.nruns += 1

        # Return Image object
        return outim
Пример #5
0
    def objgrad_scattering(self, minvec):
        """Current stochastic optics objective function gradient
        """
        wavelength = C / self.obs_next.rf * 100.0  #Observing wavelength [cm]
        wavelengthbar = wavelength / (2.0 * np.pi)  #lambda/(2pi) [cm]
        N = self.prior_next.xdim
        #Field of view, in cm, at the scattering screen
        FOV = self.prior_next.psize * N * self.scattering_model.observer_screen_distance
        rF = self.scattering_model.rF(wavelength)

        imvec = minvec[:N**2]
        EpsilonList = minvec[N**2:]
        if self.transform_next == 'log':
            imvec = np.exp(imvec)

        IM = ehtim.image.Image(imvec.reshape(N, N),
                               self.prior_next.psize,
                               self.prior_next.ra,
                               self.prior_next.dec,
                               rf=self.obs_next.rf,
                               source=self.prior_next.source,
                               mjd=self.prior_next.mjd)
        #the scattered image vector
        scatt_im = self.scattering_model.Scatter(
            IM,
            Epsilon_Screen=so.MakeEpsilonScreenFromList(EpsilonList, N),
            ea_ker=self._ea_ker,
            sqrtQ=self._sqrtQ,
            Linearized_Approximation=True).imvec

        EA_Image = self.scattering_model.Ensemble_Average_Blur(
            IM, ker=self._ea_ker)
        EA_Gradient = so.Wrapped_Gradient(
            (EA_Image.imvec / (FOV / N)).reshape(N, N))
        #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]

        Epsilon_Screen = so.MakeEpsilonScreenFromList(EpsilonList, N)
        phi = self.scattering_model.MakePhaseScreen(
            Epsilon_Screen,
            IM,
            obs_frequency_Hz=self.obs_next.rf,
            sqrtQ_init=self._sqrtQ).imvec.reshape((N, N))
        phi_Gradient = so.Wrapped_Gradient(phi / (FOV / N))
        phi_Gradient_x = -phi_Gradient[1]
        phi_Gradient_y = -phi_Gradient[0]

        #Entropy gradient; wrt unscattered image so unchanged by scattering
        regterm = 0
        reg_term_dict = self.make_reggrad_dict(imvec)
        for regname in sorted(self.reg_term_next.keys()):
            regterm += self.reg_term_next[regname] * reg_term_dict[regname]

        # Chi^2 gradient wrt the unscattered image
        # First, the chi^2 gradient wrt to the scattered image
        datterm = 0.
        chi2_term_dict = self.make_chisqgrad_dict(scatt_im)
        for dname in sorted(self.dat_term_next.keys()):
            datterm += self.dat_term_next[dname] * (chi2_term_dict[dname] - 1.)
        dchisq_dIa = datterm.reshape((N, N))
        # Now the chain rule factor to get the chi^2 gradient wrt the unscattered image
        gx = (rF**2.0 * so.Wrapped_Convolve(
            self._ea_ker_gradient_x[::-1, ::-1], phi_Gradient_x *
            (dchisq_dIa))).flatten()
        gy = (rF**2.0 * so.Wrapped_Convolve(
            self._ea_ker_gradient_y[::-1, ::-1], phi_Gradient_y *
            (dchisq_dIa))).flatten()
        chisq_grad_im = so.Wrapped_Convolve(self._ea_ker[::-1, ::-1],
                                            (dchisq_dIa)).flatten() + gx + gy

        # Gradient of the data chi^2 wrt to the epsilon screen
        #Preliminary Definitions
        chisq_grad_epsilon = np.zeros(N**2 - 1)
        i_grad = 0
        ell_mat = np.zeros((N, N))
        m_mat = np.zeros((N, N))
        for ell in range(0, N):
            for m in range(0, N):
                ell_mat[ell, m] = ell
                m_mat[ell, m] = m

        #Real part; top row
        for t in range(1, (N + 1) / 2):
            s = 0
            grad_term = so.Wrapped_Gradient(
                wavelengthbar / FOV * self._sqrtQ[s][t] * 2.0 *
                np.cos(2.0 * np.pi / N *
                       (ell_mat * s + m_mat * t)) / (FOV / N))
            grad_term_x = -grad_term[1]
            grad_term_y = -grad_term[0]
            chisq_grad_epsilon[i_grad] = np.sum(
                dchisq_dIa * rF**2 *
                (EA_Gradient_x * grad_term_x + EA_Gradient_y * grad_term_y))
            i_grad = i_grad + 1

        #Real part; remainder
        for s in range(1, (N + 1) / 2):
            for t in range(N):
                grad_term = so.Wrapped_Gradient(
                    wavelengthbar / FOV * self._sqrtQ[s][t] * 2.0 *
                    np.cos(2.0 * np.pi / N *
                           (ell_mat * s + m_mat * t)) / (FOV / N))
                grad_term_x = -grad_term[1]
                grad_term_y = -grad_term[0]
                chisq_grad_epsilon[i_grad] = np.sum(
                    dchisq_dIa * rF**2 * (EA_Gradient_x * grad_term_x +
                                          EA_Gradient_y * grad_term_y))
                i_grad = i_grad + 1

        #Imaginary part; top row
        for t in range(1, (N + 1) / 2):
            s = 0
            grad_term = so.Wrapped_Gradient(
                -wavelengthbar / FOV * self._sqrtQ[s][t] * 2.0 *
                np.sin(2.0 * np.pi / N *
                       (ell_mat * s + m_mat * t)) / (FOV / N))
            grad_term_x = -grad_term[1]
            grad_term_y = -grad_term[0]
            chisq_grad_epsilon[i_grad] = np.sum(
                dchisq_dIa * rF**2 *
                (EA_Gradient_x * grad_term_x + EA_Gradient_y * grad_term_y))
            i_grad = i_grad + 1

        #Imaginary part; remainder
        for s in range(1, (N + 1) / 2):
            for t in range(N):
                grad_term = so.Wrapped_Gradient(
                    -wavelengthbar / FOV * self._sqrtQ[s][t] * 2.0 *
                    np.sin(2.0 * np.pi / N *
                           (ell_mat * s + m_mat * t)) / (FOV / N))
                grad_term_x = -grad_term[1]
                grad_term_y = -grad_term[0]
                chisq_grad_epsilon[i_grad] = np.sum(
                    dchisq_dIa * rF**2 * (EA_Gradient_x * grad_term_x +
                                          EA_Gradient_y * grad_term_y))
                i_grad = i_grad + 1

        # Gradient of the chi^2 regularization term for the epsilon screen
        chisq_epsilon_grad = self.alpha_phi_next * 2.0 * EpsilonList / (
            (N * N - 1) / 2.0)

        # chain rule term for change of variables
        if self.transform_next == 'log':
            regterm *= imvec
            chisq_grad_im *= imvec

        return np.concatenate(((regterm + chisq_grad_im),
                               (chisq_grad_epsilon + chisq_epsilon_grad)))