Sunday, September 24, 2023

START FROM SCRATCH SIGNAL AND IMAGE PROCESSING WITH TKINTER --- VIVIAN SIAHAAN

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

SEMANGAT BELAJAR dan HORAS!!!


BALIGE CITY, NORTH SUMATERA


SUPPORT OUR YOUTUBE CHANNEL BY SUBSCRIBING:






FULL SOURCE CODE VERSION 1.0

#main_program.py
import tkinter as tk
from main_form import Main_Form
from plot_utils import Plot_Utils

class Main_Program():
    def __init__(self, root):
        self.initialize()

    def initialize(self):
        self.root = root
        width = 1560
        height = 450
        self.root.geometry(f"{width}x{height}")
        self.root.title("START FROM FROM SCRATCH SIGNAL AND IMAGE PROCESSING WITH TKINTER")

        #Creates necessary objects
        self.obj_main_form = Main_Form()
        self.obj_plot_utils = Plot_Utils()
        
        #Places widgets in root
        self.obj_main_form.add_widgets(self.root)  

        #Binds events
        self.binds_event()
                
    def binds_event(self):
        self.obj_plot_utils.binds_simple_sinusoidal(self.obj_main_form)
         
if __name__ == "__main__":
    root = tk.Tk()
    app = Main_Program(root)
    root.mainloop()

#main_form.py
import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

class Main_Form:
    def add_widgets(self, root):        
        #Adds menu
        self.add_menu(root)

        #Adds canvasses
        self.add_canvas(root)

    def add_menu(self, root):
        self.menu_bar = tk.Menu(root)
        
        #Creates a Dataset menu
        self.sinusoidal_menu = tk.Menu(self.menu_bar, tearoff=0)
        self.sinusoidal_menu.add_command(label="Simple Sinusoidal")
        self.sinusoidal_menu.add_command(label="Two Sinusoidals")
        self.sinusoidal_menu.add_command(label="Simple Sinusoidal 3")
        self.sinusoidal_menu.add_command(label="Simple Sinusoidal 4")
        self.sinusoidal_menu.add_command(label="Simple Sinusoidal 5")        
        self.menu_bar.add_cascade(label="Sinusoidal Signals", menu=self.sinusoidal_menu)      
        
        root.config(menu=self.menu_bar)    

    def add_canvas(self, root):
        #Menambahkan canvas1 widget pada root untuk menampilkan hasil
        self.figure1 = Figure(figsize=(15.2, 4.2), dpi=100)
        self.figure1.patch.set_facecolor('gray')
        self.canvas1 = FigureCanvasTkAgg(self.figure1, master=root)
        self.canvas1.get_tk_widget().grid(row=0, column=1, columnspan=1, 
            rowspan=25, padx=5, pady=5, sticky="n")


#signal_utils.py
import matplotlib.pyplot as plt
import numpy as np 

class Signal_Utils:
    def __init__(self):
        pass

    def simple_sine(self, figure, canvas):
        figure.clear()        
        start = 0
        end = 1
        step = 0.001
        x = np.arange(float(start), float(end), float(step))
        Fs = 10
        y = np.sin(2*np.pi*float(Fs)*x)
        
        ax = figure.add_subplot(1,1,1)
        ax.plot(x, y, linewidth=5.0, color='red')
        ax.set_ylabel('Amplitude', color='blue')
        ax.set_xlabel('Time (second)', color='blue')
        ax.set_title(f'Simple Sinusoidal Graph (Frequency = {Fs} Hz)')
        ax.set_facecolor('#F0F0F0')
        ax.grid(True)
        figure.tight_layout()
        canvas.draw()
        
    def two_sines(self, figure, canvas):
        figure.clear()
        
        start = 0
        end = 1
        step = 0.001
        x = np.arange(float(start), float(end), float(step))
        Fs1 = 10
        Fs2 = 6
        y1 = np.sin(2*np.pi*float(Fs1)*x)
        y2 = np.cos(2*np.pi*float(Fs2)*x)
        
        ax1 = figure.add_subplot(2,2,1)
        ax1.plot(x, y1, linewidth=3.0, color='red', label=f'Sin(2*pi*{Fs1}*x)')
        ax1.plot(x, y2, linewidth=3.0, color='black', label=f'Cos(2*pi*{Fs2}*x)')
        ax1.set_ylabel('Amplitude', color='blue')
        ax1.set_xlabel('Time (second)', color='blue')
        ax1.set_title(f'Sin(2*pi*{Fs1}*x) and Cos(2*pi*{Fs2}*x)')
        ax1.set_facecolor('#F0F0F0')
        ax1.legend()
        ax1.grid(True)        

        ax2 = figure.add_subplot(2,2,2)
        ax2.plot(x, y1*y2, linewidth=3.0, color='green')
        ax2.set_ylabel('Amplitude', color='blue')
        ax2.set_xlabel('Time (second)', color='blue')
        ax2.set_title(f'Sin(2*pi*{Fs1}*x) * Cos(2*pi*{Fs2}*x)')
        ax2.set_facecolor('#F0F0F0')
        ax2.grid(True)

        ax3 = figure.add_subplot(2,2,3)
        ax3.plot(x, y1 + y2, linewidth=3.0, color='brown')
        ax3.set_ylabel('Amplitude', color='blue')
        ax3.set_xlabel('Time (second)', color='blue')
        ax3.set_title(f'Sin(2*pi*{Fs1}*x) + Cos(2*pi*{Fs2}*x)')
        ax3.set_facecolor('#F0F0F0')
        ax3.grid(True)        
        
        ax4 = figure.add_subplot(2,2,4)
        ax4.plot(x, y1 - y2, linewidth=3.0, color='blue')
        ax4.set_ylabel('Amplitude', color='blue')
        ax4.set_xlabel('Time (second)', color='blue')
        ax4.set_title(f'Sin(2*pi*{Fs1}*x) - Cos(2*pi*{Fs2}*x)')
        ax4.set_facecolor('#F0F0F0')
        ax4.grid(True) 
        
        figure.tight_layout()
        canvas.draw()        

#form1.py
import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

