I'm working on a research project that involves detecting hand gestures with WiFi CSI data. I basically have to record samples and then select the 20-packet-long interval during which the gesture occurs. I'm writing a script using ipywidgets
to display the original spectrogram, ask for the first index of the sequence, show cropped spectrogram, and ask for confirmation before writing the clean data to a file.
The script is imported from a .py
file to an ipynb
notebook where the prompts will show.
The problem is that every time I run the imported cleaner
function, the kernel crashes. This happens both on a local machine and Google Colab.
Here's all the relevant code:
# data_cleaner.py
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import csiread # exports csv directly from pcap file!!
import ipywidgets as widgets # --> user interaction in Jupyter
from IPython.display import clear_output, display
def cleaner(csifile, gesture_length):
# Extract csi directly from pcap file
print('testing...') # not even this runs...
csifile = '/content/REU/csi samples/csi_palmfist_1.pcap'
csidata = csiread.Nexmon(csifile, chip='4339', bw=20)
csidata.read()
df1 = pd.DataFrame(csidata.csi)
magMatrix = df1.applymap(abs) # magnitude matrix
# define the useless subcarriers
garbage = [1, 0, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38] # 14 removed
cleaned = df1.drop(garbage, axis = 1)
# display(cleaned)
# amplitude visualization
magMatrix = cleaned.applymap(np.abs)
subcarLineChart(magMatrix)
subcarSpectrogram(magMatrix)
# smoothen the magnitude chart
# apply is essentially map but passes each row instead of each element
magSmoothened = magMatrix.apply(lambda x: mov_avg(x, 3))
subcarLineChart(magSmoothened)
subcarSpectrogram(magSmoothened)
# UI STARTS HERE
# limit useful gesture length to predefined value
start_index = widgets.Text(
value = '',
description = 'Index for first packet in {}-packet sequence containing gesture:'.format(length)
)
extract_btn = widgets.Button(
desciption = 'Extract'
)
extract_btn.on_click(handle_extract)
# START =
# crop selected interval
# btw: mag means magnitude
# magSelected = magSmoothened[START:(START+LENGTH)]
# show selected interval
# subcarLineChart(magSelected)
# subcarSpectrogram(magSelected)
## UI LOGIC
def handle_extract():
magSelected = magSmoothened[START:(START+LENGTH)]
subcarLineChart(magSelected)
subcarSpectrogram(magSelected)
display("Does this match what you were trying to extract? \n If not, re-run the program. (ctrl-f9 on windows)\n")
confirm_btn = widgets.Button(
description = 'Yes, looks good'
)
confirm_btn.on_click(handle_confirm)
def handle_confirm():
print('writes to file...')
## VISUALIZATION FUNCTIONS
from matplotlib import colors
def subcarLineChart(gph, log = False): # log: use log scale or not
packet_index = len(gph.index)
fig = plt.figure()
ax1 = fig.add_subplot(111)
plt.title("Magnitude of Signal by Channel and Packet Number")
plt.xlabel("Packet #")
plt.ylabel("Magnitude")
ax1.set_yscale("log") if log else None
num_subcarriers = len(gph.columns)
num_samples = len(gph)
for subcar_index in range(num_subcarriers):
ax1.plot(
range(num_samples),
gph.iloc[:,subcar_index],
lw = .25,
label = subcar_index
)
plt.show()
def subcarSpectrogram(gph, log = False, subcar_start = 0, subcar_end = -1): # log: use log scale or not
subcar_end = len(gph.iloc[0]) if subcar_end == -1 else subcar_end # replace -1 with valid final index
plt.imshow(
gph,
# extent --> left, rigth, bottom, top
extent = (subcar_start, subcar_end, len(gph), 0),
norm = colors.LogNorm() if log else None)
plt.xlabel('Subcarriers')
plt.ylabel('Packet #')
plt.colorbar(
label = 'intensity')
plt.show()
def mov_avg(arr, width):
return np.convolve(arr, np.ones(width), 'valid') / width
# interactive data cleaning.ipynb
!pip install csiread
from google.colab import drive
import sys
drive.mount('/AshkanDrive')
!ln -s '/AshkanDrive/MyDrive/google_colab_files_for_CSI' '/content/REU'
filepath = '/content/REU/csi samples/old_testing_data/csi_palmfist_1.pcap'
sys.path.insert(0, '/content/REU/utils/')
from data_cleaner import cleaner
cleaner(filepath, 20) # 20 packets should be fine to fit all gestures