Saturday, October 7, 2023

TKINTER: BUTTERWORTH FILTERING---BALIGE ACADEMY

 This is the product of BALIGE ACADEMY TEAM: Vivian Siahaan and Rismon Hasiholan Sianipar.

SEMANGAT BELAJAR dan HORAS!!!

BALIGE CITY, NORTH SUMATERA


SUPPORT OUR CHANNEL BY SUBSCRIBING TO IT:



BUTTERWORTH LOWPASS FILTERING:


#filter_utils.py
import matplotlib.pyplot as plt
import numpy as np 
import scipy.signal as sig
from am_utils import AM_Utils
from fm_utils import FM_Utils
from pm_utils import PM_Utils
from ask_utils import ASK_Utils
from fsk_utils import FSK_Utils
from psk_utils import PSK_Utils

class Filter_Utils:
    def __init__(self):
        self.am_utils = AM_Utils()
        self.fm_utils = FM_Utils()
        self.pm_utils = PM_Utils()
        self.ask_utils = ASK_Utils()
        self.fsk_utils = FSK_Utils()
        self.psk_utils = PSK_Utils()
        
    def generate_noisy_sinusoidal(self, T, F, Fs, noise_amplitude):
        # Defines time line
        t = np.arange(0, T, 1/Fs)
        signal = np.sin(2*np.pi*F*t)
        
        # Generate random noise
        noise = noise_amplitude * np.random.randn(len(t))
        y = signal + noise
        return t, y

    def generate_random_binary_array(self, length):
        # Generate a random binary array of specified length
        return np.random.randint(2, size=length)
    
    def generate_noisy_square(self, T, Fs, samples_per_bit, noise_amplitude):
        # Defines time line
        t = np.arange(0, T, 1/Fs)
        
        bit_arr_size = int(2*Fs/samples_per_bit)
        bit_arr = self.generate_random_binary_array(bit_arr_size)
        
        square_signal = np.repeat(bit_arr, samples_per_bit)[:len(t)]

       # Ensures the lengths of square_signal and t match
        if len(square_signal) < len(t):
            square_signal = np.pad(square_signal, (0, len(t) - len(square_signal)))

        # Generate random noise
        noise = noise_amplitude * np.random.randn(len(t))
        y = square_signal + noise
        
        return t, y

    def generate_noisy_amp_modulation(self, T, Fs, noise_amplitude):        
        t, carrier_wave, modulating_wave, am_signal = self.am_utils.calculate_amplitude_modulation(Fs, T, 1, 25, 1, 5)

        # Generate random noise
        noise = noise_amplitude * np.random.randn(len(t))
        y = am_signal + noise
        
        return t, y

    def generate_noisy_freq_modulation(self, T, Fs, noise_amplitude):        
        t, carrier_wave, modulating_wave, fm_signal = self.fm_utils.calculate_frequency_modulation(2, Fs, T, 1, 25, 1, 5)

        # Generate random noise
        noise = noise_amplitude * np.random.randn(len(t))
        y = fm_signal + noise
        
        return t, y

    def generate_noisy_phase_modulation(self, T, Fs, noise_amplitude):        
        t, carrier_wave, modulating_wave, am_signal = self.pm_utils.calculate_phase_modulation(Fs, T, 1, 15, 0, 1, 5, 0)

        # Generate random noise
        noise = noise_amplitude * np.random.randn(len(t))
        y = am_signal + noise
        
        return t, y

    def generate_noisy_ask_modulation(self, T, Fs, noise_amplitude):        
        t, carrier_wave, modulating_wave, ask_signal = self.ask_utils.calculate_ask_modulation(Fs, T, 1, 15, 0, 50)

        # Generate random noise
        noise = noise_amplitude * np.random.randn(len(t))
        y = ask_signal + noise
        
        return t, y

    def generate_noisy_fsk_modulation(self, T, Fs, noise_amplitude):        
        t, carrier_wave, modulating_wave, fsk_signal = self.fsk_utils.calculate_fsk_modulation(Fs, T, 1, 15, 0, 50)

        # Generate random noise
        noise = noise_amplitude * np.random.randn(len(t))
        y = fsk_signal + noise
        
        return t, y

    def generate_noisy_psk_modulation(self, T, Fs, noise_amplitude):        
        t, carrier_wave, modulating_wave, psk_signal = self.psk_utils.calculate_psk_modulation(Fs, T, 1, 15, 0, 50)

        # Generate random noise
        noise = noise_amplitude * np.random.randn(len(t))
        y = psk_signal + noise
        
        return t, y
    
    def perform_convolution(self, t, signal_in, time_filter):
        # Performs convolution
        filtered_output = np.convolve(signal_in, time_filter, mode='same')

        # Create a time array with the same length as filtered_output
        t_filtered = t[:len(filtered_output)]  
        
        return t_filtered, filtered_output
        
    def plot_signal_filtering(self, t, signal_in, title1, time_filter, title2, figure, canvas):
        figure.clear()   

        ax1 = figure.add_subplot(2,2,1)
        ax1.plot(t, signal_in, linewidth=2.0, color='red')
        ax1.set_ylabel('Amplitude', color='blue')
        ax1.set_xlabel('Time (second)', color='blue')
        ax1.set_title(title1)
        ax1.set_facecolor('#F0F0F0')
        ax1.grid(True)   
        
        ax2 = figure.add_subplot(2,2,2)
        stem= ax2.stem(range(len(time_filter)), time_filter)
        stem[1].set_linewidth(3)
        ax2.set_xlabel('n', color='blue')
        ax2.set_title(title2)
        ax2.set_facecolor('#F0F0F0')
        ax2.grid(True)         
        
        ax3 = figure.add_subplot(2,2,3)
        w, v = sig.freqz(time_filter)
        ax3.plot(w, 20*np.log10(abs(v)), linewidth=3)
        ax3.set_ylabel('Decible')
        ax3.set_xlabel('Radians per second (0-π)')
        ax3.set_title("Frequency Response of Filter")
        ax3.set_facecolor('#F0F0F0')
        ax3.grid(True)         

        ax4 = figure.add_subplot(2,2,4)
        t_filtered, filtered_output = self.perform_convolution(t, signal_in, time_filter)
        ax4.plot(t_filtered, filtered_output, linewidth=2.0, color='red')
        ax4.set_ylabel('Amplitude', color='blue')
        ax4.set_xlabel('Time (second)', color='blue')
        ax4.set_title("Filtered Output")
        ax4.set_facecolor('#F0F0F0')
        ax4.grid(True)  
        
        figure.tight_layout()
        canvas.draw()          

    def butterworth_lowpass(self, signal_in, N, lowcut, Fs):
        nyqs=0.5*Fs
        low= lowcut/nyqs
        # b is the numerator of the filter & a is the denominator
        b, a = sig.butter(N, low, 'lowpass', analog=False)
        
        # w is the freq in z-domain & h is the magnitude in z-domain
        w, h = sig.freqz(b, a, fs=Fs, worN=2000)

        signal_out = sig.filtfilt(b, a, signal_in, axis=0)
        
        return signal_out, b, a, w, h

    def butterworth_bandpass(self, signal_in, order, lowcut, highcut, Fs):
        nyqs = 0.5* Fs
        low = lowcut / nyqs
        high = highcut/ nyqs
    
        # b is the numerator of the filter & a is the denominator
        b, a = sig.butter(order, [low, high], 'bandpass', analog=False)
        
        # w is the freq in z-domain & h is the magnitude in z-domain
        w, h = sig.freqz(b, a, fs=Fs, worN=2000)

        signal_out = sig.filtfilt(b, a, signal_in, axis=0)
        
        return signal_out, b, a, w, h
    
    def plot_iir_filtering(self, t, signal_in, title1, signal_out, b, a, w, h, figure, canvas):
        figure.clear()   

        ax1 = figure.add_subplot(2,2,1)
        ax1.plot(t, signal_in, linewidth=2.0, color='red')
        ax1.set_ylabel('Amplitude', color='blue')
        ax1.set_xlabel('Time (second)', color='blue')
        ax1.set_title(title1)
        ax1.set_facecolor('#F0F0F0')
        ax1.grid(True)   
        
        ax2 = figure.add_subplot(2,2,2)
        imp = sig.unit_impulse(50)
        response = sig.lfilter(b, a, imp)  
        ax2.stem(np.arange(0, 50), imp, use_line_collection=True)
        ax2.stem(np.arange(0, 50), response, use_line_collection=True)
        ax2.set_xlabel('n', color='blue')
        ax2.set_title("Time-Domain Filter")
        ax2.set_facecolor('#F0F0F0')
        ax2.grid(True)         
        
        ax3 = figure.add_subplot(2,2,3)
        ax3.plot(w, 20*np.log10(abs(h)), linewidth=3)
        ax3.set_ylabel('Decible')
        ax3.set_xlabel('Hz')
        ax3.set_title("Frequency Response of Filter")
        ax3.set_facecolor('#F0F0F0')
        ax3.grid(True)         

        ax4 = figure.add_subplot(2,2,4)
        ax4.plot(t, signal_out, linewidth=2.0, color='red')
        ax4.set_ylabel('Amplitude', color='blue')
        ax4.set_xlabel('Time (second)', color='blue')
        ax4.set_title("Filtered Output")
        ax4.set_facecolor('#F0F0F0')
        ax4.grid(True)  
        
        figure.tight_layout()
        canvas.draw() 


#form_butter_lowpass.py
import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import scipy.signal as sig
from filter_utils import Filter_Utils
from form1 import Form1

class Form_Butter_LowPass:
    def __init__(self, window):
        self.window = window
        width = 1520
        height = 760
        self.window.geometry(f"{width}x{height}")
        
        #Adds label widgets
        self.add_labels(self.window)
        
        #Adds canvasses
        self.add_canvas(self.window)
        
        #Adds entry widgets
        self.add_entries(self.window)
        
        #Adds listbox widget
        self.add_listbox(self.window)

        #Binds events
        self.binds_event()
        
        #Creates neccesary objects
        self.filter_utils = Filter_Utils()       
        
    def add_labels(self, master):
        # Create labels
        self.label1 = tk.Label(master, text="SAMPLING FREQUENCY")
        self.label1.grid(row=0, column=0, padx=5, pady=0.1, sticky="w")

        self.label2 = tk.Label(master, text="TIME PERIODE")
        self.label2.grid(row=2, column=0, padx=5, pady=0.1, sticky="nw")

        self.label3 = tk.Label(master, text="FILTER ORDER")
        self.label3.grid(row=4, column=0, padx=5, pady=0.1, sticky="nw")

        self.label4 = tk.Label(master, text="CUT-OFF FREQUENCY")
        self.label4.grid(row=6, column=0, padx=5, pady=0.1, sticky="nw") 

        self.label5 = tk.Label(master, text="NOISE AMPLITUDE")
        self.label5.grid(row=8, column=0, padx=5, pady=0.1, sticky="nw")  
        
        self.label6 = tk.Label(master, text="CHOOSE SIGNALS")
        self.label6.grid(row=10, column=0, padx=5, pady=0.1, sticky="nw")   
        
    def add_entries(self, master):
        # Create entry widgets
        self.entry_fs = tk.Entry(master, width=20, bg="lightblue")
        self.entry_fs.grid(row=1, column=0, padx=5, pady=0.1, sticky="nw")  
        self.entry_fs.insert(0, "1000")
        self.entry_fs.bind('<Return>', self.choose_list_widget)

        self.entry_periode = tk.Entry(master, width=20, bg="lightblue")
        self.entry_periode.grid(row=3, column=0, padx=5, pady=0.1, sticky="nw") 
        self.entry_periode.insert(0, "1")
        self.entry_periode.bind('<Return>', self.choose_list_widget)

        self.entry_filt_ord = tk.Entry(master, width=20, bg="lightblue")
        self.entry_filt_ord.grid(row=5, column=0, padx=5, pady=0.1, sticky="nw") 
        self.entry_filt_ord.insert(0, "3")
        self.entry_filt_ord.bind('<Return>', self.choose_list_widget)

        self.entry_cutoff = tk.Entry(master, width=20, bg="lightblue")
        self.entry_cutoff.grid(row=7, column=0, padx=5, pady=0.1, sticky="nw") 
        self.entry_cutoff.insert(0, "100")
        self.entry_cutoff.bind('<Return>', self.choose_list_widget)

        self.entry_noise = tk.Entry(master, width=20, bg="lightblue")
        self.entry_noise.grid(row=9, column=0, padx=5, pady=0.1, sticky="nw") 
        self.entry_noise.insert(0, "0.1")
        self.entry_noise.bind('<Return>', self.choose_list_widget)
        
    def add_canvas(self, master):    
        # Create a frame for canvas1 with a border
        frame1 = ttk.Frame(master, borderwidth=3, relief="groove")
        frame1.grid(row=0, column=1, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n")

        # Adds canvas1 widget to frame1
        self.figure1 = Figure(figsize=(13.2, 7.4), dpi=100)
        self.figure1.patch.set_facecolor('#F0F0F0')
        self.canvas1 = FigureCanvasTkAgg(self.figure1, master=frame1)
        self.canvas1.get_tk_widget().pack(fill=tk.BOTH, expand=True)

    def add_listbox(self, root):
        #Menambahkan listbox widget
        self.listbox = tk.Listbox(root, selectmode=tk.SINGLE, width=25)
        self.listbox.grid(row=11, column=0, sticky='nw', padx=1, pady=1)

        # Menyisipkan item ke dalam list widget
        items = ["Noisy Sinusoidal", 
                 "Noisy Square Wave", 
                 "Noisy Amplitude Modulation Signal", 
                 "Noisy Frequency Modulation Signal", 
                 "Noisy Phase Modulation Signal", 
                 "Noisy ASK Modulation Signal", 
                 "Noisy FSK Modulation Signal",
                 "Noisy PSK Modulation Signal"]
        for item in items:
            self.listbox.insert(tk.END, item)

        self.listbox.config(height=len(items)) 

    def binds_event(self):
        #Binds listbox to choose_list_widget() function
        self.listbox.bind("<<ListboxSelect>>", self.choose_list_widget)
        
    def read_and_check_input(self, fs, T, filt_ord, cutoff, amp):             
        try:
            fsampling = float(fs)
        except ValueError:
            fsampling = 1000
            self.entry_fs.delete(0, tk.END)
            self.entry_fs.insert(0, "1000")

        try:
            periode = float(T)
        except ValueError:
            periode = 1
            self.entry_periode.delete(0, tk.END)
            self.entry_periode.insert(0, "1")

        try:
            filter_order = float(filt_ord)
        except ValueError:
            filter_order = 3
            self.entry_filt_ord.delete(0, tk.END)
            self.entry_filt_ord.insert(0, "3")

        try:
            cutoff_freq = float(cutoff)
        except ValueError:
            cutoff_freq = 100
            self.entry_cutoff.delete(0, tk.END)
            self.entry_cutoff.insert(0, "100")            

        try:
            noise_amp = float(amp)
        except ValueError:
            noise_amp = 0.1
            self.entry_noise.delete(0, tk.END)
            self.entry_noise.insert(0, "0.1")
            
        return fsampling, periode, filter_order, cutoff_freq, noise_amp
    
    def choose_list_widget(self, event):
        chosen = self.listbox.get(self.listbox.curselection())

        #Reads and checks params
        fsampling = self.entry_fs.get()
        periode = self.entry_periode.get()
        filter_ord = self.entry_filt_ord.get()
        cutoff_freq = self.entry_cutoff.get()
        amp = self.entry_noise.get()
        
        Fs, T, filt_order, cutoff, noise_amp = self.read_and_check_input(fsampling, periode, 
                    filter_ord, cutoff_freq, amp)        
        
        
        if chosen == "Noisy Sinusoidal":
            freq_sinus = 10
            t, y = self.filter_utils.generate_noisy_sinusoidal(T, freq_sinus, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_lowpass(y, filt_order, cutoff, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                f"Noisy Sinusoidal Signal, Freq={freq_sinus}, Noise Amp={noise_amp}", 
                signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy Square Wave":
            samples_per_bit = 50
            t, y = self.filter_utils.generate_noisy_square(T, Fs, samples_per_bit, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_lowpass(y, filt_order, cutoff, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy Square Signal, Samples Per Bit={samples_per_bit}, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)


        if chosen == "Noisy Amplitude Modulation Signal":
            t, y = self.filter_utils.generate_noisy_amp_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_lowpass(y, filt_order, cutoff, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy Amplitude Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy Frequency Modulation Signal":
            t, y = self.filter_utils.generate_noisy_freq_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_lowpass(y, filt_order, cutoff, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy Frequency Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy Phase Modulation Signal":
            t, y = self.filter_utils.generate_noisy_phase_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_lowpass(y, filt_order, cutoff, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy Phase Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy ASK Modulation Signal":
            t, y = self.filter_utils.generate_noisy_ask_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_lowpass(y, filt_order, cutoff, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy ASK Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy FSK Modulation Signal":
            t, y = self.filter_utils.generate_noisy_fsk_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_lowpass(y, filt_order, cutoff, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy FSK Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy PSK Modulation Signal":
            t, y = self.filter_utils.generate_noisy_psk_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_lowpass(y, filt_order, cutoff, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy PSK Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)
            
if __name__ == "__main__":
    window = tk.Tk()
    Form_Butter_LowPass(window)
    window.mainloop()

DOWNLOAD FULL SOURCE CODE VERSION 11.0


BUTTERWORTH BANDPASS FILTERING:


#form_butter_bandpass.py
import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import scipy.signal as sig
from filter_utils import Filter_Utils
from form1 import Form1

class Form_Butter_BandPass:
    def __init__(self, window):
        self.window = window
        width = 1520
        height = 760
        self.window.geometry(f"{width}x{height}")
        
        #Adds label widgets
        self.add_labels(self.window)
        
        #Adds canvasses
        self.add_canvas(self.window)
        
        #Adds entry widgets
        self.add_entries(self.window)
        
        #Adds listbox widget
        self.add_listbox(self.window)

        #Binds events
        self.binds_event()
        
        #Creates neccesary objects
        self.filter_utils = Filter_Utils()       
        
    def add_labels(self, master):
        # Create labels
        self.label1 = tk.Label(master, text="SAMPLING FREQUENCY")
        self.label1.grid(row=0, column=0, padx=5, pady=0.1, sticky="w")

        self.label2 = tk.Label(master, text="TIME PERIODE")
        self.label2.grid(row=2, column=0, padx=5, pady=0.1, sticky="nw")

        self.label3 = tk.Label(master, text="FILTER ORDER")
        self.label3.grid(row=4, column=0, padx=5, pady=0.1, sticky="nw")

        self.label4 = tk.Label(master, text="CUT-OFF FREQUENCY 1")
        self.label4.grid(row=6, column=0, padx=5, pady=0.1, sticky="nw") 

        self.label5 = tk.Label(master, text="CUT-OFF FREQUENCY 2")
        self.label5.grid(row=8, column=0, padx=5, pady=0.1, sticky="nw") 
        
        self.label6 = tk.Label(master, text="NOISE AMPLITUDE")
        self.label6.grid(row=10, column=0, padx=5, pady=0.1, sticky="nw")  
        
        self.label7 = tk.Label(master, text="CHOOSE SIGNALS")
        self.label7.grid(row=12, column=0, padx=5, pady=0.1, sticky="nw")   
        
    def add_entries(self, master):
        # Create entry widgets
        self.entry_fs = tk.Entry(master, width=20, bg="lightblue")
        self.entry_fs.grid(row=1, column=0, padx=5, pady=0.1, sticky="nw")  
        self.entry_fs.insert(0, "1000")
        self.entry_fs.bind('<Return>', self.choose_list_widget)

        self.entry_periode = tk.Entry(master, width=20, bg="lightblue")
        self.entry_periode.grid(row=3, column=0, padx=5, pady=0.1, sticky="nw") 
        self.entry_periode.insert(0, "1")
        self.entry_periode.bind('<Return>', self.choose_list_widget)

        self.entry_filt_ord = tk.Entry(master, width=20, bg="lightblue")
        self.entry_filt_ord.grid(row=5, column=0, padx=5, pady=0.1, sticky="nw") 
        self.entry_filt_ord.insert(0, "3")
        self.entry_filt_ord.bind('<Return>', self.choose_list_widget)

        self.entry_cutoff1 = tk.Entry(master, width=20, bg="lightblue")
        self.entry_cutoff1.grid(row=7, column=0, padx=5, pady=0.1, sticky="nw") 
        self.entry_cutoff1.insert(0, "100")
        self.entry_cutoff1.bind('<Return>', self.choose_list_widget)

        self.entry_cutoff2 = tk.Entry(master, width=20, bg="lightblue")
        self.entry_cutoff2.grid(row=9, column=0, padx=5, pady=0.1, sticky="nw") 
        self.entry_cutoff2.insert(0, "300")
        self.entry_cutoff2.bind('<Return>', self.choose_list_widget)
        
        self.entry_noise = tk.Entry(master, width=20, bg="lightblue")
        self.entry_noise.grid(row=11, column=0, padx=5, pady=0.1, sticky="nw") 
        self.entry_noise.insert(0, "0.1")
        self.entry_noise.bind('<Return>', self.choose_list_widget)
        
    def add_canvas(self, master):    
        # Create a frame for canvas1 with a border
        frame1 = ttk.Frame(master, borderwidth=3, relief="groove")
        frame1.grid(row=0, column=1, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n")

        # Adds canvas1 widget to frame1
        self.figure1 = Figure(figsize=(13.2, 7.4), dpi=100)
        self.figure1.patch.set_facecolor('#F0F0F0')
        self.canvas1 = FigureCanvasTkAgg(self.figure1, master=frame1)
        self.canvas1.get_tk_widget().pack(fill=tk.BOTH, expand=True)

    def add_listbox(self, root):
        #Menambahkan listbox widget
        self.listbox = tk.Listbox(root, selectmode=tk.SINGLE, width=25)
        self.listbox.grid(row=13, column=0, sticky='nw', padx=1, pady=1)

        # Menyisipkan item ke dalam list widget
        items = ["Noisy Sinusoidal", 
                 "Noisy Square Wave", 
                 "Noisy Amplitude Modulation Signal", 
                 "Noisy Frequency Modulation Signal", 
                 "Noisy Phase Modulation Signal", 
                 "Noisy ASK Modulation Signal", 
                 "Noisy FSK Modulation Signal",
                 "Noisy PSK Modulation Signal"]
        for item in items:
            self.listbox.insert(tk.END, item)

        self.listbox.config(height=len(items)) 

    def binds_event(self):
        #Binds listbox to choose_list_widget() function
        self.listbox.bind("<<ListboxSelect>>", self.choose_list_widget)
        
    def read_and_check_input(self, fs, T, filt_ord, cutoff1, cutoff2, amp):             
        try:
            fsampling = float(fs)
        except ValueError:
            fsampling = 1000
            self.entry_fs.delete(0, tk.END)
            self.entry_fs.insert(0, "1000")

        try:
            periode = float(T)
        except ValueError:
            periode = 1
            self.entry_periode.delete(0, tk.END)
            self.entry_periode.insert(0, "1")

        try:
            filter_order = float(filt_ord)
        except ValueError:
            filter_order = 3
            self.entry_filt_ord.delete(0, tk.END)
            self.entry_filt_ord.insert(0, "3")

        try:
            cutoff_freq1 = float(cutoff1)
        except ValueError:
            cutoff_freq1 = 100
            self.entry_cutoff1.delete(0, tk.END)
            self.entry_cutoff1.insert(0, "100")            

        try:
            cutoff_freq2 = float(cutoff2)
        except ValueError:
            cutoff_freq2 = 300
            self.entry_cutoff2.delete(0, tk.END)
            self.entry_cutoff2.insert(0, "300") 
            
        try:
            noise_amp = float(amp)
        except ValueError:
            noise_amp = 0.1
            self.entry_noise.delete(0, tk.END)
            self.entry_noise.insert(0, "0.1")
            
        return fsampling, periode, filter_order, cutoff_freq1, cutoff_freq2, noise_amp
    
    def choose_list_widget(self, event):
        chosen = self.listbox.get(self.listbox.curselection())

        #Reads and checks params
        fsampling = self.entry_fs.get()
        periode = self.entry_periode.get()
        filter_ord = self.entry_filt_ord.get()
        cutoff_freq1 = self.entry_cutoff1.get()
        cutoff_freq2 = self.entry_cutoff2.get()
        amp = self.entry_noise.get()
        
        Fs, T, filt_order, cutoff1, cutoff2, noise_amp = self.read_and_check_input(fsampling, periode, 
                    filter_ord, cutoff_freq1, cutoff_freq2, amp) 
        
        if chosen == "Noisy Sinusoidal":
            freq_sinus = 10
            t, y = self.filter_utils.generate_noisy_sinusoidal(T, freq_sinus, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_bandpass(y, filt_order, cutoff1, cutoff2, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy Sinusoidal Signal, Freq={freq_sinus}, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy Square Wave":
            samples_per_bit = 50
            t, y = self.filter_utils.generate_noisy_square(T, Fs, samples_per_bit, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_bandpass(y, filt_order, cutoff1, cutoff2, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy Square Signal, Samples Per Bit={samples_per_bit}, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)


        if chosen == "Noisy Amplitude Modulation Signal":
            t, y = self.filter_utils.generate_noisy_amp_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_bandpass(y, filt_order, cutoff1, cutoff2, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy Amplitude Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy Frequency Modulation Signal":
            t, y = self.filter_utils.generate_noisy_freq_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_bandpass(y, filt_order, cutoff1, cutoff2, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy Frequency Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy Phase Modulation Signal":
            t, y = self.filter_utils.generate_noisy_phase_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_bandpass(y, filt_order, cutoff1, cutoff2, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy Phase Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy ASK Modulation Signal":
            t, y = self.filter_utils.generate_noisy_ask_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_bandpass(y, filt_order, cutoff1, cutoff2, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy ASK Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy FSK Modulation Signal":
            t, y = self.filter_utils.generate_noisy_fsk_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_bandpass(y, filt_order, cutoff1, cutoff2, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy FSK Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy PSK Modulation Signal":
            t, y = self.filter_utils.generate_noisy_psk_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_bandpass(y, filt_order, cutoff1, cutoff2, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy PSK Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)            
        
if __name__ == "__main__":
    window = tk.Tk()
    Form_Butter_BandPass(window)
    window.mainloop()

DOWNLOAD FULL SOURCE CODE VERSION 11.0


BUTTERWORTH HIGHPASS FILTERING:


    def butterworth_highpass(self, signal_in, N, highcut, Fs):
        nyqs=0.5*Fs
        high= highcut/nyqs
        # b is the numerator of the filter & a is the denominator
        b, a = sig.butter(N, high, 'highpass', analog=False)
        
        # w is the freq in z-domain & h is the magnitude in z-domain
        w, h = sig.freqz(b, a, fs=Fs, worN=2000)

        signal_out = sig.filtfilt(b, a, signal_in, axis=0)
        
        return signal_out, b, a, w, h


#form_butter_highpass.py
import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import scipy.signal as sig
from filter_utils import Filter_Utils
from form1 import Form1

class Form_Butter_HighPass:
    def __init__(self, window):
        self.window = window
        width = 1520
        height = 760
        self.window.geometry(f"{width}x{height}")
        
        #Adds label widgets
        self.add_labels(self.window)
        
        #Adds canvasses
        self.add_canvas(self.window)
        
        #Adds entry widgets
        self.add_entries(self.window)
        
        #Adds listbox widget
        self.add_listbox(self.window)

        #Binds events
        self.binds_event()
        
        #Creates neccesary objects
        self.filter_utils = Filter_Utils()       
        
    def add_labels(self, master):
        # Create labels
        self.label1 = tk.Label(master, text="SAMPLING FREQUENCY")
        self.label1.grid(row=0, column=0, padx=5, pady=0.1, sticky="w")

        self.label2 = tk.Label(master, text="TIME PERIODE")
        self.label2.grid(row=2, column=0, padx=5, pady=0.1, sticky="nw")

        self.label3 = tk.Label(master, text="FILTER ORDER")
        self.label3.grid(row=4, column=0, padx=5, pady=0.1, sticky="nw")

        self.label4 = tk.Label(master, text="CUT-OFF FREQUENCY")
        self.label4.grid(row=6, column=0, padx=5, pady=0.1, sticky="nw") 

        self.label5 = tk.Label(master, text="NOISE AMPLITUDE")
        self.label5.grid(row=8, column=0, padx=5, pady=0.1, sticky="nw")  
        
        self.label6 = tk.Label(master, text="CHOOSE SIGNALS")
        self.label6.grid(row=10, column=0, padx=5, pady=0.1, sticky="nw")   
        
    def add_entries(self, master):
        # Create entry widgets
        self.entry_fs = tk.Entry(master, width=20, bg="lightblue")
        self.entry_fs.grid(row=1, column=0, padx=5, pady=0.1, sticky="nw")  
        self.entry_fs.insert(0, "1000")
        self.entry_fs.bind('<Return>', self.choose_list_widget)

        self.entry_periode = tk.Entry(master, width=20, bg="lightblue")
        self.entry_periode.grid(row=3, column=0, padx=5, pady=0.1, sticky="nw") 
        self.entry_periode.insert(0, "1")
        self.entry_periode.bind('<Return>', self.choose_list_widget)

        self.entry_filt_ord = tk.Entry(master, width=20, bg="lightblue")
        self.entry_filt_ord.grid(row=5, column=0, padx=5, pady=0.1, sticky="nw") 
        self.entry_filt_ord.insert(0, "3")
        self.entry_filt_ord.bind('<Return>', self.choose_list_widget)

        self.entry_cutoff = tk.Entry(master, width=20, bg="lightblue")
        self.entry_cutoff.grid(row=7, column=0, padx=5, pady=0.1, sticky="nw") 
        self.entry_cutoff.insert(0, "300")
        self.entry_cutoff.bind('<Return>', self.choose_list_widget)

        self.entry_noise = tk.Entry(master, width=20, bg="lightblue")
        self.entry_noise.grid(row=9, column=0, padx=5, pady=0.1, sticky="nw") 
        self.entry_noise.insert(0, "0.1")
        self.entry_noise.bind('<Return>', self.choose_list_widget)
        
    def add_canvas(self, master):    
        # Create a frame for canvas1 with a border
        frame1 = ttk.Frame(master, borderwidth=3, relief="groove")
        frame1.grid(row=0, column=1, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n")

        # Adds canvas1 widget to frame1
        self.figure1 = Figure(figsize=(13.2, 7.4), dpi=100)
        self.figure1.patch.set_facecolor('#F0F0F0')
        self.canvas1 = FigureCanvasTkAgg(self.figure1, master=frame1)
        self.canvas1.get_tk_widget().pack(fill=tk.BOTH, expand=True)

    def add_listbox(self, root):
        #Menambahkan listbox widget
        self.listbox = tk.Listbox(root, selectmode=tk.SINGLE, width=25)
        self.listbox.grid(row=11, column=0, sticky='nw', padx=1, pady=1)

        # Menyisipkan item ke dalam list widget
        items = ["Noisy Sinusoidal", 
                 "Noisy Square Wave", 
                 "Noisy Amplitude Modulation Signal", 
                 "Noisy Frequency Modulation Signal", 
                 "Noisy Phase Modulation Signal", 
                 "Noisy ASK Modulation Signal", 
                 "Noisy FSK Modulation Signal",
                 "Noisy PSK Modulation Signal"]
        for item in items:
            self.listbox.insert(tk.END, item)

        self.listbox.config(height=len(items)) 

    def binds_event(self):
        #Binds listbox to choose_list_widget() function
        self.listbox.bind("<<ListboxSelect>>", self.choose_list_widget)
        
    def read_and_check_input(self, fs, T, filt_ord, cutoff, amp):             
        try:
            fsampling = float(fs)
        except ValueError:
            fsampling = 1000
            self.entry_fs.delete(0, tk.END)
            self.entry_fs.insert(0, "1000")

        try:
            periode = float(T)
        except ValueError:
            periode = 1
            self.entry_periode.delete(0, tk.END)
            self.entry_periode.insert(0, "1")

        try:
            filter_order = float(filt_ord)
        except ValueError:
            filter_order = 3
            self.entry_filt_ord.delete(0, tk.END)
            self.entry_filt_ord.insert(0, "3")

        try:
            cutoff_freq = float(cutoff)
        except ValueError:
            cutoff_freq = 300
            self.entry_cutoff.delete(0, tk.END)
            self.entry_cutoff.insert(0, "300")            

        try:
            noise_amp = float(amp)
        except ValueError:
            noise_amp = 0.1
            self.entry_noise.delete(0, tk.END)
            self.entry_noise.insert(0, "0.1")
            
        return fsampling, periode, filter_order, cutoff_freq, noise_amp
    
    def choose_list_widget(self, event):
        chosen = self.listbox.get(self.listbox.curselection())

        #Reads and checks params
        fsampling = self.entry_fs.get()
        periode = self.entry_periode.get()
        filter_ord = self.entry_filt_ord.get()
        cutoff_freq = self.entry_cutoff.get()
        amp = self.entry_noise.get()
        
        Fs, T, filt_order, cutoff, noise_amp = self.read_and_check_input(fsampling, periode, 
                    filter_ord, cutoff_freq, amp)        
                
        if chosen == "Noisy Sinusoidal":
            freq_sinus = 10
            t, y = self.filter_utils.generate_noisy_sinusoidal(T, freq_sinus, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_highpass(y, filt_order, cutoff, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                f"Noisy Sinusoidal Signal, Freq={freq_sinus}, Noise Amp={noise_amp}", 
                signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy Square Wave":
            samples_per_bit = 50
            t, y = self.filter_utils.generate_noisy_square(T, Fs, samples_per_bit, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_highpass(y, filt_order, cutoff, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy Square Signal, Samples Per Bit={samples_per_bit}, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)


        if chosen == "Noisy Amplitude Modulation Signal":
            t, y = self.filter_utils.generate_noisy_amp_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_highpass(y, filt_order, cutoff, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy Amplitude Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy Frequency Modulation Signal":
            t, y = self.filter_utils.generate_noisy_freq_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_highpass(y, filt_order, cutoff, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy Frequency Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy Phase Modulation Signal":
            t, y = self.filter_utils.generate_noisy_phase_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_highpass(y, filt_order, cutoff, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy Phase Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy ASK Modulation Signal":
            t, y = self.filter_utils.generate_noisy_ask_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_highpass(y, filt_order, cutoff, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy ASK Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy FSK Modulation Signal":
            t, y = self.filter_utils.generate_noisy_fsk_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_highpass(y, filt_order, cutoff, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy FSK Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy PSK Modulation Signal":
            t, y = self.filter_utils.generate_noisy_psk_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_highpass(y, filt_order, cutoff, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy PSK Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)
            
if __name__ == "__main__":
    window = tk.Tk()
    Form_Butter_HighPass(window)
    window.mainloop()


DOWNLOAD FULL SOURCE CODE VERSION 12.0


BUTTERWORTH BANDSTOP FILTERING:



#filter_utils.py
import matplotlib.pyplot as plt
import numpy as np 
import scipy.signal as sig
from am_utils import AM_Utils
from fm_utils import FM_Utils
from pm_utils import PM_Utils
from ask_utils import ASK_Utils
from fsk_utils import FSK_Utils
from psk_utils import PSK_Utils

class Filter_Utils:
    def __init__(self):
        self.am_utils = AM_Utils()
        self.fm_utils = FM_Utils()
        self.pm_utils = PM_Utils()
        self.ask_utils = ASK_Utils()
        self.fsk_utils = FSK_Utils()
        self.psk_utils = PSK_Utils()
        
    def generate_noisy_sinusoidal(self, T, F, Fs, noise_amplitude):
        # Defines time line
        t = np.arange(0, T, 1/Fs)
        signal = np.sin(2*np.pi*F*t)
        
        # Generate random noise
        noise = noise_amplitude * np.random.randn(len(t))
        y = signal + noise
        return t, y

    def generate_random_binary_array(self, length):
        # Generate a random binary array of specified length
        return np.random.randint(2, size=length)
    
    def generate_noisy_square(self, T, Fs, samples_per_bit, noise_amplitude):
        # Defines time line
        t = np.arange(0, T, 1/Fs)
        
        bit_arr_size = int(2*Fs/samples_per_bit)
        bit_arr = self.generate_random_binary_array(bit_arr_size)
        
        square_signal = np.repeat(bit_arr, samples_per_bit)[:len(t)]

       # Ensures the lengths of square_signal and t match
        if len(square_signal) < len(t):
            square_signal = np.pad(square_signal, (0, len(t) - len(square_signal)))

        # Generate random noise
        noise = noise_amplitude * np.random.randn(len(t))
        y = square_signal + noise
        
        return t, y

    def generate_noisy_amp_modulation(self, T, Fs, noise_amplitude):        
        t, carrier_wave, modulating_wave, am_signal = self.am_utils.calculate_amplitude_modulation(Fs, T, 1, 25, 1, 5)

        # Generate random noise
        noise = noise_amplitude * np.random.randn(len(t))
        y = am_signal + noise
        
        return t, y

    def generate_noisy_freq_modulation(self, T, Fs, noise_amplitude):        
        t, carrier_wave, modulating_wave, fm_signal = self.fm_utils.calculate_frequency_modulation(2, Fs, T, 1, 25, 1, 5)

        # Generate random noise
        noise = noise_amplitude * np.random.randn(len(t))
        y = fm_signal + noise
        
        return t, y

    def generate_noisy_phase_modulation(self, T, Fs, noise_amplitude):        
        t, carrier_wave, modulating_wave, am_signal = self.pm_utils.calculate_phase_modulation(Fs, T, 1, 15, 0, 1, 5, 0)

        # Generate random noise
        noise = noise_amplitude * np.random.randn(len(t))
        y = am_signal + noise
        
        return t, y

    def generate_noisy_ask_modulation(self, T, Fs, noise_amplitude):        
        t, carrier_wave, modulating_wave, ask_signal = self.ask_utils.calculate_ask_modulation(Fs, T, 1, 15, 0, 50)

        # Generate random noise
        noise = noise_amplitude * np.random.randn(len(t))
        y = ask_signal + noise
        
        return t, y

    def generate_noisy_fsk_modulation(self, T, Fs, noise_amplitude):        
        t, carrier_wave, modulating_wave, fsk_signal = self.fsk_utils.calculate_fsk_modulation(Fs, T, 1, 15, 0, 50)

        # Generate random noise
        noise = noise_amplitude * np.random.randn(len(t))
        y = fsk_signal + noise
        
        return t, y

    def generate_noisy_psk_modulation(self, T, Fs, noise_amplitude):        
        t, carrier_wave, modulating_wave, psk_signal = self.psk_utils.calculate_psk_modulation(Fs, T, 1, 15, 0, 50)

        # Generate random noise
        noise = noise_amplitude * np.random.randn(len(t))
        y = psk_signal + noise
        
        return t, y
    
    def perform_convolution(self, t, signal_in, time_filter):
        # Performs convolution
        filtered_output = np.convolve(signal_in, time_filter, mode='same')

        # Create a time array with the same length as filtered_output
        t_filtered = t[:len(filtered_output)]  
        
        return t_filtered, filtered_output
        
    def plot_signal_filtering(self, t, signal_in, title1, time_filter, title2, figure, canvas):
        figure.clear()   

        ax1 = figure.add_subplot(2,2,1)
        ax1.plot(t, signal_in, linewidth=2.0, color='red')
        ax1.set_ylabel('Amplitude', color='blue')
        ax1.set_xlabel('Time (second)', color='blue')
        ax1.set_title(title1)
        ax1.set_facecolor('#F0F0F0')
        ax1.grid(True)   
        
        ax2 = figure.add_subplot(2,2,2)
        stem= ax2.stem(range(len(time_filter)), time_filter)
        stem[1].set_linewidth(3)
        ax2.set_xlabel('n', color='blue')
        ax2.set_title(title2)
        ax2.set_facecolor('#F0F0F0')
        ax2.grid(True)         
        
        ax3 = figure.add_subplot(2,2,3)
        w, v = sig.freqz(time_filter)
        ax3.plot(w, 20*np.log10(abs(v)), linewidth=3)
        ax3.set_ylabel('Decible')
        ax3.set_xlabel('Radians per second (0-π)')
        ax3.set_title("Frequency Response of Filter")
        ax3.set_facecolor('#F0F0F0')
        ax3.grid(True)         

        ax4 = figure.add_subplot(2,2,4)
        t_filtered, filtered_output = self.perform_convolution(t, signal_in, time_filter)
        ax4.plot(t_filtered, filtered_output, linewidth=2.0, color='red')
        ax4.set_ylabel('Amplitude', color='blue')
        ax4.set_xlabel('Time (second)', color='blue')
        ax4.set_title("Filtered Output")
        ax4.set_facecolor('#F0F0F0')
        ax4.grid(True)  
        
        figure.tight_layout()
        canvas.draw()          

    def butterworth_lowpass(self, signal_in, N, lowcut, Fs):
        nyqs=0.5*Fs
        low= lowcut/nyqs
        # b is the numerator of the filter & a is the denominator
        b, a = sig.butter(N, low, 'lowpass', analog=False)
        
        # w is the freq in z-domain & h is the magnitude in z-domain
        w, h = sig.freqz(b, a, fs=Fs, worN=2000)

        signal_out = sig.filtfilt(b, a, signal_in, axis=0)
        
        return signal_out, b, a, w, h

    def butterworth_bandpass(self, signal_in, order, lowcut, highcut, Fs):
        nyqs = 0.5* Fs
        low = lowcut / nyqs
        high = highcut/ nyqs
    
        # b is the numerator of the filter & a is the denominator
        b, a = sig.butter(order, [low, high], 'bandpass', analog=False)
        
        # w is the freq in z-domain & h is the magnitude in z-domain
        w, h = sig.freqz(b, a, fs=Fs, worN=2000)

        signal_out = sig.filtfilt(b, a, signal_in, axis=0)
        
        return signal_out, b, a, w, h

    def butterworth_highpass(self, signal_in, N, highcut, Fs):
        nyqs=0.5*Fs
        high= highcut/nyqs
        # b is the numerator of the filter & a is the denominator
        b, a = sig.butter(N, high, 'highpass', analog=False)
        
        # w is the freq in z-domain & h is the magnitude in z-domain
        w, h = sig.freqz(b, a, fs=Fs, worN=2000)

        signal_out = sig.filtfilt(b, a, signal_in, axis=0)
        
        return signal_out, b, a, w, h

    def butterworth_bandstop(self, signal_in, order, lowcut, highcut, Fs):
        nyqs = 0.5* Fs
        low = lowcut / nyqs
        high = highcut/ nyqs
    
        # b is the numerator of the filter & a is the denominator
        b, a = sig.butter(order, [low, high], 'bandstop', analog=False)
        
        # w is the freq in z-domain & h is the magnitude in z-domain
        w, h = sig.freqz(b, a, fs=Fs, worN=2000)

        signal_out = sig.filtfilt(b, a, signal_in, axis=0)
        
        return signal_out, b, a, w, h
    
    def plot_iir_filtering(self, t, signal_in, title1, signal_out, b, a, w, h, figure, canvas):
        figure.clear()   

        ax1 = figure.add_subplot(2,2,1)
        ax1.plot(t, signal_in, linewidth=2.0, color='red')
        ax1.set_ylabel('Amplitude', color='blue')
        ax1.set_xlabel('Time (second)', color='blue')
        ax1.set_title(title1)
        ax1.set_facecolor('#F0F0F0')
        ax1.grid(True)   
        
        ax2 = figure.add_subplot(2,2,2)
        imp = sig.unit_impulse(50)
        response = sig.lfilter(b, a, imp)  
        ax2.stem(np.arange(0, 50), imp, use_line_collection=True)
        ax2.stem(np.arange(0, 50), response, use_line_collection=True)
        ax2.set_xlabel('n', color='blue')
        ax2.set_title("Impulse Response of Filter")
        ax2.set_facecolor('#F0F0F0')
        ax2.grid(True)         
        
        ax3 = figure.add_subplot(2,2,3)
        ax3.plot(w, 20*np.log10(abs(h)), linewidth=3)
        ax3.set_ylabel('Decible')
        ax3.set_xlabel('Hz')
        ax3.set_title("Frequency Response of Filter")
        ax3.set_facecolor('#F0F0F0')
        ax3.grid(True)         

        ax4 = figure.add_subplot(2,2,4)
        ax4.plot(t, signal_out, linewidth=2.0, color='red')
        ax4.set_ylabel('Amplitude', color='blue')
        ax4.set_xlabel('Time (second)', color='blue')
        ax4.set_title("Filtered Output")
        ax4.set_facecolor('#F0F0F0')
        ax4.grid(True)  
        
        figure.tight_layout()
        canvas.draw() 


#form_butter_bandstop.py
import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import scipy.signal as sig
from filter_utils import Filter_Utils
from form1 import Form1

class Form_Butter_BandStop:
    def __init__(self, window):
        self.window = window
        width = 1520
        height = 760
        self.window.geometry(f"{width}x{height}")
        
        #Adds label widgets
        self.add_labels(self.window)
        
        #Adds canvasses
        self.add_canvas(self.window)
        
        #Adds entry widgets
        self.add_entries(self.window)
        
        #Adds listbox widget
        self.add_listbox(self.window)

        #Binds events
        self.binds_event()
        
        #Creates neccesary objects
        self.filter_utils = Filter_Utils()       
        
    def add_labels(self, master):
        # Create labels
        self.label1 = tk.Label(master, text="SAMPLING FREQUENCY")
        self.label1.grid(row=0, column=0, padx=5, pady=0.1, sticky="w")

        self.label2 = tk.Label(master, text="TIME PERIODE")
        self.label2.grid(row=2, column=0, padx=5, pady=0.1, sticky="nw")

        self.label3 = tk.Label(master, text="FILTER ORDER")
        self.label3.grid(row=4, column=0, padx=5, pady=0.1, sticky="nw")

        self.label4 = tk.Label(master, text="CUT-OFF FREQUENCY 1")
        self.label4.grid(row=6, column=0, padx=5, pady=0.1, sticky="nw") 

        self.label5 = tk.Label(master, text="CUT-OFF FREQUENCY 2")
        self.label5.grid(row=8, column=0, padx=5, pady=0.1, sticky="nw") 
        
        self.label6 = tk.Label(master, text="NOISE AMPLITUDE")
        self.label6.grid(row=10, column=0, padx=5, pady=0.1, sticky="nw")  
        
        self.label7 = tk.Label(master, text="CHOOSE SIGNALS")
        self.label7.grid(row=12, column=0, padx=5, pady=0.1, sticky="nw")   
        
    def add_entries(self, master):
        # Create entry widgets
        self.entry_fs = tk.Entry(master, width=20, bg="lightblue")
        self.entry_fs.grid(row=1, column=0, padx=5, pady=0.1, sticky="nw")  
        self.entry_fs.insert(0, "1000")
        self.entry_fs.bind('<Return>', self.choose_list_widget)

        self.entry_periode = tk.Entry(master, width=20, bg="lightblue")
        self.entry_periode.grid(row=3, column=0, padx=5, pady=0.1, sticky="nw") 
        self.entry_periode.insert(0, "1")
        self.entry_periode.bind('<Return>', self.choose_list_widget)

        self.entry_filt_ord = tk.Entry(master, width=20, bg="lightblue")
        self.entry_filt_ord.grid(row=5, column=0, padx=5, pady=0.1, sticky="nw") 
        self.entry_filt_ord.insert(0, "3")
        self.entry_filt_ord.bind('<Return>', self.choose_list_widget)

        self.entry_cutoff1 = tk.Entry(master, width=20, bg="lightblue")
        self.entry_cutoff1.grid(row=7, column=0, padx=5, pady=0.1, sticky="nw") 
        self.entry_cutoff1.insert(0, "100")
        self.entry_cutoff1.bind('<Return>', self.choose_list_widget)

        self.entry_cutoff2 = tk.Entry(master, width=20, bg="lightblue")
        self.entry_cutoff2.grid(row=9, column=0, padx=5, pady=0.1, sticky="nw") 
        self.entry_cutoff2.insert(0, "300")
        self.entry_cutoff2.bind('<Return>', self.choose_list_widget)
        
        self.entry_noise = tk.Entry(master, width=20, bg="lightblue")
        self.entry_noise.grid(row=11, column=0, padx=5, pady=0.1, sticky="nw") 
        self.entry_noise.insert(0, "0.1")
        self.entry_noise.bind('<Return>', self.choose_list_widget)
        
    def add_canvas(self, master):    
        # Create a frame for canvas1 with a border
        frame1 = ttk.Frame(master, borderwidth=3, relief="groove")
        frame1.grid(row=0, column=1, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n")

        # Adds canvas1 widget to frame1
        self.figure1 = Figure(figsize=(13.2, 7.4), dpi=100)
        self.figure1.patch.set_facecolor('#F0F0F0')
        self.canvas1 = FigureCanvasTkAgg(self.figure1, master=frame1)
        self.canvas1.get_tk_widget().pack(fill=tk.BOTH, expand=True)

    def add_listbox(self, root):
        #Menambahkan listbox widget
        self.listbox = tk.Listbox(root, selectmode=tk.SINGLE, width=25)
        self.listbox.grid(row=13, column=0, sticky='nw', padx=1, pady=1)

        # Menyisipkan item ke dalam list widget
        items = ["Noisy Sinusoidal", 
                 "Noisy Square Wave", 
                 "Noisy Amplitude Modulation Signal", 
                 "Noisy Frequency Modulation Signal", 
                 "Noisy Phase Modulation Signal", 
                 "Noisy ASK Modulation Signal", 
                 "Noisy FSK Modulation Signal",
                 "Noisy PSK Modulation Signal"]
        for item in items:
            self.listbox.insert(tk.END, item)

        self.listbox.config(height=len(items)) 

    def binds_event(self):
        #Binds listbox to choose_list_widget() function
        self.listbox.bind("<<ListboxSelect>>", self.choose_list_widget)
        
    def read_and_check_input(self, fs, T, filt_ord, cutoff1, cutoff2, amp):             
        try:
            fsampling = float(fs)
        except ValueError:
            fsampling = 1000
            self.entry_fs.delete(0, tk.END)
            self.entry_fs.insert(0, "1000")

        try:
            periode = float(T)
        except ValueError:
            periode = 1
            self.entry_periode.delete(0, tk.END)
            self.entry_periode.insert(0, "1")

        try:
            filter_order = float(filt_ord)
        except ValueError:
            filter_order = 3
            self.entry_filt_ord.delete(0, tk.END)
            self.entry_filt_ord.insert(0, "3")

        try:
            cutoff_freq1 = float(cutoff1)
        except ValueError:
            cutoff_freq1 = 100
            self.entry_cutoff1.delete(0, tk.END)
            self.entry_cutoff1.insert(0, "100")            

        try:
            cutoff_freq2 = float(cutoff2)
        except ValueError:
            cutoff_freq2 = 300
            self.entry_cutoff2.delete(0, tk.END)
            self.entry_cutoff2.insert(0, "300") 
            
        try:
            noise_amp = float(amp)
        except ValueError:
            noise_amp = 0.1
            self.entry_noise.delete(0, tk.END)
            self.entry_noise.insert(0, "0.1")
            
        return fsampling, periode, filter_order, cutoff_freq1, cutoff_freq2, noise_amp
    
    def choose_list_widget(self, event):
        chosen = self.listbox.get(self.listbox.curselection())

        #Reads and checks params
        fsampling = self.entry_fs.get()
        periode = self.entry_periode.get()
        filter_ord = self.entry_filt_ord.get()
        cutoff_freq1 = self.entry_cutoff1.get()
        cutoff_freq2 = self.entry_cutoff2.get()
        amp = self.entry_noise.get()
        
        Fs, T, filt_order, cutoff1, cutoff2, noise_amp = self.read_and_check_input(fsampling, periode, 
                    filter_ord, cutoff_freq1, cutoff_freq2, amp) 
        
        if chosen == "Noisy Sinusoidal":
            freq_sinus = 50
            t, y = self.filter_utils.generate_noisy_sinusoidal(T, freq_sinus, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_bandstop(y, filt_order, cutoff1, cutoff2, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy Sinusoidal Signal, Freq={freq_sinus}, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy Square Wave":
            samples_per_bit = 50
            t, y = self.filter_utils.generate_noisy_square(T, Fs, samples_per_bit, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_bandstop(y, filt_order, cutoff1, cutoff2, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy Square Signal, Samples Per Bit={samples_per_bit}, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)


        if chosen == "Noisy Amplitude Modulation Signal":
            t, y = self.filter_utils.generate_noisy_amp_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_bandstop(y, filt_order, cutoff1, cutoff2, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy Amplitude Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy Frequency Modulation Signal":
            t, y = self.filter_utils.generate_noisy_freq_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_bandstop(y, filt_order, cutoff1, cutoff2, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy Frequency Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy Phase Modulation Signal":
            t, y = self.filter_utils.generate_noisy_phase_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_bandstop(y, filt_order, cutoff1, cutoff2, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy Phase Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy ASK Modulation Signal":
            t, y = self.filter_utils.generate_noisy_ask_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_bandstop(y, filt_order, cutoff1, cutoff2, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy ASK Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy FSK Modulation Signal":
            t, y = self.filter_utils.generate_noisy_fsk_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_bandstop(y, filt_order, cutoff1, cutoff2, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy FSK Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)

        if chosen == "Noisy PSK Modulation Signal":
            t, y = self.filter_utils.generate_noisy_psk_modulation(T, Fs, noise_amp)
            signal_out, b, a, w, h = self.filter_utils.butterworth_bandstop(y, filt_order, cutoff1, cutoff2, Fs)
            self.filter_utils.plot_iir_filtering(t, y, 
                    f"Noisy PSK Modulation Signal, Noise Amp={noise_amp}", 
                   signal_out, b, a, w, h, self.figure1, self.canvas1)            
        
if __name__ == "__main__":
    window = tk.Tk()
    Form_Butter_BandStop(window)
    window.mainloop()

DOWNLOAD FULL SOURCE CODE VERSION 13.0




























No comments:

Post a Comment