class Form1:
    def __init__(self, window):
        self.window = window
        width = 1520
        height = 760
        self.window.geometry(f"{width}x{height}")
    
        #Adds canvasses
        self.add_canvas(self.window)

    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=0, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n")

        # Adds canvas1 widget to frame1
        self.figure1 = Figure(figsize=(15, 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)

        
if __name__ == "__main__":
    window = tk.Tk()
    Form1(window)
    window.mainloop()

#plot_utils.py
import matplotlib.pyplot as plt
import tkinter as tk
from tkinter import *
import seaborn as sns
import numpy as np 
import pandas as pd
from form1 import Form1
from signal_utils import Signal_Utils

class Plot_Utils:
    def __init__(self):
        self.signal_utils = Signal_Utils()

    def plot_simple_sine(self):
        win = tk.Toplevel()
        form1 = Form1(win)
        win.title("Simple Sinusoidal Signal")
        self.signal_utils.simple_sine(form1.figure1, form1.canvas1)

    def plot_two_sines(self):
        win = tk.Toplevel()
        form1 = Form1(win)
        win.title("Two Simple Sinusoidal Signals")
        self.signal_utils.two_sines(form1.figure1, form1.canvas1)
        
    def binds_simple_sinusoidal(self, window):     
        window.sinusoidal_menu.entryconfigure("Simple Sinusoidal",
            command =lambda:self.plot_simple_sine()) 
        
        window.sinusoidal_menu.entryconfigure("Two Sinusoidals",
            command =lambda:self.plot_two_sines())         

FULL SOURCE CODE VERSION 2.0



#main_program.py
import tkinter as tk
from main_form import Main_Form
from plot_utils import Plot_Utils

class Main_Program():
    def __init__(self, root):
        self.initialize(root)

    def initialize(self, root):
        self.root = root
        width = 1560
        height = 450
        self.root.geometry(f"{width}x{height}")
        self.root.title("START FROM FROM SCRATCH SIGNAL AND IMAGE PROCESSING WITH TKINTER")

        #Creates necessary objects
        self.obj_main_form = Main_Form()
        self.obj_plot_utils = Plot_Utils()
        
        #Places widgets in root
        self.obj_main_form.add_widgets(self.root)  

        #Binds events
        self.binds_event()
                
    def binds_event(self):
        self.obj_plot_utils.binds_simple_sinusoidal(self.obj_main_form)
         
if __name__ == "__main__":
    root = tk.Tk()
    app = Main_Program(root)
    root.mainloop()


#main_form.py
import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

class Main_Form:
    def add_widgets(self, root):        
        #Adds menu
        self.add_menu(root)

        #Adds canvasses
        self.add_canvas(root)

    def add_menu(self, root):
        self.menu_bar = tk.Menu(root)
        
        #Creates a Dataset menu
        self.sinusoidal_menu = tk.Menu(self.menu_bar, tearoff=0)
        self.sinusoidal_menu.add_command(label="Simple Sinusoidal")
        self.sinusoidal_menu.add_command(label="Two Sinusoidals")
        self.sinusoidal_menu.add_command(label="More Two Sinusoidals")
        self.sinusoidal_menu.add_command(label="Simple Sinusoidal 4")
        self.sinusoidal_menu.add_command(label="Simple Sinusoidal 5")        
        self.menu_bar.add_cascade(label="Sinusoidal Signals", menu=self.sinusoidal_menu)      
        
        root.config(menu=self.menu_bar)    

    def add_canvas(self, root):
        #Menambahkan canvas1 widget pada root untuk menampilkan hasil
        self.figure1 = Figure(figsize=(15.2, 4.2), dpi=100)
        self.figure1.patch.set_facecolor('gray')
        self.canvas1 = FigureCanvasTkAgg(self.figure1, master=root)
        self.canvas1.get_tk_widget().grid(row=0, column=1, columnspan=1, 
            rowspan=25, padx=5, pady=5, sticky="n")


#form1.py
import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

class Form1:
    def __init__(self, window):
        self.window = window
        width = 1520
        height = 760
        self.window.geometry(f"{width}x{height}")
    
        #Adds canvasses
        self.add_canvas(self.window)

    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=0, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n")

        # Adds canvas1 widget to frame1
        self.figure1 = Figure(figsize=(15, 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)

        
if __name__ == "__main__":
    window = tk.Tk()
    Form1(window)
    window.mainloop()


#form2.py
import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from signal_utils import Signal_Utils

class Form2:
    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 entry widgets
        self.add_entries(self.window)
        
        #Adds canvasses
        self.add_canvas(self.window)
        
        #Adds button
        self.add_button(self.window)
        
        self.signal_utils = Signal_Utils()

    def add_labels(self, master):
        # Create two labels
        self.label1 = tk.Label(master, text="START")
        self.label1.grid(row=0, column=0, padx=5, pady=0.1, sticky="w")

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

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

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

        self.label5 = tk.Label(master, text="FREQUENCY 2")
        self.label5.grid(row=8, column=0, padx=5, pady=0.1, sticky="w")
        
    def add_entries(self, master):
        # Create an entry widget and place it in the first row, first column
        self.entry_start = tk.Entry(master, width=20, bg="cyan")
        self.entry_start.grid(row=1, column=0, padx=5, pady=0.1, sticky="n")  
        self.entry_start.insert(0, "0")
        self.entry_start.bind('<Return>', self.plot_graph_event)

        # Create an entry widget and place it in the first row, first column
        self.entry_end = tk.Entry(master, width=20, bg="cyan")
        self.entry_end.grid(row=3, column=0, padx=5, pady=0.1, sticky="n") 
        self.entry_end.insert(0, "1")
        self.entry_end.bind('<Return>', self.plot_graph_event)

        # Create an entry widget and place it in the first row, first column
        self.entry_step = tk.Entry(master, width=20, bg="cyan")
        self.entry_step.grid(row=5, column=0, padx=5, pady=0.1, sticky="n") 
        self.entry_step.insert(0, "0.001")
        self.entry_step.bind('<Return>', self.plot_graph_event)

        # Create an entry widget and place it in the first row, first column
        self.entry_freq1 = tk.Entry(master, width=20, bg="cyan")
        self.entry_freq1.grid(row=7, column=0, padx=5, pady=0.1, sticky="n") 
        self.entry_freq1.insert(0, "7")
        self.entry_freq1.bind('<Return>', self.plot_graph_event)

        # Create an entry widget and place it in the first row, first column
        self.entry_freq2 = tk.Entry(master, width=20, bg="cyan")
        self.entry_freq2.grid(row=9, column=0, padx=5, pady=0.1, sticky="n") 
        self.entry_freq2.insert(0, "5")
        self.entry_freq2.bind('<Return>', self.plot_graph_event)
        
    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.7, 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_button(self, master):
        #Adds button
        self.btn1 = tk.Button(master, height=2, width=17, text="PLOT GRAPH", 
            command=self.plot_graph)
        self.btn1.grid(row=10, column=0, padx=5, pady=1, sticky="n")

    def read_and_check_input(self, start, end, step, freq1, freq2):        
        try:
            start = float(self.entry_start.get())
        except ValueError:
            start = 0
            self.entry_start.delete(0, tk.END)
            self.entry_start.insert(0, "0")

        try:
            end = float(self.entry_end.get())
        except ValueError:
            end = 1
            self.entry_end.delete(0, tk.END)
            self.entry_end.insert(0, "1")

        try:
            step = float(self.entry_step.get())
        except ValueError:
            step = 0.001
            self.entry_step.delete(0, tk.END)
            self.entry_step.insert(0, "0.001")

        try:
            freq1 = float(self.entry_freq1.get())
        except ValueError:
            freq1 = 10
            self.entry_freq1.delete(0, tk.END)
            self.entry_freq1.insert(0, "10")

        try:
            freq2 = float(self.entry_freq2.get())
        except ValueError:
            freq2 = 5
            self.entry_freq2.delete(0, tk.END)
            self.entry_freq2.insert(0, "5")

        return start, end, step, freq1, freq2

    def plot_graph(self):
        start = self.entry_start.get()
        end = self.entry_end.get()
        step = self.entry_step.get()
        freq1 = self.entry_freq1.get()
        freq2 = self.entry_freq2.get()

        start, end, step, freq1, freq2 = self.read_and_check_input(start, end, 
                step, freq1, freq2)
        self.signal_utils.more_two_sines(start, end, step, freq1, 
                freq2, self.figure1, self.canvas1)

    def plot_graph_event(self, event):
        self.plot_graph()

        
if __name__ == "__main__":
    window = tk.Tk()
    Form2(window)
    window.mainloop()


#plot_utils.py
import matplotlib.pyplot as plt
import tkinter as tk
from tkinter import *
import seaborn as sns
import numpy as np 
import pandas as pd
from form1 import Form1
from form2 import Form2
from signal_utils import Signal_Utils

class Plot_Utils:
    def __init__(self):
        self.signal_utils = Signal_Utils()

    def plot_simple_sine(self):
        win = tk.Toplevel()
        form1 = Form1(win)
        win.title("Simple Sinusoidal Signal")
        self.signal_utils.simple_sine(form1.figure1, form1.canvas1)

    def plot_two_sines(self):
        win = tk.Toplevel()
        form1 = Form1(win)
        win.title("Two Simple Sinusoidal Signals")
        self.signal_utils.two_sines(form1.figure1, form1.canvas1)

    def plot_more_two_sines(self):
        win = tk.Toplevel()
        win.title("MANIPULATING SINUSOIDAL SIGNALS")
        form2 = Form2(win)
        start = float(form2.entry_start.get())
        end = float(form2.entry_end.get())
        step = float(form2.entry_step.get())
        freq1 = float(form2.entry_freq1.get())
        freq2 = float(form2.entry_freq2.get())
        self.signal_utils.more_two_sines(start, end, step, freq1, freq2, form2.figure1, form2.canvas1)
        
    def binds_simple_sinusoidal(self, window):     
        window.sinusoidal_menu.entryconfigure("Simple Sinusoidal",
            command =lambda:self.plot_simple_sine()) 
        
        window.sinusoidal_menu.entryconfigure("Two Sinusoidals",
            command =lambda:self.plot_two_sines())         

        window.sinusoidal_menu.entryconfigure("More Two Sinusoidals",
            command =lambda:self.plot_more_two_sines())  



#signal_utils.py
import matplotlib.pyplot as plt
import numpy as np 

class Signal_Utils:
    def __init__(self):
        pass

    def simple_sine(self, figure, canvas):
        figure.clear()        
        start = 0
        end = 1
        step = 0.001
        x = np.arange(float(start), float(end), float(step))
        Fs = 10
        y = np.sin(2*np.pi*float(Fs)*x)
        
        ax = figure.add_subplot(1,1,1)
        ax.plot(x, y, linewidth=5.0, color='red')
        ax.set_ylabel('Amplitude', color='blue')
        ax.set_xlabel('Time (second)', color='blue')
        ax.set_title(f'Simple Sinusoidal Graph (Frequency = {Fs} Hz)')
        ax.set_facecolor('#F0F0F0')
        ax.grid(True)
        figure.tight_layout()
        canvas.draw()
        
    def two_sines(self, figure, canvas):
        figure.clear()
        
        start = 0
        end = 1
        step = 0.001
        x = np.arange(float(start), float(end), float(step))
        Fs1 = 10
        Fs2 = 6
        y1 = np.sin(2*np.pi*float(Fs1)*x)
        y2 = np.cos(2*np.pi*float(Fs2)*x)
        
        ax1 = figure.add_subplot(2,2,1)
        ax1.plot(x, y1, linewidth=3.0, color='red', label=f'Sin(2*pi*{Fs1}*x)')
        ax1.plot(x, y2, linewidth=3.0, color='black', label=f'Cos(2*pi*{Fs2}*x)')
        ax1.set_ylabel('Amplitude', color='blue')
        ax1.set_xlabel('Time (second)', color='blue')
        ax1.set_title(f'Sin(2*pi*{Fs1}*x) and Cos(2*pi*{Fs2}*x)')
        ax1.set_facecolor('#F0F0F0')
        ax1.legend()
        ax1.grid(True)        

        ax2 = figure.add_subplot(2,2,2)
        ax2.plot(x, y1*y2, linewidth=3.0, color='green')
        ax2.set_ylabel('Amplitude', color='blue')
        ax2.set_xlabel('Time (second)', color='blue')
        ax2.set_title(f'Sin(2*pi*{Fs1}*x) * Cos(2*pi*{Fs2}*x)')
        ax2.set_facecolor('#F0F0F0')
        ax2.grid(True)

        ax3 = figure.add_subplot(2,2,3)
        ax3.plot(x, y1 + y2, linewidth=3.0, color='brown')
        ax3.set_ylabel('Amplitude', color='blue')
        ax3.set_xlabel('Time (second)', color='blue')
        ax3.set_title(f'Sin(2*pi*{Fs1}*x) + Cos(2*pi*{Fs2}*x)')
        ax3.set_facecolor('#F0F0F0')
        ax3.grid(True)        
        
        ax4 = figure.add_subplot(2,2,4)
        ax4.plot(x, y1 - y2, linewidth=3.0, color='blue')
        ax4.set_ylabel('Amplitude', color='blue')
        ax4.set_xlabel('Time (second)', color='blue')
        ax4.set_title(f'Sin(2*pi*{Fs1}*x) - Cos(2*pi*{Fs2}*x)')
        ax4.set_facecolor('#F0F0F0')
        ax4.grid(True) 
        
        figure.tight_layout()
        canvas.draw()  
        
    def more_two_sines(self, start=0, end=1, step=0.001, Fs1=7, Fs2=5, figure=None, canvas=None):
        figure.clear()

        x = np.arange(float(start), float(end), float(step))

        y1 = np.sin(2*np.pi*float(Fs1)*x)
        y2 = np.cos(2*np.pi*float(Fs2)*x)
        
        ax1 = figure.add_subplot(2,2,1)
        ax1.plot(x, y1, linewidth=3.0, color='red', label=f'Sin(2*pi*{Fs1}*x)')
        ax1.plot(x, y2, linewidth=3.0, color='black', label=f'Cos(2*pi*{Fs2}*x)')
        ax1.set_ylabel('Amplitude', color='blue')
        ax1.set_xlabel('Time (second)', color='blue')
        ax1.set_title(f'Sin(2*pi*{Fs1}*x) and Cos(2*pi*{Fs2}*x)')
        ax1.set_facecolor('#F0F0F0')
        ax1.legend()
        ax1.grid(True)        

        ax2 = figure.add_subplot(2,2,2)
        ax2.plot(x, y1*y2, linewidth=3.0, color='green')
        ax2.set_ylabel('Amplitude', color='blue')
        ax2.set_xlabel('Time (second)', color='blue')
        ax2.set_title(f'Sin(2*pi*{Fs1}*x) * Cos(2*pi*{Fs2}*x)')
        ax2.set_facecolor('#F0F0F0')
        ax2.grid(True)

        ax3 = figure.add_subplot(2,2,3)
        ax3.plot(x, y1 + y2, linewidth=3.0, color='brown')
        ax3.set_ylabel('Amplitude', color='blue')
        ax3.set_xlabel('Time (second)', color='blue')
        ax3.set_title(f'Sin(2*pi*{Fs1}*x) + Cos(2*pi*{Fs2}*x)')
        ax3.set_facecolor('#F0F0F0')
        ax3.grid(True)        
        
        ax4 = figure.add_subplot(2,2,4)
        ax4.plot(x, y1 - y2, linewidth=3.0, color='blue')
        ax4.set_ylabel('Amplitude', color='blue')
        ax4.set_xlabel('Time (second)', color='blue')
        ax4.set_title(f'Sin(2*pi*{Fs1}*x) - Cos(2*pi*{Fs2}*x)')
        ax4.set_facecolor('#F0F0F0')
        ax4.grid(True) 
        
        figure.tight_layout()
        canvas.draw()                
        


FULL SOURCE CODE VERSION 3.0 (AMPLITUDE MODULATION)



#main_program.py
import tkinter as tk
from main_form import Main_Form
from plot_utils import Plot_Utils

class Main_Program():
    def __init__(self, root):
        self.initialize(root)

    def initialize(self, root):
        self.root = root
        width = 1560
        height = 450
        self.root.geometry(f"{width}x{height}")
        self.root.title("START FROM FROM SCRATCH SIGNAL AND IMAGE PROCESSING WITH TKINTER")

        #Creates necessary objects
        self.obj_main_form = Main_Form()
        self.obj_plot_utils = Plot_Utils()
        
        #Places widgets in root
        self.obj_main_form.add_widgets(self.root)  

        #Binds events
        self.binds_event()
                
    def binds_event(self):
        self.obj_plot_utils.binds_simple_sinusoidal(self.obj_main_form)
        self.obj_plot_utils.binds_modulation(self.obj_main_form)
         
if __name__ == "__main__":
    root = tk.Tk()
    app = Main_Program(root)
    root.mainloop()


#main_form.py
import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

class Main_Form:
    def add_widgets(self, root):        
        #Adds menu
        self.add_menu(root)

        #Adds canvasses
        self.add_canvas(root)

    def add_menu(self, root):
        self.menu_bar = tk.Menu(root)
        
        #Creates a sinusoidal menu
        self.sinusoidal_menu = tk.Menu(self.menu_bar, tearoff=0)
        self.sinusoidal_menu.add_command(label="Simple Sinusoidal")
        self.sinusoidal_menu.add_command(label="Two Sinusoidals")
        self.sinusoidal_menu.add_command(label="More Two Sinusoidals")      
        self.menu_bar.add_cascade(label="Sinusoidal Signals", menu=self.sinusoidal_menu)      

        #Creates a modulation menu
        self.modulation = tk.Menu(self.menu_bar, tearoff=0)
        self.modulation.add_command(label="Amplitude Modulation")
        self.modulation.add_command(label="Frequency Modulation")     
        self.menu_bar.add_cascade(label="Modulation", menu=self.modulation)  
        
        root.config(menu=self.menu_bar)    

    def add_canvas(self, root):
        #Menambahkan canvas1 widget pada root untuk menampilkan hasil
        self.figure1 = Figure(figsize=(15.2, 4.2), dpi=100)
        self.figure1.patch.set_facecolor('gray')
        self.canvas1 = FigureCanvasTkAgg(self.figure1, master=root)
        self.canvas1.get_tk_widget().grid(row=0, column=1, columnspan=1, 
            rowspan=25, padx=5, pady=5, sticky="n")


#form1.py
import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

class Form1:
    def __init__(self, window):
        self.window = window
        width = 1520
        height = 760
        self.window.geometry(f"{width}x{height}")
    
        #Adds canvasses
        self.add_canvas(self.window)

    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=0, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n")

        # Adds canvas1 widget to frame1
        self.figure1 = Figure(figsize=(15, 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)

        
if __name__ == "__main__":
    window = tk.Tk()
    Form1(window)
    window.mainloop()

#form2.py
import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from signal_utils import Signal_Utils

class Form2:
    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 entry widgets
        self.add_entries(self.window)
        
        #Adds canvasses
        self.add_canvas(self.window)
        
        #Adds button
        self.add_button(self.window)
        
        self.signal_utils = Signal_Utils()

    def add_labels(self, master):
        # Create two labels
        self.label1 = tk.Label(master, text="START")
        self.label1.grid(row=0, column=0, padx=5, pady=0.1, sticky="w")

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

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

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

        self.label5 = tk.Label(master, text="FREQUENCY 2")
        self.label5.grid(row=8, column=0, padx=5, pady=0.1, sticky="w")
        
    def add_entries(self, master):
        # Create an entry widget and place it in the first row, first column
        self.entry_start = tk.Entry(master, width=20, bg="cyan")
        self.entry_start.grid(row=1, column=0, padx=5, pady=0.1, sticky="n")  
        self.entry_start.insert(0, "0")
        self.entry_start.bind('<Return>', self.plot_graph_event)

        # Create an entry widget and place it in the first row, first column
        self.entry_end = tk.Entry(master, width=20, bg="cyan")
        self.entry_end.grid(row=3, column=0, padx=5, pady=0.1, sticky="n") 
        self.entry_end.insert(0, "1")
        self.entry_end.bind('<Return>', self.plot_graph_event)

        # Create an entry widget and place it in the first row, first column
        self.entry_step = tk.Entry(master, width=20, bg="cyan")
        self.entry_step.grid(row=5, column=0, padx=5, pady=0.1, sticky="n") 
        self.entry_step.insert(0, "0.001")
        self.entry_step.bind('<Return>', self.plot_graph_event)

        # Create an entry widget and place it in the first row, first column
        self.entry_freq1 = tk.Entry(master, width=20, bg="cyan")
        self.entry_freq1.grid(row=7, column=0, padx=5, pady=0.1, sticky="n") 
        self.entry_freq1.insert(0, "7")
        self.entry_freq1.bind('<Return>', self.plot_graph_event)

        # Create an entry widget and place it in the first row, first column
        self.entry_freq2 = tk.Entry(master, width=20, bg="cyan")
        self.entry_freq2.grid(row=9, column=0, padx=5, pady=0.1, sticky="n") 
        self.entry_freq2.insert(0, "5")
        self.entry_freq2.bind('<Return>', self.plot_graph_event)
        
    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.7, 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_button(self, master):
        #Adds button
        self.btn1 = tk.Button(master, height=2, width=17, text="PLOT GRAPH", 
            command=self.plot_graph)
        self.btn1.grid(row=10, column=0, padx=5, pady=1, sticky="n")

    def read_and_check_input(self, start, end, step, freq1, freq2):        
        try:
            start = float(self.entry_start.get())
        except ValueError:
            start = 0
            self.entry_start.delete(0, tk.END)
            self.entry_start.insert(0, "0")

        try:
            end = float(self.entry_end.get())
        except ValueError:
            end = 1
            self.entry_end.delete(0, tk.END)
            self.entry_end.insert(0, "1")

        try:
            step = float(self.entry_step.get())
        except ValueError:
            step = 0.001
            self.entry_step.delete(0, tk.END)
            self.entry_step.insert(0, "0.001")

        try:
            freq1 = float(self.entry_freq1.get())
        except ValueError:
            freq1 = 10
            self.entry_freq1.delete(0, tk.END)
            self.entry_freq1.insert(0, "10")

        try:
            freq2 = float(self.entry_freq2.get())
        except ValueError:
            freq2 = 5
            self.entry_freq2.delete(0, tk.END)
            self.entry_freq2.insert(0, "5")

        return start, end, step, freq1, freq2

    def plot_graph(self):
        start = self.entry_start.get()
        end = self.entry_end.get()
        step = self.entry_step.get()
        freq1 = self.entry_freq1.get()
        freq2 = self.entry_freq2.get()

        start, end, step, freq1, freq2 = self.read_and_check_input(start, end, 
                step, freq1, freq2)
        self.signal_utils.more_two_sines(start, end, step, freq1, 
                freq2, self.figure1, self.canvas1)

    def plot_graph_event(self, event):
        self.plot_graph()

        
if __name__ == "__main__":
    window = tk.Tk()
    Form2(window)
    window.mainloop()


#form3.py
import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from modulation_utils import Modulation_Utils
from form1 import Form1

class Form3:
    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 entry widgets
        self.add_entries(self.window)
        
        #Adds canvasses
        self.add_canvas(self.window)
        
        #Adds button
        self.add_button(self.window)
        
        self.modulation_utils = Modulation_Utils()

    def add_labels(self, master):
        # Create two 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="w")

        self.label3 = tk.Label(master, text="CARRIER AMPLITUDE")
        self.label3.grid(row=4, column=0, padx=5, pady=0.1, sticky="w")
        
        self.label4 = tk.Label(master, text="CARRIER FREQUENCY")
        self.label4.grid(row=6, column=0, padx=5, pady=0.1, sticky="w")

        self.label5 = tk.Label(master, text="MODULATING AMPLITUDE")
        self.label5.grid(row=8, column=0, padx=5, pady=0.1, sticky="w")
        
        self.label6 = tk.Label(master, text="MODULATING FREQUENCY")
        self.label6.grid(row=10, column=0, padx=5, pady=0.1, sticky="w")

        self.label7 = tk.Label(master, text="IDX MOD:", font=("Helvetica", 10))
        self.label7.grid(row=14, column=0, padx=5, pady=0.1, sticky="w")
        
    def add_entries(self, master):
        # Create entry widgets
        self.entry_fs = tk.Entry(master, width=20, bg="cyan")
        self.entry_fs.grid(row=1, column=0, padx=5, pady=0.1, sticky="n")  
        self.entry_fs.insert(0, "1000")
        self.entry_fs.bind('<Return>', self.plot_graph_event)

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

        self.entry_ac = tk.Entry(master, width=20, bg="cyan")
        self.entry_ac.grid(row=5, column=0, padx=5, pady=0.1, sticky="n") 
        self.entry_ac.insert(0, "1")
        self.entry_ac.bind('<Return>', self.plot_graph_event)
        
        self.entry_fc = tk.Entry(master, width=20, bg="cyan")
        self.entry_fc.grid(row=7, column=0, padx=5, pady=0.1, sticky="n") 
        self.entry_fc.insert(0, "50")
        self.entry_fc.bind('<Return>', self.plot_graph_event)

        self.entry_am = tk.Entry(master, width=20, bg="cyan")
        self.entry_am.grid(row=9, column=0, padx=5, pady=0.1, sticky="n") 
        self.entry_am.insert(0, "1")
        self.entry_am.bind('<Return>', self.plot_graph_event)
        
        self.entry_fm = tk.Entry(master, width=20, bg="cyan")
        self.entry_fm.grid(row=11, column=0, padx=5, pady=0.1, sticky="n") 
        self.entry_fm.insert(0, "5")
        self.entry_fm.bind('<Return>', self.plot_graph_event)
        
    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_button(self, master):
        #Adds button
        self.btn1 = tk.Button(master, height=2, width=17, text="PLOT GRAPH", 
            command=self.plot_graph)
        self.btn1.grid(row=12, column=0, padx=5, pady=1, sticky="n")

        self.btn2 = tk.Button(master, height=2, width=17, text="PLOT FFT", 
            command=self.plot_fft_am)
        self.btn2.grid(row=13, column=0, padx=5, pady=1, sticky="n")
        
    def read_and_check_input(self, fs, T, ac, fc, am, fm):        
        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:
            amp_carrier = float(ac)
        except ValueError:
            amp_carrier = 1
            self.entry_ac.delete(0, tk.END)
            self.entry_ac.insert(0, "1")
            
        try:
            freq_carrier = float(fc)
        except ValueError:
            freq_carrier = 50
            self.entry_fc.delete(0, tk.END)
            self.entry_fc.insert(0, "50")

        try:
            amp_mod = float(am)
        except ValueError:
            amp_mod = 1
            self.entry_am.delete(0, tk.END)
            self.entry_am.insert(0, "1")
            
        try:
            freq_mod = float(fm)
        except ValueError:
            freq_mod = 5
            self.entry_fm.delete(0, tk.END)
            self.entry_fm.insert(0, "5")
            
        return fsampling, periode, amp_carrier, freq_carrier, amp_mod, freq_mod

    def plot_graph(self):
        #Reads AM params
        fsampling = self.entry_fs.get()
        periode = self.entry_periode.get()
        amp_carrier = self.entry_ac.get()
        freq_carrier = self.entry_fc.get()
        amp_mod = self.entry_am.get()
        freq_mod = self.entry_fm.get()
        
        #Change text in label7 for index modulation
        miu=float(amp_mod)/float(amp_carrier)
        self.label7.config(text=f"IDX MOD: {miu:.2f}", font=("Helvetica", 12, "bold"))

        Fs, T, Ac, Fc, Am, Fm = self.read_and_check_input(fsampling, periode, amp_carrier,
                freq_carrier, amp_mod, freq_mod)
        
        # Performs amplitude modulation
        t, carrier_wave, modulating_wave, am_signal = self.modulation_utils.calculate_amplitude_modulation(Fs, T, Ac, Fc, Am, Fm)
        
        title1 = f'Carrier Signal, frequency = {Fc}, Amplitude = {Ac}'
        title2 = f'Modulating Signal, frequency = {Fm}, Amplitude = {Am}'
        title3 = "Amplitude Modulated Signal"
        self.modulation_utils.amplitude_modulation(t, carrier_wave, title1, modulating_wave, title2,
                             am_signal, title3, self.figure1, self.canvas1)

    def plot_fft_am(self):
        #Plots FFT of signals in form1
        win2 = tk.Toplevel()
        win2.title("AMPLITUDE MODULATION")
        form1 = Form1(win2)      

        #Reads AM params
        fsampling = self.entry_fs.get()
        periode = self.entry_periode.get()
        amp_carrier = self.entry_ac.get()
        freq_carrier = self.entry_fc.get()
        amp_mod = self.entry_am.get()
        freq_mod = self.entry_fm.get()

        Fs, T, Ac, Fc, Am, Fm = self.read_and_check_input(fsampling, periode, amp_carrier,
                freq_carrier, amp_mod, freq_mod)
        
        # Performs amplitude modulation
        t, carrier_wave, modulating_wave, am_signal = self.modulation_utils.calculate_amplitude_modulation(Fs, T, Ac, Fc, Am, Fm)


        self.modulation_utils.fft_am(Fs, carrier_wave, \
            "FFT of Carrier Signal", modulating_wave, "FFT of Modulating Signal", 
            am_signal, "FFT of AM Signal", form1.figure1, form1.canvas1)         
            
    def plot_graph_event(self, event):
        self.plot_graph()

        
if __name__ == "__main__":
    window = tk.Tk()
    Form3(window)
    window.mainloop()


#signal_utils.py
import matplotlib.pyplot as plt
import numpy as np 

class Signal_Utils:
    def __init__(self):
        pass

    def simple_sine(self, figure, canvas):
        figure.clear()        
        start = 0
        end = 1
        step = 0.001
        x = np.arange(float(start), float(end), float(step))
        Fs = 10
        y = np.sin(2*np.pi*float(Fs)*x)
        
        ax = figure.add_subplot(1,1,1)
        ax.plot(x, y, linewidth=5.0, color='red')
        ax.set_ylabel('Amplitude', color='blue')
        ax.set_xlabel('Time (second)', color='blue')
        ax.set_title(f'Simple Sinusoidal Graph (Frequency = {Fs} Hz)')
        ax.set_facecolor('#F0F0F0')
        ax.grid(True)
        figure.tight_layout()
        canvas.draw()
        
    def two_sines(self, figure, canvas):
        figure.clear()
        
        start = 0
        end = 1
        step = 0.001
        x = np.arange(float(start), float(end), float(step))
        Fs1 = 10
        Fs2 = 6
        y1 = np.sin(2*np.pi*float(Fs1)*x)
        y2 = np.cos(2*np.pi*float(Fs2)*x)
        
        ax1 = figure.add_subplot(2,2,1)
        ax1.plot(x, y1, linewidth=3.0, color='red', label=f'Sin(2*pi*{Fs1}*x)')
        ax1.plot(x, y2, linewidth=3.0, color='black', label=f'Cos(2*pi*{Fs2}*x)')
        ax1.set_ylabel('Amplitude', color='blue')
        ax1.set_xlabel('Time (second)', color='blue')
        ax1.set_title(f'Sin(2*pi*{Fs1}*x) and Cos(2*pi*{Fs2}*x)')
        ax1.set_facecolor('#F0F0F0')
        ax1.legend()
        ax1.grid(True)        

        ax2 = figure.add_subplot(2,2,2)
        ax2.plot(x, y1*y2, linewidth=3.0, color='green')
        ax2.set_ylabel('Amplitude', color='blue')
        ax2.set_xlabel('Time (second)', color='blue')
        ax2.set_title(f'Sin(2*pi*{Fs1}*x) * Cos(2*pi*{Fs2}*x)')
        ax2.set_facecolor('#F0F0F0')
        ax2.grid(True)

        ax3 = figure.add_subplot(2,2,3)
        ax3.plot(x, y1 + y2, linewidth=3.0, color='brown')
        ax3.set_ylabel('Amplitude', color='blue')
        ax3.set_xlabel('Time (second)', color='blue')
        ax3.set_title(f'Sin(2*pi*{Fs1}*x) + Cos(2*pi*{Fs2}*x)')
        ax3.set_facecolor('#F0F0F0')
        ax3.grid(True)        
        
        ax4 = figure.add_subplot(2,2,4)
        ax4.plot(x, y1 - y2, linewidth=3.0, color='blue')
        ax4.set_ylabel('Amplitude', color='blue')
        ax4.set_xlabel('Time (second)', color='blue')
        ax4.set_title(f'Sin(2*pi*{Fs1}*x) - Cos(2*pi*{Fs2}*x)')
        ax4.set_facecolor('#F0F0F0')
        ax4.grid(True) 
        
        figure.tight_layout()
        canvas.draw()  
        
    def more_two_sines(self, start=0, end=1, step=0.001, Fs1=7, Fs2=5, figure=None, canvas=None):
        figure.clear()

        x = np.arange(float(start), float(end), float(step))

        y1 = np.sin(2*np.pi*float(Fs1)*x)
        y2 = np.cos(2*np.pi*float(Fs2)*x)
        
        ax1 = figure.add_subplot(2,2,1)
        ax1.plot(x, y1, linewidth=3.0, color='red', label=f'Sin(2*pi*{Fs1}*x)')
        ax1.plot(x, y2, linewidth=3.0, color='black', label=f'Cos(2*pi*{Fs2}*x)')
        ax1.set_ylabel('Amplitude', color='blue')
        ax1.set_xlabel('Time (second)', color='blue')
        ax1.set_title(f'Sin(2*pi*{Fs1}*x) and Cos(2*pi*{Fs2}*x)')
        ax1.set_facecolor('#F0F0F0')
        ax1.legend()
        ax1.grid(True)        

        ax2 = figure.add_subplot(2,2,2)
        ax2.plot(x, y1*y2, linewidth=3.0, color='green')
        ax2.set_ylabel('Amplitude', color='blue')
        ax2.set_xlabel('Time (second)', color='blue')
        ax2.set_title(f'Sin(2*pi*{Fs1}*x) * Cos(2*pi*{Fs2}*x)')
        ax2.set_facecolor('#F0F0F0')
        ax2.grid(True)

        ax3 = figure.add_subplot(2,2,3)
        ax3.plot(x, y1 + y2, linewidth=3.0, color='brown')
        ax3.set_ylabel('Amplitude', color='blue')
        ax3.set_xlabel('Time (second)', color='blue')
        ax3.set_title(f'Sin(2*pi*{Fs1}*x) + Cos(2*pi*{Fs2}*x)')
        ax3.set_facecolor('#F0F0F0')
        ax3.grid(True)        
        
        ax4 = figure.add_subplot(2,2,4)
        ax4.plot(x, y1 - y2, linewidth=3.0, color='blue')
        ax4.set_ylabel('Amplitude', color='blue')
        ax4.set_xlabel('Time (second)', color='blue')
        ax4.set_title(f'Sin(2*pi*{Fs1}*x) - Cos(2*pi*{Fs2}*x)')
        ax4.set_facecolor('#F0F0F0')
        ax4.grid(True) 
        
        figure.tight_layout()
        canvas.draw()                


#plot_utils.py
import matplotlib.pyplot as plt
import tkinter as tk
from tkinter import *
import seaborn as sns
import numpy as np 
import pandas as pd
from form1 import Form1
from form2 import Form2
from form3 import Form3
from signal_utils import Signal_Utils
from modulation_utils import Modulation_Utils

class Plot_Utils:
    def __init__(self):
        self.signal_utils = Signal_Utils()
        self.modulation_utils = Modulation_Utils()

    def plot_simple_sine(self):
        win = tk.Toplevel()
        form1 = Form1(win)
        win.title("Simple Sinusoidal Signal")
        self.signal_utils.simple_sine(form1.figure1, form1.canvas1)

    def plot_two_sines(self):
        win = tk.Toplevel()
        form1 = Form1(win)
        win.title("Two Simple Sinusoidal Signals")
        self.signal_utils.two_sines(form1.figure1, form1.canvas1)

    def plot_more_two_sines(self):
        win = tk.Toplevel()
        win.title("MANIPULATING SINUSOIDAL SIGNALS")
        form2 = Form2(win)
        start = float(form2.entry_start.get())
        end = float(form2.entry_end.get())
        step = float(form2.entry_step.get())
        freq1 = float(form2.entry_freq1.get())
        freq2 = float(form2.entry_freq2.get())
        self.signal_utils.more_two_sines(start, end, step, freq1, freq2, form2.figure1, form2.canvas1)
        
    def binds_simple_sinusoidal(self, window):     
        window.sinusoidal_menu.entryconfigure("Simple Sinusoidal",
            command =lambda:self.plot_simple_sine()) 
        
        window.sinusoidal_menu.entryconfigure("Two Sinusoidals",
            command =lambda:self.plot_two_sines())         

        window.sinusoidal_menu.entryconfigure("More Two Sinusoidals",
            command =lambda:self.plot_more_two_sines())  

    def plot_amplitude_modulation(self):
        win = tk.Toplevel()
        win.title("AMPLITUDE MODULATION")
        form3 = Form3(win)
        Fs = float(form3.entry_fs.get())
        T = float(form3.entry_periode.get())
        Ac = float(form3.entry_ac.get())
        Fc = float(form3.entry_fc.get())
        Am = float(form3.entry_am.get())
        Fm = float(form3.entry_fm.get())        
        
        # Performs amplitude modulation
        t, carrier_wave, modulating_wave, am_signal = \
            self.modulation_utils.calculate_amplitude_modulation(Fs, T, Ac, Fc, Am, Fm)
        
        title1 = f'Carrier Signal, frequency = {Fc}, Amplitude = {Ac}'
        title2 = f'Modulating Signal, frequency = {Fm}, Amplitude = {Am}'
        title3 = "Amplitude Modulated Signal"
        self.modulation_utils.amplitude_modulation(t, carrier_wave, title1, modulating_wave, title2,
                             am_signal, title3, form3.figure1, form3.canvas1)

        #Plots FFT of signals in form1
        win2 = tk.Toplevel()
        win2.title("AMPLITUDE MODULATION")
        form1 = Form1(win2)      
     
        self.modulation_utils.fft_am(Fs, carrier_wave, \
            "FFT of Carrier Signal", modulating_wave, "FFT of Modulating Signal", 
            am_signal, "FFT of AM Signal", form1.figure1, form1.canvas1)        
        
    def binds_modulation(self, window):     
        window.modulation.entryconfigure("Amplitude Modulation",
            command =lambda:self.plot_amplitude_modulation())         
        
     
#modulation_utils.py
import matplotlib.pyplot as plt
import numpy as np 

class Modulation_Utils:
    def __init__(self):
        pass

    def calculate_amplitude_modulation(self, Fs, T, Ac, Fc, Am, Fm):
        # Define time line
        t = np.arange(0, T, 1/Fs)

        # Carrier signal
        carrier_wave = Ac*np.cos(2*np.pi*Fc*t)

        # Modulating signal
        modulating_wave = Am*np.cos(2*np.pi*Fm*t)

        # Amplitude modulation
        miu = Am/Ac
        am_signal = Ac*(1 + miu*np.cos(2*np.pi*Fm*t)) * np.cos(2*np.pi*Fc*t)
        
        return t, carrier_wave, modulating_wave, am_signal
        
    def amplitude_modulation(self, t, carrier_wave, title1, modulating_wave, title2,
                             am_signal, title3, figure=None, canvas=None):
        figure.clear()   

        ax1 = figure.add_subplot(3,1,1)
        ax1.plot(t, carrier_wave, linewidth=3.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.legend()
        ax1.grid(True)
         
        ax2 = figure.add_subplot(3,1,2)
        ax2.plot(t, modulating_wave, linewidth=3.0, color='black')
        ax2.set_ylabel('Amplitude', color='blue')
        ax2.set_xlabel('Time (second)', color='blue')
        ax2.set_title(title2)
        ax2.set_facecolor('#F0F0F0')
        ax2.grid(True)        
        
        ax3 = figure.add_subplot(3,1,3)
        ax3.plot(t, am_signal, linewidth=3.0, color='blue')
        ax3.set_ylabel('Amplitude', color='blue')
        ax3.set_xlabel('Time (second)', color='blue')
        ax3.set_title(title3)
        ax3.set_facecolor('#F0F0F0')
        ax3.grid(True)         

        figure.tight_layout()
        canvas.draw()  

    def fft_signal(self, Fs, signal):
        # Perform FFT
        fft_result = np.fft.fft(signal)
        freqs = np.fft.fftfreq(len(signal), 1/Fs)

        return freqs, fft_result

    def fft_am(self, Fs, signal1, title1, signal2, title2, signal3, title3, figure=None, canvas=None):
        figure.clear()   

        #Calculate FFT
        freqs1, fft_result1 = self.fft_signal(Fs, signal1)
        freqs2, fft_result2 = self.fft_signal(Fs, signal2)
        freqs3, fft_result3 = self.fft_signal(Fs, signal3) 

        ax1 = figure.add_subplot(3,1,1)
        ax1.plot(freqs1, np.abs(fft_result1), linewidth=2.0, color='red')
        ax1.set_ylabel('Magnitude', color='blue')
        ax1.set_xlabel('Frequency (Hz)', color='blue')
        ax1.set_title(title1)
        ax1.set_xticks(np.arange(min(freqs1), max(freqs1)+1, step=50))
        ax1.set_facecolor('#F0F0F0')
        ax1.legend()
        ax1.grid(True)
         
        ax2 = figure.add_subplot(3,1,2)
        ax2.plot(freqs2, np.abs(fft_result2), linewidth=2.0, color='black')
        ax2.set_ylabel('Magnitude', color='blue')
        ax2.set_xlabel('Frequency (Hz)', color='blue')
        ax2.set_title(title2)
        ax2.set_facecolor('#F0F0F0')
        ax2.set_xticks(np.arange(min(freqs1), max(freqs2)+1, step=50))
        ax2.legend()
        ax2.grid(True)        

        ax3 = figure.add_subplot(3,1,3)
        ax3.plot(freqs3, np.abs(fft_result3), linewidth=2.0, color='blue')
        ax3.set_ylabel('Magnitude', color='blue')
        ax3.set_xlabel('Frequency (Hz)', color='blue')
        ax3.set_title(title3)
        ax3.set_facecolor('#F0F0F0')
        ax3.set_xticks(np.arange(min(freqs1), max(freqs3)+1, step=50))
        ax3.legend()
        ax3.grid(True)

        # Set x-axis ticks at every 10th step
        
        
        figure.tight_layout()
        canvas.draw()  


        





No comments:

Post a Comment