Exemplo n.º 1
0
 def setup_class(self):
     self.fobs = 316 * u.MHz
     f = (np.arange(-16, 16)/2.) << u.MHz
     self.f = self.fobs + f
     self.df = self.f[1]-self.f[0]
     self.t = (np.arange(-16, 16) << u.minute)[:, np.newaxis]
     self.dt = self.t[1, 0]-self.t[0, 0]
     self.d_eff = 1*u.kpc
     self.mu_eff = 30*u.mas/u.yr
     self.theta = [0., -0.3, 0.5] << u.mas
     self.dw = dynamic_field(self.theta, 0., 1.,
                             self.d_eff, self.mu_eff, self.f, self.t)
     self.magnification = np.array([1., 0.2, 0.1j])
     ds = np.abs((self.dw * self.magnification[:, np.newaxis, np.newaxis])
                 .sum(0))**2
     self.ds = DynamicSpectrum(ds, self.f, self.t, 0.001,
                               d_eff=self.d_eff, mu_eff=self.mu_eff,
                               magnification=self.magnification)
     self.ds.theta = self.theta
     self.conjspec = np.fft.fftshift(np.fft.fft2(self.ds.dynspec))
Exemplo n.º 2
0
 def setup_class(cls):
     cls.fobs = 316 * u.MHz
     f = (np.arange(-16, 16) / 2.) << u.MHz
     cls.f = cls.fobs + f
     cls.t = (np.arange(-16, 16) << u.minute)[:, np.newaxis]
     cls.d_eff = 1 * u.kpc
     cls.mu_eff = 30 * u.mas / u.yr
     cls.theta = [0., -0.3, 0.5] << u.mas
     cls.dw = dynamic_field(cls.theta, 0., 1., cls.d_eff, cls.mu_eff, cls.f,
                            cls.t)
     cls.magnification = np.array([1., 0.2, 0.1j])
     ds = np.abs(
         (cls.dw * cls.magnification[:, np.newaxis, np.newaxis]).sum(0))**2
     cls.ds = DynamicSpectrum(ds,
                              cls.f,
                              cls.t,
                              0.001,
                              d_eff=cls.d_eff,
                              mu_eff=cls.mu_eff,
                              magnification=cls.magnification)
     cls.ds.theta = cls.theta
Exemplo n.º 3
0
    def test_jacobian(self):
        """Test derivatives d DS / d mag (real,imag) and d DS / d mu_eff."""
        jac_mag, jac_mu = self.ds.jacobian(self.magnification, self.mu_eff)
        dmag = 1e-6
        for real in True, False:
            for i in range(self.magnification.size):
                magnification = self.magnification.copy()
                magnification[i] += dmag * (1 if real else 1j)
                ds = np.abs((magnification[:, np.newaxis, np.newaxis] *
                             self.dw).sum(0))**2
                ddsdmag = (ds - self.ds.dynspec).reshape(ds.size) / dmag
                jac = jac_mag['mag_real' if real else 'mag_imag'][:, i]
                # Typical numbers are order unity.
                assert np.allclose(ddsdmag, jac, atol=1e-6)

        dmu = self.mu_eff * 1e-6
        mu_eff = self.mu_eff + dmu
        ds = np.abs((self.magnification[:, np.newaxis, np.newaxis] *
                     dynamic_field(self.theta, 0., 1., self.d_eff, mu_eff,
                                   self.f, self.t)).sum(0))**2
        ddsdmu = (ds - self.ds.dynspec).reshape(ds.size) / dmu
        # Typical numbers are of order 0.01 yr/mas.
        assert u.allclose(ddsdmu, jac_mu[:, 0], atol=1e-7 * u.yr / u.mas)
Exemplo n.º 4
0
f = fobs + np.linspace(-0.5 * u.MHz, 0.5 * u.MHz, 200,
                       endpoint=False) / scale**2
t = np.linspace(-10 * u.minute, 10 * u.minute, 100,
                endpoint=False)[:, np.newaxis] / scale

