Forums › VSG Series Discussions › VSG60 AWGN using Python Example › Reply To: VSG60 AWGN using Python Example
SignalHoundUser
Forum wont allow .py files. Hopefully the txt will work.
# -*- coding: utf-8 -*-
# This example generates a basic AWGN signal.
from vsgdevice.vsg_api import *
from time import sleep
import matplotlib.pyplot as plt
#numpy.set_printoptions(threshold=numpy.inf) #Use to print full length arrays
def plot_complex_fft(complex_data, sampling_rate):
# Calculate and plot the Frequency data
# Calculate FFT
fft_result = numpy.fft.fft(complex_data)
fft_freq = numpy.fft.fftfreq(len(complex_data), 1 / sampling_rate)
# print(fft_freq)
# Plot the results
plt.figure(figsize=(10, 6))
# Plot the frequency-domain signal (FFT)
plt.plot(fft_freq, numpy.real(fft_result), color=’red’, label=’I Data’)
plt.plot(fft_freq, numpy.imag(fft_result), color=’blue’, label=’Q Data’)
# plt.plot(numpy.abs(fft_result))
plt.title(‘FFT of Complex Signal’)
plt.xlabel(‘Frequency (Hz)’)
plt.ylabel(‘Amplitude’)
plt.show()
def plot_IQ(complex_data, sampling_rate):
# Plot the Time Series results
plt.figure(figsize=(10, 6))
# Separate the real and imaginary parts
I_data = numpy.real(complex_data)
Q_data = numpy.imag(complex_data)
# Plot the frequency-domain signal (FFT)
plt.plot(I_data, color=’red’, label=’I Data’)
plt.plot(Q_data, color=’blue’, label=’Q Data’)
# plt.plot(numpy.abs(fft_result))
plt.title(‘Complex Signal’)
plt.xlabel(‘Samples’)
plt.ylabel(‘Amplitude’)
plt.show()
def low_pass_filter(complex_data: numpy.ndarray, BW: int = 40e6, sampling_rate: int = 50e6) -> numpy.ndarray:
# translate bandlimit from Hz to dataindex according to sampling rate and data size
bandlimit_index = int(BW * (complex_data.size/2) / sampling_rate)
fsig = numpy.fft.fft(complex_data)
for i in range(bandlimit_index + 1, len(fsig) – bandlimit_index):
fsig[i] = 0
adata_filtered = numpy.fft.ifft(fsig)
return adata_filtered
def normalise_level(complex_data):
# Normalise average level to 0dB
aveSig = numpy.average(numpy.abs(complex_data))
aveSigdB = 20*numpy.log10(aveSig) # should be 0dB
print(“Normalised Signal dB = ” + str(aveSigdB))
complex_data *= 1/aveSig
aveSig = numpy.average(numpy.abs(complex_data))
aveSigdB = 20*numpy.log10(aveSig) # should be 0dB
print(“Normalised Signal dB = ” + str(aveSigdB))
return complex_data
def interleaved_to_complex(interleaved_data):
# Reshape the interleaved data into a complex array
complex_data = interleaved_data[0::2] + 1j * interleaved_data[1::2]
return complex_data
def complex_to_interleaved(complex_data):
# Separate the real and imaginary parts
real_parts = numpy.real(complex_data)
imag_parts = numpy.imag(complex_data)
# Interleave the real and imaginary parts
interleaved_iq = numpy.empty(2 * len(complex_data), dtype=numpy.float32)
interleaved_iq[0::2] = real_parts
interleaved_iq[1::2] = imag_parts
return interleaved_iq
def complex_AWGN(length, stddev):
iq = numpy.random.normal(0, stddev, length) + 1j * \
numpy.random.normal(0, stddev, length) # .astype(numpy.float32)
return iq
def generate_iq():
# Open device
ret = vsg_open_device()
print(ret)
handle = ret[“handle”]
serialNumber = vsg_get_serial_number(handle)[“serial”]
# Configure generator
freq = 1.0e9 # Hz
sample_rate = 50.0e6 # samples per second
BW = 40.0e6 # Target bandwidth of AWGN
level = -20.0 # dBm
vsg_set_frequency(handle, freq)
vsg_set_level(handle, level)
vsg_set_sample_rate(handle, sample_rate)
vsg_recal(handle)
# Gernerate Waveform
iq = complex_AWGN(16384, 100)
iq = low_pass_filter(iq, BW, sample_rate)
iq = normalise_level(iq) #Set IQ to 0dB
iq = complex_to_interleaved(iq)
vsg_repeat_waveform(handle, iq.astype(numpy.float32), int(len(iq)/2))
print(“Waveform set”)
# Ramp Power
for power in range(-100, -30, 5):
vsg_set_level(handle, power)
print(“Power = ” + str(power))
scaling = vsg_get_IQ_scale(handle)[“iq_scale”]
print(“scaling = ” + str(scaling))
sleep(1)
print(“complete”)
# Stop waveform
vsg_abort(handle)
# Done with device
vsg_close_device(handle)
print(“closed”)
if __name__ == “__main__”:
generate_iq()
