Skip to content

Instantly share code, notes, and snippets.

@Tschucker
Created February 16, 2021 19:02
Show Gist options
  • Save Tschucker/a1aa91f446e772302309c57e9f7c2949 to your computer and use it in GitHub Desktop.
Save Tschucker/a1aa91f446e772302309c57e9f7c2949 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Intensity Graded FFT Animation with QPSK"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"from matplotlib import pyplot as plt\n",
"from matplotlib.animation import FuncAnimation\n",
"import math\n",
"from IPython.display import HTML, Image"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"#Test QPSK Signal\n",
"num_symbols = 256*10240\n",
"sps = 2\n",
"\n",
"x_int = np.random.randint(0, 4, num_symbols) # 0 to 3\n",
"\n",
"x_int = np.repeat(x_int, sps, axis=0)\n",
"\n",
"x_degrees = x_int*360/4.0 + 45 # 45, 135, 225, 315 degrees\n",
"x_radians = x_degrees*np.pi/180.0 # sin() and cos() takes in radians\n",
"x_symbols = np.cos(x_radians) + 1j*np.sin(x_radians) # this produces our QPSK complex symbols\n",
"\n",
"# Create our raised-cosine filter\n",
"num_taps = 101\n",
"beta = 0.35\n",
"Ts = sps # Assume sample rate is 1 Hz, so sample period is 1, so *symbol* period is 8\n",
"t = np.arange(-51, 52) # remember it's not inclusive of final number\n",
"h = np.sinc(t/Ts) * np.cos(np.pi*beta*t/Ts) / (1 - (2*beta*t/Ts)**2)\n",
"\n",
"# Filter our signal, in order to apply the pulse shaping\n",
"x_shaped = np.convolve(x_symbols, h)\n",
"\n",
"n = (np.random.randn(len(x_shaped)) + 1j*np.random.randn(len(x_shaped)))/np.sqrt(2) # AWGN with unity power\n",
"noise_power = 0.001\n",
"r = x_shaped + n * np.sqrt(noise_power)\n",
"\n",
"samples = r"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"#Animate function that interates over fft data\n",
"def animate(i, im, norm_fft_array, mag_steps, fft_len, fft_div): \n",
" mag_step = 1/mag_steps\n",
" \n",
" if i == 0:\n",
" hitmap_array = im.get_array()*np.exp(-10)\n",
" \n",
" else:\n",
" hitmap_array = im.get_array()*np.exp(-0.04)\n",
"\n",
" for m in range(fft_len):\n",
" hit_mag = int(norm_fft_array[i][m]/mag_step)\n",
" hitmap_array[hit_mag][int(m/fft_div)] = hitmap_array[hit_mag][int(m/fft_div)] + .5\n",
"\n",
" #hitmap_array_db = 10.0 * np.log10(hitmap_array) \n",
" \n",
" im.set_array(hitmap_array)\n",
" return [im]\n",
"\n",
"#Function\n",
"def fft_intensity_animate(samples: np.ndarray, fft_len: int = 256, fft_div: int = 2, mag_steps: int = 100):\n",
" \n",
" num_ffts = math.floor(len(samples)/fft_len)\n",
" \n",
" fft_array = []\n",
" for i in range(num_ffts):\n",
" temp = np.fft.fftshift(np.fft.fft(samples[i*fft_len:(i+1)*fft_len]))\n",
" temp_mag = 20.0 * np.log10(np.abs(temp))\n",
" fft_array.append(temp_mag)\n",
" \n",
" max_mag = np.amax(fft_array)\n",
" min_mag = np.abs(np.amin(fft_array))\n",
" \n",
" norm_fft_array = fft_array\n",
" for i in range(num_ffts):\n",
" norm_fft_array[i] = (fft_array[i]+min_mag)/(max_mag+min_mag) \n",
" \n",
" #animation place holder\n",
" fig = plt.figure()\n",
" a = np.random.random((mag_steps+1,int(fft_len/fft_div)))\n",
" im = plt.imshow(a, origin='lower', cmap='plasma', interpolation='bilinear')\n",
" \n",
" #compute animation\n",
" anim = FuncAnimation(fig, animate, frames=1000, fargs = (im,norm_fft_array,mag_steps,fft_len,fft_div), interval=1, blit=True)\n",
" \n",
" return(anim)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Animation"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"# Test parameters\n",
"fft_len = 1024\n",
"fft_div = 2\n",
"mag_steps = 400\n",
"\n",
"anim = fft_intensity_animate(samples, fft_len, fft_div, mag_steps)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Save Animation"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"anim.save('fft_qpsk_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Optional GIF Animation"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"#anim.save('fft_animation.gif', fps=30, writer='pillow')\n",
"#Image(url='fft_animation.gif')"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment