From e4b0645ac6ecb19bb91dfce9f77873a752d67dff Mon Sep 17 00:00:00 2001 From: Jono Targett Date: Mon, 27 May 2024 00:37:47 +0930 Subject: [PATCH] Proper cleanup of selcal-fft.py --- scripts/selcal-fft.py | 69 +++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 38 deletions(-) diff --git a/scripts/selcal-fft.py b/scripts/selcal-fft.py index d2f4b13..a9a6bc9 100755 --- a/scripts/selcal-fft.py +++ b/scripts/selcal-fft.py @@ -1,6 +1,5 @@ #! /usr/bin/env python3 - import numpy as np from scipy.io import wavfile from scipy.fft import fft @@ -40,14 +39,14 @@ data, sample_rate = anti_alias(data, sample_rate, max_freq) fft_size = 1024 # Must be larger than max_freq TODO JMT: fix this, zero-pad frequency_resolution = sample_rate / fft_size -high_bin = int(max_freq / frequency_resolution) +max_bin = int(max_freq / frequency_resolution) segment_interval = 0.2 # seconds samples_per_interval = int(sample_rate * segment_interval) num_segments = len(data) // samples_per_interval -fft_results = np.zeros((num_segments, high_bin)) +fft_results = np.zeros((num_segments, max_bin)) for i in range(num_segments): # Segment window is current position to fft_size samples in the past. As such some segments @@ -65,16 +64,18 @@ for i in range(num_segments): normalized_magnitudes = magnitudes / np.sqrt(total_energy) # Store the normalised magnitude spectrum only for the desired frequency range - fft_results[i, :] = normalized_magnitudes[:high_bin] + fft_results[i, :] = normalized_magnitudes[:max_bin] tone_width = 6.25 # Hz def band(centre_frequency, width=tone_width): - return np.array([centre_frequency - width, centre_frequency + width]) + return (centre_frequency - width, centre_frequency + width) + + def bins(band): + return (int(band[0]/frequency_resolution), int(band[1]/frequency_resolution)) def magnitude_in_band(band): - return np.sum( - normalized_magnitudes[int(band[0]/frequency_resolution):int(band[1]/frequency_resolution)] - ) + low_bin, high_bin = bins(band) + return np.sum(normalized_magnitudes[low_bin:high_bin]) scores = { tone:decibels(magnitude_in_band(band(frequency))) @@ -85,8 +86,8 @@ for i in range(num_segments): if active_tones: print(active_tones) - except: - pass + except Exception as e: + print(e) # Only import if we're actually plotting, these imports are pretty heavy. @@ -94,39 +95,31 @@ import pyqtgraph as pg from pyqtgraph.Qt import QtGui, QtWidgets, QtCore, mkQApp app = pg.mkQApp("ImageView Example") +window = QtWidgets.QMainWindow() +window.resize(1280, 720) +window.setWindowTitle(f"SELCAL FFT Analysis: {file_name}") -## Create window with ImageView widget -win = QtWidgets.QMainWindow() -win.resize(1280, 720) -imv = pg.GraphicsLayoutWidget(show=True) -win.setCentralWidget(imv) +layout = pg.GraphicsLayoutWidget(show=True) +window.setCentralWidget(layout) +plot = layout.addPlot() +fft_view = pg.ImageItem() +fft_view.setImage(fft_results) +fft_view.setRect(QtCore.QRectF(0, 0, len(data) // sample_rate, max_freq)) +plot.addItem(fft_view) -correlogram = pg.ImageItem() -correlogram.setImage(fft_results) -img_rect = QtCore.QRectF(0, 0, len(data) // sample_rate, max_freq) -correlogram.setRect(img_rect) +# Note JMT: Requires matplotlib installed to use this colormap +colormap = pg.colormap.get("CMRmap", source='matplotlib') +colorbar = pg.ColorBarItem( values=(0,1), colorMap=colormap) +colorbar.setImageItem(fft_view, insert_in=plot) -plotItem = imv.addPlot() # add PlotItem to the main GraphicsLayoutWidget -#plotItem.setDefaultPadding(0.0) # plot without padding data range -plotItem.addItem(correlogram) # display correlogram -#plotItem.showAxes(True, showValues=(True, True, False, False), size=20) - -freq_pen = pg.mkPen(color=(20, 20, 20), width=1, style=QtCore.Qt.DashLine) -for freq in TONES.values(): - horizontal_line = pg.InfiniteLine(pos=freq, angle=0, pen=freq_pen) - plotItem.addItem(horizontal_line) +tone_pen = pg.mkPen(color=(20, 20, 20), width=1, style=QtCore.Qt.DashLine) +for frequency in TONES.values(): + tone_line = pg.InfiniteLine(pos=frequency, angle=0, pen=tone_pen) + plot.addItem(tone_line) yticks = [(frequency, tone) for tone,frequency in TONES.items()] -plotItem.getAxis('left').setTicks([yticks]) - -colorMap = pg.colormap.get("CMRmap", source='matplotlib') # choose perceptually uniform, diverging color map -# generate an adjustabled color bar, initially spanning -1 to 1: -bar = pg.ColorBarItem( values=(0,1), colorMap=colorMap) -# link color bar and color map to correlogram, and show it in plotItem: -bar.setImageItem(correlogram, insert_in=plotItem) - -win.show() -win.setWindowTitle('pyqtgraph example: ImageView') +plot.getAxis('left').setTicks([yticks]) +window.show() pg.exec()