import numpy as np from galileo_rx.signal_profiles import galileo_e1_profile from galileo_rx.signals.boc import boc_subcarrier, sample_primary_code from galileo_rx.signals.code_provider import SyntheticCodeProvider from galileo_rx.signals.signal_generator import ChannelModelConfig, SatelliteSignalConfig, SyntheticSignalGenerator def test_code_sampling_wrap_and_noninteger_rate() -> None: code = np.array([1, -1, 1, 1], dtype=np.int8) sampled, phase = sample_primary_code(code, 11, 2.5, 1.0, 3.5) assert sampled.shape == (11,) assert 0 <= phase < 4 assert set(sampled) == {-1.0, 1.0} def test_boc_phase_continuity_between_blocks() -> None: whole, _ = boc_subcarrier(31, 7.3e6, 1.023e6, 0.17) first, phase = boc_subcarrier(13, 7.3e6, 1.023e6, 0.17) second, _ = boc_subcarrier(18, 7.3e6, 1.023e6, phase) np.testing.assert_array_equal(whole, np.concatenate([first, second])) def test_synthetic_provider_is_deterministic_and_component_specific() -> None: profile = galileo_e1_profile() provider = SyntheticCodeProvider() a = provider.primary_code(profile, "E1C", 1) np.testing.assert_array_equal(a, provider.primary_code(profile, "E1C", 1)) assert not np.array_equal(a, provider.primary_code(profile, "E1B", 1)) def test_generator_streaming_matches_single_block_without_noise() -> None: profile = galileo_e1_profile() provider = SyntheticCodeProvider() satellite = SatelliteSignalConfig(prn=3, doppler_hz=1234.0, code_delay_chips=17.25) channel = ChannelModelConfig(add_awgn=False) whole_generator = SyntheticSignalGenerator(profile, provider, 4.5e6, satellites=[satellite], channel=channel) block_generator = SyntheticSignalGenerator(profile, provider, 4.5e6, satellites=[satellite], channel=channel) whole, _ = whole_generator.generate(1001) a, _ = block_generator.generate(317) b, _ = block_generator.generate(684) np.testing.assert_allclose(whole, np.concatenate([a, b]), atol=2e-6) def test_real_if_and_truth_metadata() -> None: profile = galileo_e1_profile() generator = SyntheticSignalGenerator( profile, SyntheticCodeProvider(), 8.0e6, 2.0e6, True, [SatelliteSignalConfig(prn=7, component="E1B", code_delay_chips=2.5)], ChannelModelConfig(add_awgn=False), ) samples, truth = generator.generate(80) assert samples.dtype == np.float64 and not np.iscomplexobj(samples) assert truth.satellites[0].initial_code_delay_samples == 2.5 * 8.0e6 / 1.023e6