示例#1
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
示例#2
0
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)
示例#3
0
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]]))