import numpy as np import pandas as pd import math def generate_radar_csv(filename="pulse_compression_output.csv"): """ Generate realistic radar CSV data for testing the Python GUI """ # Radar parameters matching your testbench num_long_chirps = 16 num_short_chirps = 16 samples_per_chirp = 512 # Reduced for manageable file size fs_adc = 400e6 # 400 MHz ADC timestamp_ns = 0 # Target parameters targets = [ {'range': 3000, 'velocity': 25, 'snr': 30, 'azimuth': 10, 'elevation': 5}, # Fast moving target {'range': 5000, 'velocity': -15, 'snr': 25, 'azimuth': 20, 'elevation': 2}, # Approaching target {'range': 8000, 'velocity': 5, 'snr': 20, 'azimuth': 30, 'elevation': 8}, # Slow moving target {'range': 12000, 'velocity': -8, 'snr': 18, 'azimuth': 45, 'elevation': 3}, # Distant target ] # Noise parameters noise_std = 5 clutter_std = 10 data = [] chirp_number = 0 # Generate Long Chirps (30µs duration equivalent) print("Generating Long Chirps...") for chirp in range(num_long_chirps): for sample in range(samples_per_chirp): # Base noise i_val = np.random.normal(0, noise_std) q_val = np.random.normal(0, noise_std) # Add clutter (stationary targets) clutter_range = 2000 # Fixed clutter at 2km if sample < 100: # Simulate clutter in first 100 samples i_val += np.random.normal(0, clutter_std) q_val += np.random.normal(0, clutter_std) # Add moving targets with Doppler shift for target in targets: # Calculate range bin (simplified) range_bin = int(target['range'] / 20) # ~20m per bin doppler_phase = 2 * math.pi * target['velocity'] * chirp / 100 # Doppler phase shift # Target appears around its range bin with some spread if abs(sample - range_bin) < 10: # Signal amplitude decreases with range amplitude = target['snr'] * (10000 / target['range']) phase = 2 * math.pi * sample / 50 + doppler_phase i_val += amplitude * math.cos(phase) q_val += amplitude * math.sin(phase) # Calculate derived values magnitude_squared = i_val**2 + q_val**2 data.append({ 'timestamp_ns': timestamp_ns, 'chirp_number': chirp_number, 'chirp_type': 'LONG', 'sample_index': sample, 'I_value': int(i_val), 'Q_value': int(q_val), 'magnitude_squared': int(magnitude_squared) }) timestamp_ns += int(1e9 / fs_adc) # 2.5ns per sample at 400MHz chirp_number += 1 timestamp_ns += 137000 # Add listening period (137µs) # Guard time between long and short chirps timestamp_ns += 175400 # 175.4µs guard time # Generate Short Chirps (0.5µs duration equivalent) print("Generating Short Chirps...") for chirp in range(num_short_chirps): for sample in range(samples_per_chirp): # Base noise i_val = np.random.normal(0, noise_std) q_val = np.random.normal(0, noise_std) # Add clutter (different characteristics for short chirps) if sample < 50: # Less clutter for short chirps i_val += np.random.normal(0, clutter_std/2) q_val += np.random.normal(0, clutter_std/2) # Add moving targets with different Doppler for short chirps for target in targets: # Range bin calculation (different for short chirps) range_bin = int(target['range'] / 40) # Different range resolution doppler_phase = 2 * math.pi * target['velocity'] * (chirp + 5) / 80 # Different Doppler # Target appears around its range bin if abs(sample - range_bin) < 8: # Different amplitude characteristics for short chirps amplitude = target['snr'] * 0.7 * (8000 / target['range']) # 70% amplitude phase = 2 * math.pi * sample / 30 + doppler_phase i_val += amplitude * math.cos(phase) q_val += amplitude * math.sin(phase) # Calculate derived values magnitude_squared = i_val**2 + q_val**2 data.append({ 'timestamp_ns': timestamp_ns, 'chirp_number': chirp_number, 'chirp_type': 'SHORT', 'sample_index': sample, 'I_value': int(i_val), 'Q_value': int(q_val), 'magnitude_squared': int(magnitude_squared) }) timestamp_ns += int(1e9 / fs_adc) # 2.5ns per sample chirp_number += 1 timestamp_ns += 174500 # Add listening period (174.5µs) # Create DataFrame df = pd.DataFrame(data) # Save to CSV df.to_csv(filename, index=False) print(f"Generated CSV file: {filename}") print(f"Total samples: {len(df)}") print(f"Long chirps: {num_long_chirps}, Short chirps: {num_short_chirps}") print(f"Samples per chirp: {samples_per_chirp}") print(f"File size: {len(df) // 1000}K samples") return df def analyze_generated_data(df): """ Analyze the generated data to verify target detection """ print("\n=== Data Analysis ===") # Basic statistics long_chirps = df[df['chirp_type'] == 'LONG'] short_chirps = df[df['chirp_type'] == 'SHORT'] print(f"Long chirp samples: {len(long_chirps)}") print(f"Short chirp samples: {len(short_chirps)}") print(f"Unique chirp numbers: {df['chirp_number'].nunique()}") # Calculate actual magnitude and phase for analysis df['magnitude'] = np.sqrt(df['I_value']**2 + df['Q_value']**2) df['phase_rad'] = np.arctan2(df['Q_value'], df['I_value']) # Find high-magnitude samples (potential targets) high_mag_threshold = df['magnitude'].quantile(0.95) # Top 5% targets_detected = df[df['magnitude'] > high_mag_threshold] print(f"\nTarget detection threshold: {high_mag_threshold:.2f}") print(f"High magnitude samples: {len(targets_detected)}") # Group by chirp type long_targets = targets_detected[targets_detected['chirp_type'] == 'LONG'] short_targets = targets_detected[targets_detected['chirp_type'] == 'SHORT'] print(f"Targets in long chirps: {len(long_targets)}") print(f"Targets in short chirps: {len(short_targets)}") return df if __name__ == "__main__": # Generate the CSV file df = generate_radar_csv("test_radar_data.csv") # Analyze the generated data analyze_generated_data(df) print("\n=== CSV File Ready ===") print("You can now test the Python GUI with this CSV file!") print("The file contains:") print("- 16 Long chirps + 16 Short chirps") print("- 4 simulated targets at different ranges and velocities") print("- Realistic noise and clutter") print("- Proper I/Q data for Doppler processing")