ax1 = plt.subplot(131)
plt.scatter(th,
            th_perp,
            marker='o',
            s=np.maximum(np.abs(realization * 40), 0.5))
plt.xlim(th.min() * 1.05, th.max() * 1.05)
plt.ylim(th.min() * 1.05, th.max() * 1.05)
ax1.set_aspect(1.)

dynwave = dynamic_field(th, th_perp, realization, d_eff, mu_eff, f, t)
axes = tuple(range(0, dynwave.ndim - 2))
dynspec = np.abs(dynwave[...].sum(axes))**2

# Just for fun, add noise.  Add as gaussian noise, since in a real
# observation, the dynamic spectrum would consist of folded data of
# a lot of background-subtracted pulses, so intensities would no longer
# be chi2 distributed.
noise = 0.01
dynspec += noise * np.random.normal(size=dynspec.shape)

plt.subplot(132)
# TODO: really, should just use a WCS!
ds_extent = (t[0, 0].value, t[-1, 0].value, f[0].value, f[-1].value)
plt.imshow(dynspec.T,
           origin='lower',
Exemplo n.º 5
0
def simple_figure(th_par, magnification,
                  d_eff=0.5*u.kpc, mu_eff=50.*u.mas/u.yr, fobs=316.*u.MHz,
                  delta_f=2.*u.MHz, delta_t=90.*u.minute, nf=200, nt=180,
                  **kwargs):

    # Observation frequencies and times
    f = (fobs + np.linspace(-0.5*delta_f, 0.5*delta_f, nf, endpoint=False)
         + 0.5*delta_f/nf)
    t = (np.linspace(0.*u.minute, delta_t, nt, endpoint=False)[:, np.newaxis]
         + 0.5*delta_t/nt)

    # Create electric field and dynamic spectrum
    th_perp = np.zeros_like(th_par)
    dynwave = dynamic_field(th_par, th_perp, magnification,
                            d_eff, mu_eff, f, t)
    axes = tuple(range(0, dynwave.ndim-2))
    dynwave = dynwave[...].sum(axes)
    dynspec = np.abs(dynwave)**2

    # Create conjugate and then secondary spectrum
    ss = SecondarySpectrum.from_dynamic_spectrum(dynspec, f=f, t=t, noise=0.,
                                                 d_eff=d_eff, mu_eff=mu_eff,
                                                 theta=th_par,
                                                 magnification=magnification)
    tau = ss.tau
    fd = ss.fd
    secspec = np.abs(ss.secspec)**2

    # Create dynamic wavefield
    dwft = np.fft.fft2(dynwave)
    dwft /= dwft[0, 0]
    dwft = np.fft.fftshift(dwft)

    # Figure
    fig = plt.figure(figsize=(12., 8.))
    plt.subplots_adjust(wspace=0., hspace=0.4)

    ds_extent = (t[0][0].value - 0.5*(t[1][0].value - t[0][0].value),
                 t[-1][0].value + 0.5*(t[1][0].value - t[0][0].value),
                 f[0].value - 0.5*(f[1].value - f[0].value),
                 f[-1].value + 0.5*(f[1].value - f[0].value))
    ss_extent = (fd[0][0].value - 0.5*(fd[1][0].value - fd[0][0].value),
                 fd[-1][0].value + 0.5*(fd[1][0].value - fd[0][0].value),
                 tau[0].value - 0.5*(tau[1].value - tau[0].value),
                 tau[-1].value + 0.5*(tau[1].value - tau[0].value))

    f_lims = (fobs.value - 0.5*delta_f.value, fobs.value + 0.5*delta_f.value)
    t_lims = (0., delta_t.value)

    tau_lims = (-15., 15.)
    fd_lims = (-5., 5.)

    # Plot dynamic spectrum
    ax1 = plt.subplot(231)
    im1 = ax1.imshow(dynspec.T,
                     origin='lower', aspect='auto', interpolation='none',
                     cmap='Greys', extent=ds_extent,
                     vmin=(0 if np.max(dynspec) > 2 else None))
    plt.title('dynamic spectrum')
    plt.xlabel(rf"time $t$ ({t.unit.to_string('latex')})")
    plt.ylabel(rf"frequency $f$ ({f.unit.to_string('latex')})")
    plt.xlim(t_lims)
    plt.ylim(f_lims)
    cbar = plt.colorbar(im1)
    cbar.set_label('normalized intensity')

    # Plot secondary spectrum
    ax2 = plt.subplot(234)
    im2 = ax2.imshow(secspec.T,
                     origin='lower', aspect='auto', interpolation='none',
                     cmap='Greys', extent=ss_extent,
                     norm=mcolors.LogNorm(vmin=1.e-4, vmax=1.))
    plt.title('secondary spectrum')
    plt.xlabel(r"differential Doppler shift $f_\mathrm{{D}}$"
               rf"({fd.unit.to_string('latex')})")
    plt.ylabel(r"relative geometric delay $\tau$ "
               rf"({tau.unit.to_string('latex')})")
    plt.xlim(fd_lims)
    plt.ylim(tau_lims)
    cbar = plt.colorbar(im2)
    cbar.set_label('normalized power')

    # Plot electric field
    bgcol = 'w'
    ax3 = plt.subplot(233)
    ax3.set_facecolor(bgcol)
    ax3.imshow(np.angle(dynwave).T,
               alpha=np.abs(dynwave).T / np.max(np.abs(dynwave).T),
               origin='lower', aspect='auto', interpolation='none',
               cmap=phasecmap, extent=ds_extent, vmin=-np.pi, vmax=np.pi)
    plt.title('dynamic wavefield')
    plt.xlabel(rf"time $t$ ({t.unit.to_string('latex')})")
    plt.ylabel(rf"frequency $f$ ({f.unit.to_string('latex')})")
    plt.xlim(t_lims)
    plt.ylim(f_lims)

    # create temporary colorbar, for axes positioning
    cbar = plt.colorbar(cm.ScalarMappable(), ax=ax3, aspect=5.5)
    cbar_pos = fig.axes[-1].get_position()
    cbar.remove()

    # create 2D colormap
    cax = fig.add_axes(cbar_pos)
    phases = np.linspace(-np.pi, np.pi, 360, endpoint=False)
    alphas = np.linspace(0., 1., 256)
    phasegrid, alphagrid = np.meshgrid(phases, alphas)
    cax.set_facecolor(bgcol)
    cax.imshow(phasegrid, alpha=alphagrid,
               origin='lower', aspect='auto', interpolation='none',
               cmap=phasecmap,
               extent=[-np.pi, np.pi, 0., np.max(np.abs(dynwave))])
    cax.set_xticks([-np.pi, 0., np.pi])
    cax.set_xticklabels([r'$-\pi$', '0', r'$\pi$'])
    cax.xaxis.tick_top()
    cax.xaxis.set_label_position('top')
    cax.yaxis.tick_right()
    cax.yaxis.set_label_position('right')
    cax.set_xlabel('phase (rad)')
    cax.set_ylabel('normalized intensity')

    # Plot wavefield
    ax4 = plt.subplot(236)
    im4 = ax4.imshow(np.abs(dwft).T,
                     origin='lower', aspect='auto', interpolation='none',
                     cmap='Greys', extent=ss_extent,
                     norm=mcolors.LogNorm(vmin=1.e-2, vmax=1.))
    plt.title('conjugate wavefield')
    plt.xlabel(r"differential Doppler shift $f_\mathrm{{D}}$"
               rf"({fd.unit.to_string('latex')})")
    plt.ylabel(r"relative geometric delay $\tau$ "
               rf"({tau.unit.to_string('latex')})")
    plt.xlim(fd_lims)
    plt.ylim(tau_lims)
    cbar = plt.colorbar(im4)
    cbar.set_label('normalized power')

    # Add sketch
    ax5 = plt.subplot(132)
    make_sketch(th_par, mu_eff=mu_eff, rotation=-90.*u.deg, ax=ax5, **kwargs)
    ax5.set_position([0.34, 0.05, 0.3, 0.9])

    plt.show()