コード例 #1
0
ファイル: test_sampling.py プロジェクト: mhvk/baseband-tasks
 def setup_class(self):
     # Chose signals that are not commensurate with quarter-sample offsets,
     # or with the frames.
     f_signal = (self.full_sample_rate * 2 / self.samples_per_full_frame *
                 np.array([31.092, 65.1234]))
     cosine = PureTone(f_signal, self.start_time, np.pi * u.deg)
     # Create a stream that just contains the two tones, and one sampled
     # at 4 times lower rate.
     self.full_fh = StreamGenerator(
         cosine,
         shape=((self.samples_per_full_frame * self.n_frames, ) +
                self.sideband.shape),
         sample_rate=self.full_sample_rate,
         samples_per_frame=self.samples_per_full_frame,
         frequency=self.frequency,
         sideband=self.sideband,
         start_time=self.start_time,
         dtype=self.dtype)
     self.part_fh = StreamGenerator(
         cosine,
         shape=((self.samples_per_full_frame // 4 * self.n_frames, ) +
                self.sideband.shape),
         sample_rate=self.full_sample_rate / 4,
         samples_per_frame=self.samples_per_full_frame // 4,
         frequency=self.frequency,
         sideband=self.sideband,
         start_time=self.start_time,
         dtype=self.dtype)
コード例 #2
0
def test_real_to_complex_delta():
    """Test converting a real delta function to complex."""
    def real_delta(handle):
        real_delta = np.zeros(handle.samples_per_frame, dtype=np.float64)
        if handle.offset == 0:
            real_delta[0] = 1.0
        return real_delta

    delta_fh = StreamGenerator(real_delta,
                               samples_per_frame=1024,
                               start_time=Time('2010-11-12T13:14:15'),
                               sample_rate=1. * u.kHz,
                               frequency=400 * u.kHz,
                               sideband=1,
                               shape=(2048, ),
                               dtype='f8')
    real_data = delta_fh.read()
    assert real_data[0] == 1.
    assert np.all(real_data[1:] == 0.)

    complex_delta = np.zeros(2048 // 2, dtype=np.complex128)
    complex_delta[0] = 1.0

    real2complex = Real2Complex(delta_fh)
    complex_signal = real2complex.read()
    assert complex_signal.shape == (1024, )
    assert np.iscomplexobj(complex_signal)
    assert np.isclose(complex_signal, complex_delta).all()
    assert real2complex.frequency == 400.5 * u.kHz
    assert real2complex.sideband == 1

    r = repr(real2complex)
    assert r.startswith('Real2Complex(ih)')
コード例 #3
0
ファイル: test_sampling.py プロジェクト: mhvk/baseband-tasks
 def setup_class(self):
     self.shape = (1000, 5, 3)
     self.ih = StreamGenerator(self.make_arange_data,
                               self.shape,
                               Time('2010-11-12'),
                               1. * u.Hz,
                               samples_per_frame=100,
                               dtype=float)
     self.ih.intensity = 2
     self.ih.non_uniform_axis = 1
コード例 #4
0
def test_real_to_complex_sine(f_nyquist):
    """Test converting a real sine function to complex."""
    def real_sine(handle):

        real_sine = np.sin(f_nyquist * np.pi *
                           np.arange(handle.samples_per_frame))
        return real_sine

    sine_fh = StreamGenerator(real_sine,
                              samples_per_frame=1024,
                              start_time=Time('2010-11-12T13:14:15'),
                              sample_rate=1. * u.kHz,
                              frequency=400 * u.kHz,
                              sideband=-1,
                              shape=(2048, ),
                              dtype='f8')

    f_complex = f_nyquist - 0.5
    complex_dc = np.exp(2j * np.pi *
                        (-0.25 + np.arange(2048 // 2) * f_complex))

    real2complex = Real2Complex(sine_fh)
    complex_signal = real2complex.read()

    assert complex_signal.shape == (1024, )
    assert np.iscomplexobj(complex_signal)
    assert_allclose(complex_signal, complex_dc, atol=1e-8)
    assert real2complex.frequency == 399.5 * u.kHz
    assert real2complex.sideband == -1
コード例 #5
0
    def test_sample_slice(self):
        sh = StreamGenerator(self.my_source,
                             shape=self.shape,
                             start_time=self.start_time,
                             sample_rate=self.sample_rate,
                             samples_per_frame=1)
        sliced = sh[-400:]
        assert sliced.shape == (400, ) + sh.sample_shape
        assert abs(sliced.stop_time - sh.stop_time) < 1. * u.ns
        assert abs(sliced.start_time -
                   (sh.stop_time - 400 / sh.sample_rate)) < 1. * u.ns
        sh.seek(-400, 2)
        expected = sh.read()
        data = sliced.read()
        assert np.all(data == expected)

        r = repr(sliced)
        assert r.startswith('GetSlice(ih, item=')
        assert '\nih: StreamGenerator(' in r
コード例 #6
0
    def test_exceptions(self):
        with StreamGenerator(self.my_source,
                             shape=self.shape,
                             start_time=self.start_time,
                             sample_rate=self.sample_rate,
                             samples_per_frame=1) as sh:
            with pytest.raises(EOFError):
                sh.seek(-10, 2)
                sh.read(20)
            with pytest.raises(AttributeError):
                sh.frequency
            with pytest.raises(AttributeError):
                sh.sideband
            with pytest.raises(AttributeError):
                sh.polarization

        with pytest.raises(ValueError):
            StreamGenerator(self.my_source,
                            shape=self.shape,
                            start_time=self.start_time,
                            sample_rate=self.sample_rate,
                            sideband=np.ones((2, 2), dtype='i1'))
コード例 #7
0
 def test_frequency_sideband_setting(self):
     frequency = np.array([320., 350., 380., 410.])[:, np.newaxis] * u.MHz
     sideband = np.array([-1, 1])
     with StreamGenerator(self.my_source,
                          frequency=frequency,
                          sideband=sideband,
                          shape=self.shape,
                          start_time=self.start_time,
                          sample_rate=self.sample_rate,
                          samples_per_frame=1) as sh:
         assert np.all(sh.frequency == frequency)
         assert np.all(sh.sideband == sideband)
         with pytest.raises(AttributeError):
             sh.polarization
コード例 #8
0
 def test_frequency_sideband_polarization_setting(self):
     frequency = np.array([320., 320., 350., 350.])[:, np.newaxis] * u.MHz
     sideband = np.array([-1, 1, -1, 1])[:, np.newaxis]
     polarization = np.array(['X', 'Y'])
     with StreamGenerator(self.my_source,
                          polarization=polarization,
                          frequency=frequency,
                          sideband=sideband,
                          shape=self.shape,
                          start_time=self.start_time,
                          sample_rate=self.sample_rate,
                          samples_per_frame=1) as sh:
         assert np.all(sh.frequency == frequency)
         assert np.all(sh.sideband == sideband)
         assert np.all(sh.polarization == polarization)
コード例 #9
0
ファイル: test_sampling.py プロジェクト: mhvk/baseband-tasks
 def setup_class(self):
     self.full_shape = ((self.samples_per_full_frame * self.n_frames, ) +
                        self.sideband.shape)
     self.downsample = (16 if self.dtype.kind == 'c' else 8)
     self.sample_rate = self.full_sample_rate / self.downsample
     # Create the IF (which can produce a complex tone for quadrature).
     self.mixer = PureTone(self.lo, self.start_time, self.phi0_mixer)
     # Create a real-valued stream with a test-specific signal.
     self.raw = StreamGenerator(
         self.signal,
         shape=self.full_shape,
         start_time=self.start_time,
         sample_rate=self.full_sample_rate,
         dtype=np.dtype('f4'),
         samples_per_frame=self.samples_per_full_frame)
コード例 #10
0
 def setup_class(self):
     self.start_time = Time('2010-11-12T13:14:15')
     self.sample_rate = 128. * u.kHz
     self.shape = (164000, 2)
     self.gp_sample = 64000
     # Complex timestream
     self.gp = StreamGenerator(self.make_giant_pulse,
                               shape=self.shape,
                               start_time=self.start_time,
                               sample_rate=self.sample_rate,
                               samples_per_frame=1000,
                               dtype=np.complex64,
                               frequency=300 * u.MHz,
                               sideband=np.array((1, -1)))
     # Time delay of 0.05 s over 128 kHz band.
     self.dm = DispersionMeasure(1000. * 0.05 / 0.039342251)
コード例 #11
0
 def setup(self):
     self.start_time = Time('2010-11-12T13:14:15')
     self.sample_rate = 128. * u.kHz
     self.shape = (164000, 2)
     self.gp_sample = 64000
     # Real timestream; mean frequecies of the two bands are the same.
     self.gp = StreamGenerator(self.make_giant_pulse,
                               shape=self.shape,
                               start_time=self.start_time,
                               sample_rate=self.sample_rate,
                               samples_per_frame=1000,
                               dtype=np.float32,
                               frequency=300. * u.MHz,
                               sideband=np.array((1, -1)))
     # Time delay of 0.05 s over 128 kHz band.
     self.dm = DispersionMeasure(1000. * 0.05 / 0.039342251)
コード例 #12
0
    def test_repr(self):
        frequency = np.array([320., 350., 380., 410.])[:, np.newaxis] * u.MHz
        sideband = np.array([-1, 1])
        with StreamGenerator(self.my_source,
                             frequency=frequency,
                             sideband=sideband,
                             shape=self.shape,
                             start_time=self.start_time,
                             sample_rate=self.sample_rate,
                             samples_per_frame=1) as sh:
            r = repr(sh)

        assert r.startswith('StreamGenerator(')
        assert 'start_time=' in r
        assert 'samples_per_frame' not in r  # has default
        assert 'frequency=' in r
        assert 'polarization' not in r
コード例 #13
0
 def test_basics(self):
     with StreamGenerator(self.my_source,
                          shape=self.shape,
                          start_time=self.start_time,
                          sample_rate=self.sample_rate,
                          samples_per_frame=1) as sh:
         assert sh.size == np.prod(self.shape)
         assert sh.shape == self.shape
         assert isinstance(sh.dtype, np.dtype)
         assert sh.dtype == np.dtype('c8')
         assert sh.samples_per_frame == 1
         assert abs(sh.stop_time - sh.start_time - 1. * u.s) < 1. * u.ns
         sh.seek(980)
         data1 = sh.read(1)
         assert data1.dtype == sh.dtype
         assert np.all(data1 == 980.)
         data2 = sh.read()
         assert data2.shape == (1000 - 981, 4, 2)
         assert np.all(data2 == np.arange(981, 1000).reshape(19, 1, 1))
コード例 #14
0
    def test_zeros_generation(self):
        def generate_zero(sh):
            return np.zeros((sh.samples_per_frame, ) + sh.shape[1:], sh.dtype)

        with StreamGenerator(generate_zero,
                             shape=self.shape,
                             start_time=self.start_time,
                             sample_rate=self.sample_rate,
                             samples_per_frame=10) as sh:
            assert sh.size == np.prod(self.shape)
            assert sh.shape == self.shape
            assert sh.samples_per_frame == 10
            assert abs(sh.stop_time - sh.start_time - 1. * u.s) < 1. * u.ns
            sh.seek(10)
            data1 = sh.read(2)
            assert data1.dtype == sh.dtype == np.dtype('c8')
            assert np.all(data1 == 0.)
            data2 = sh.read()
            assert data2.shape == (1000 - 12, 4, 2)
            assert np.all(data2 == 0.)
コード例 #15
0
 def test_disperse(self):
     gp = StreamGenerator(self.make_giant_pulse,
                          shape=self.shape,
                          start_time=self.start_time,
                          sample_rate=self.sample_rate,
                          samples_per_frame=1000,
                          dtype=np.float32,
                          frequency=300. * u.MHz,
                          sideband=np.array((1, -1)))
     disperse = Disperse(gp, self.dm)
     assert_quantity_allclose(disperse.reference_frequency, 300. * u.MHz)
     disperse.seek(self.start_time + self.gp_sample / self.sample_rate)
     disperse.seek(-self.gp_sample // 2, 1)
     around_gp = disperse.read(self.gp_sample)
     assert around_gp.dtype == np.float32
     p = (around_gp**2).reshape(-1, self.gp_sample // 20, 2).sum(1)
     # Note: FT leakage means that not everything outside of the dispersed
     # pulse is zero.  But the total power there is small.
     assert np.all(p[:9] < 0.006)
     assert np.all(p[11:] < 0.006)
     # Lower sideband [1] has lower frequencies and thus is dispersed
     # to later.
     assert p[9, 0] > 0.99 and p[10, 0] < 0.006
     assert p[10, 1] > 0.99 and p[9, 1] < 0.006
コード例 #16
0
ファイル: test_sampling.py プロジェクト: mhvk/baseband-tasks
class TestResampleReal:
    """Tests for resampling a signal.

    Here used for a real signal, but subclassed below for complex.
    """

    dtype = np.dtype('f4')
    full_sample_rate = 1 * u.kHz
    samples_per_full_frame = 4096  # Per full frame.
    start_time = Time('2010-11-12T13:14:15')
    frequency = 400. * u.kHz
    sideband = np.array([-1, 1])
    n_frames = 3

    pad = 32  # Size of response = 2*pad + 1.
    atol = 7e-4  # Tolerance within which we expect to reproduce signal.

    @classmethod
    def setup_class(self):
        # Chose signals that are not commensurate with quarter-sample offsets,
        # or with the frames.
        f_signal = (self.full_sample_rate * 2 / self.samples_per_full_frame *
                    np.array([31.092, 65.1234]))
        cosine = PureTone(f_signal, self.start_time, np.pi * u.deg)
        # Create a stream that just contains the two tones, and one sampled
        # at 4 times lower rate.
        self.full_fh = StreamGenerator(
            cosine,
            shape=((self.samples_per_full_frame * self.n_frames, ) +
                   self.sideband.shape),
            sample_rate=self.full_sample_rate,
            samples_per_frame=self.samples_per_full_frame,
            frequency=self.frequency,
            sideband=self.sideband,
            start_time=self.start_time,
            dtype=self.dtype)
        self.part_fh = StreamGenerator(
            cosine,
            shape=((self.samples_per_full_frame // 4 * self.n_frames, ) +
                   self.sideband.shape),
            sample_rate=self.full_sample_rate / 4,
            samples_per_frame=self.samples_per_full_frame // 4,
            frequency=self.frequency,
            sideband=self.sideband,
            start_time=self.start_time,
            dtype=self.dtype)

    def test_setup(self):
        self.full_fh.seek(0)
        self.part_fh.seek(0)
        full = self.full_fh.read()
        part = self.part_fh.read()
        assert_allclose(part, full[::4], atol=1e-8, rtol=0)

    @pytest.mark.parametrize('offset',
                             (34, 34.5, 35.75, 50. * u.ms, 0.065 * u.s,
                              Time('2010-11-12T13:14:15.073')))
    def test_resample(self, offset):
        # Offsets equal to quarter samples to allow check with full_fh.
        ih = Resample(self.part_fh, offset, pad=self.pad)
        # Always lose 2 * pad per frame.
        assert ih.shape[0] == self.part_fh.shape[0] - 2 * self.pad
        assert ih.sample_shape == self.part_fh.sample_shape
        # Check we are at the given offset.
        if isinstance(offset, Time):
            expected_time = offset
        elif isinstance(offset, u.Quantity):
            expected_time = self.part_fh.start_time + offset
        else:
            expected_time = (self.part_fh.start_time +
                             offset / self.part_fh.sample_rate)
        assert abs(ih.time - expected_time) < 1. * u.ns

        part_fh_offset = seek_float(self.part_fh, offset)
        ioffset = round(part_fh_offset)
        fraction = part_fh_offset - ioffset
        assert ih.offset + self.pad == ioffset
        expected_start_time = (self.part_fh.start_time + (
            (self.pad + fraction) / self.part_fh.sample_rate))
        assert abs(ih.start_time - expected_start_time) < 1. * u.ns
        # Check that data is correctly resampled.
        ih.seek(0)
        data = ih.read()
        # Find corresponding fully sampled data.
        self.full_fh.seek(ih.start_time)
        # Check time: should be exact, since our offsets are quarter samples.
        assert np.abs(self.full_fh.time - ih.start_time) < 1. * u.ns
        expected = self.full_fh.read(data.shape[0] * 4)[::4]
        assert_allclose(data, expected, atol=self.atol, rtol=0)

    def test_repr(self):
        ih = Resample(self.part_fh, 0.5, samples_per_frame=511)
        r = repr(ih)
        assert r.startswith('Resample(ih')
        assert 'offset=0.5' in r

    @pytest.mark.parametrize('shift',
                             (0., 0.25, -5.25, [1.75, 10.25], [-1., 13] * u.ms)
                             )
    @pytest.mark.parametrize('offset', (None, 0, 0.25))
    def test_shift_and_resample(self, shift, offset):
        # Shifts and offsets at quarter samples to allow check with full_fh.
        ih = ShiftAndResample(self.part_fh, shift, offset=offset, pad=self.pad)
        # start_time should be at expected offset from old grid.
        expected_offset = seek_float(
            self.part_fh, offset if offset is not None else np.mean(shift))
        d_off = ((ih.start_time - self.start_time) * ih.sample_rate -
                 expected_offset).to_value(u.one)
        assert abs(d_off - np.around(d_off)) < u.ns * ih.sample_rate
        expected_length = (self.part_fh.shape[0] - 2 * self.pad -
                           seek_float(self.part_fh, np.ptp(shift)))
        assert abs(ih.shape[0] - expected_length) <= 0.5

        # Data should be shifted by the expected amounts.
        shift = np.atleast_1d(shift)
        for i, s in enumerate(shift):
            ih.seek(0)
            time_shift = seek_float(self.part_fh, s) / ih.sample_rate
            fh_pos = self.full_fh.seek(ih.time - time_shift)
            assert fh_pos >= 0
            assert abs(ih.time - time_shift - self.full_fh.time) < 1. * u.ns

            data = ih.read()
            expected = self.full_fh.read(len(data) * 4)[::4]
            sel = i if shift.size > 1 else Ellipsis
            assert_allclose(data[:, sel],
                            expected[:, sel],
                            atol=self.atol,
                            rtol=0)
コード例 #17
0
ファイル: test_sampling.py プロジェクト: mhvk/baseband-tasks
class TestShiftSamples:
    @classmethod
    def make_arange_data(self, ih):
        test_data = (np.arange(
            ih.offset, ih.offset +
            ih.samples_per_frame).reshape((ih.samples_per_frame, ) +
                                          (1, ) * len(ih.shape[1:])))
        new_shape = (ih.samples_per_frame, ) + ih.shape[1:]
        return np.broadcast_to(test_data, new_shape)

    @classmethod
    def make_non_uniform_arange_data(self, ih):
        axis = ih.non_uniform_axis
        data = self.make_arange_data(ih)
        multiplier = np.arange(1, data.shape[axis] + 1) * ih.intensity
        return data * multiplier.reshape((data.shape[axis], ) + (1, ) *
                                         (data.ndim - 1 - axis))

    @classmethod
    def setup_class(self):
        self.shape = (1000, 5, 3)
        self.ih = StreamGenerator(self.make_arange_data,
                                  self.shape,
                                  Time('2010-11-12'),
                                  1. * u.Hz,
                                  samples_per_frame=100,
                                  dtype=float)
        self.ih.intensity = 2
        self.ih.non_uniform_axis = 1

    @pytest.mark.parametrize('start, n', [(0, 5), (90, 20)])
    def test_shift_back(self, start, n):
        shift_axis = 1
        shift = np.arange(-self.shape[shift_axis] + 1, 1)
        assert shift.max() == 0
        shifter = ShiftSamples(self.ih,
                               shift.reshape(-1, 1),
                               samples_per_frame=100)
        assert shifter.start_time == self.ih.start_time
        shifter.seek(start)
        shifted = shifter.read(n)
        self.ih.seek(start)
        raw_data = self.ih.read(100)
        for i, sf in enumerate(-shift):
            assert np.all(shifted[:, i] == raw_data[sf:sf + n, i])

    @pytest.mark.parametrize('start, n', [(0, 5), (100, 20)])
    def test_shift_both(self, start, n):
        shift = np.array([-2, 0, 3])
        shifter = ShiftSamples(self.ih, shift, samples_per_frame=100)
        assert abs(shifter.start_time - 3 / self.ih.sample_rate -
                   self.ih.start_time) < 1. * u.ns
        shifter.seek(start)
        shifted = shifter.read(n)
        self.ih.seek(start)
        raw_data = self.ih.read(100)
        for i, sf in enumerate(3 - shift):
            assert np.all(shifted[:, :, i] == raw_data[sf:sf + n, :, i])

    def test_compare_with_shift_and_resample(self):
        shift = np.array([-2, 1, 4])
        shifter = ShiftSamples(self.ih, shift, samples_per_frame=100)
        resampler = ShiftAndResample(self.ih,
                                     shift,
                                     offset=0,
                                     pad=32,
                                     samples_per_frame=200)
        # Note: resampler has larger padding, so start time is later.
        shifter.seek(90)
        resampler.seek(shifter.time)
        # integer shifts, so time should be same.
        assert abs(resampler.time - shifter.time) < 1. * u.ns
        shifted = shifter.read(20)
        resampled = resampler.read(20)
        assert_allclose(shifted, resampled)

    @pytest.mark.parametrize(
        'fshift, ishift', [(np.array([1., 2., 3.25]), [1, 2, 3]),
                           (np.array([[-1.9], [-5.], [5.25], [3.49], [-1.2]]),
                            np.reshape([-2, -5, 5, 3, -1], (-1, 1)))])
    def test_non_integer_shift(self, fshift, ishift):
        shifter1 = ShiftSamples(self.ih, fshift)
        comparison = ShiftSamples(self.ih, ishift)
        assert np.all(shifter1._shift == comparison._shift)
        data1 = shifter1.read()
        expected = comparison.read()
        assert np.all(data1 == expected)
        shifter2 = ShiftSamples(self.ih, fshift / self.ih.sample_rate)
        assert np.all(shifter2._shift == comparison._shift)
        data2 = shifter2.read()
        assert np.all(data2 == expected)

    def test_wrong_shape(self):
        with pytest.raises(ValueError, match='broadcast to sample shape'):
            ShiftSamples(self.ih, np.array([[1], [2]]))