<repo_name>yzy19900402/OFDR_GUI<file_sep>/Gui.py
from tkinter import *
from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg, NavigationToolbar2Tk)
import matplotlib.pyplot as plt
import Data as DT
import Draw
import tkinter as tk
from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg, NavigationToolbar2Tk)
import shlex
import subprocess
import os

class gui_window:
    #  The parameters
    color_bg = 'white'  # Set background color
    color_text = '#E1F5FE'  # Set text color
    color_btn = '#212121'  # Set button color
    color_line = '#01579B'  # Set line color
    color_can = '#212121'  # Set canvas colorcd ..
    color_oval = '#2196F3'  # Set oval color
    target_color = '#FF6D00'

    Debug_STOP = FALSE
    Work_STOP = FALSE
    Data_Save_STOP = TRUE
    i = 1

    def __init__(self, folder, Data_length, folder_number, UDP_MAX, COLUMN_NUM, TARGET_IP, TARGET_PORT):
        self.root = Tk()  # create root window
        self.root.title("OFDR Client")
        self.root.maxsize(800, 600)
        self.root.config(bg="skyblue")

        self.Data = DT.Data(folder, Data_length, folder_number, UDP_MAX, COLUMN_NUM, TARGET_IP, TARGET_PORT)

        # Create left and right frames
        self.Control_Frame = Frame(self.root, width=2560, height=200, bg='grey')
        self.Control_Frame.pack(side='bottom', fill='x', padx=10, pady=5, expand=False)

        self.Fig_Frame = Frame(self.root, width=2560, height=1200, bg='grey')
        self.Fig_Frame.pack(side='bottom', fill='both', padx=10, pady=5, expand=True)

        # self.tool_bar = Frame(self.Control_Frame, width=90, height=185, bg='lightgrey')
        # self.tool_bar.grid(side='left', fill='both', padx=5, pady=5, expand=True)

        self.Control_bar = Frame(self.Control_Frame, width=1024, height=200, bg='lightgrey')
        self.Control_bar.pack(side='left', fill='y', padx=10, pady=5, expand=False)

        self.Terminal_bar = Frame(self.Control_Frame, width=1536, height=200, bg='black')
        self.Terminal_bar.pack(side='left', fill='both', padx=10, pady=5, expand=True)

        wid = self.Terminal_bar.winfo_id()
        args = shlex.split('xterm -into %d -geometry 80x80 -sb -e command &' % (wid))
        # os.system('xterm -into %d -geometry 40x20 -sb -e command &' % wid)
        self.terminal = subprocess.Popen(args)
        self.root.protocol('WM_DELETE_WINDOW', self.before_close)

        # Example labels that serve as placeholders for other widgets
        Label(self.Control_bar, text="Control", font=64).grid(column=5, row=0, sticky='news')

        # For now, when the buttons are clicked, they only call the clicked() method. We will add functionality later.
        Button(self.Control_bar, text="Debug", command=self.ReDebug).grid(column=0, row=1, sticky='news')
        Button(self.Control_bar, text="Stop", command=self.Stop).grid(column=0, row=2, sticky='news')
        Button(self.Control_bar, text="Work", command=self.Restart).grid(column=0, row=3, sticky='news')

        self.E1 = tk.Entry(self.Control_bar, show=None, width=30, bg="#37474F", fg='#eceff1')
        self.E1.grid(column=2, row=1, columnspan=6, sticky='news')  #Define a Entry and put it in position
        self.E1.insert(0, './Debug')
        Button(self.Control_bar, text="Debug Save", command=self.Debug_Save_data).grid(column=10, row=1, sticky='news')

        self.E2 = tk.Entry(self.Control_bar, show=None, width=30, bg="#37474F", fg='#eceff1')
        self.E2.grid(column=2, row=2, columnspan=6, sticky='news')  #Define a Entry and put it in position
        self.E2.insert(0, '128')

        self.E3 = tk.Entry(self.Control_bar, show=None, width=30, bg="#37474F", fg='#eceff1')
        self.E3.grid(column=2, row=3, columnspan=6, sticky='news')  #Define a Entry and put it in position
        self.E3.insert(0, './Data')
        Button(self.Control_bar, text="Stream Save", command=self.Save_data_Stream).grid(column=10, row=3, sticky='news')

        self.Fig = Draw.DRAW(self.Data)
        self.canvas = FigureCanvasTkAgg(self.Fig.fig, master=self.Fig_Frame)  # A tk.DrawingArea.
        self.canvas.get_tk_widget().pack(side='right', fill='both', padx=5, pady=5, expand=True)
        self.Fig.Test()
        self.canvas.draw()
        toolbar = NavigationToolbar2Tk(self.canvas, self.Fig_Frame)
        toolbar.config(background=self.color_bg)
        toolbar._message_label.config(background=self.color_bg)
        for button in toolbar.winfo_children():
            button.config(background=self.color_bg)
        toolbar.update()
        self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1, padx=0, pady=0)
        self.i = 1

    def ReDebug(self):
        self.Work_STOP = TRUE
        self.Data_Save_STOP = TRUE
        self.Debug_STOP = FALSE
        self.Debug()

    def Restart(self):
        self.Work_STOP = FALSE
        self.Debug_STOP = TRUE
        self.Data_Save_STOP = FALSE
        self.Work()

    def Stop(self):
        # print("tick")
        self.Work_STOP = TRUE
        self.Debug_STOP = TRUE
        self.Data_Save_STOP = FALSE

    def Start_gui(self):
        self.root.after(100, self.clicked)
        self.root.mainloop()

    def clicked(self):
        '''if button is clicked, display message'''
        print("Clicked.")

    def Debug_Save_data(self):
        name = self.E1.get()
        Status = self.Data.save_data(name)
        tk.messagebox.showinfo('Info', 'Debug data saved')

    def Save_data_Stream(self):
        self.Debug_STOP = TRUE
        self.Work_STOP = TRUE
        if self.Data_Save_STOP:
            self.i = 1
            print("Data saving stops")
        else:
            self.root.after(20, self.Save_data_Stream)
            if self.i < int(self.E2.get()):
                if self.Data.Try_data_run():
                    self.Fig.Work_moniter()
                    self.canvas.draw()
                    name = self.E3.get() + '/' + str(self.i) + '/'
                    print(name)
                    Status = self.Data.save_data(name)
                    self.i += 1
            else:
                self.Data_Save_STOP = TRUE
                tk.messagebox.showinfo('Info', 'Stream data saved')


    def Debug(self):
        if self.Debug_STOP:
            print("Debug stops")
        else:
            self.Fig.Test()
            self.canvas.draw()
            self.root.after(20, self.Debug)

    def Work(self):
        if self.Work_STOP:
            print("Working stops")
        else:
            self.root.after(20, self.Work)
            if self.Data.Try_data_run():
                self.Fig.Work_moniter()
                self.canvas.draw()

    def before_close(self):
        # self.terminal.terminate()
        self.root.destroy()

<file_sep>/Main.py
import Gui
import math

#global paramters
TARGET_IP = ''
TARGET_PORT = 8001
Data_length = 65536# the data length for u64, 8bytes
UDP_MAX = 32768  # the max byte length for UDP
COLUMN_NUM = math.floor(UDP_MAX / 8)
folder = '/home/clark/Documents/Measurements/01_15_20_Fiber_cable_ID/226ns/01_23_20_Cables/CableAA1/'
folder_number = 1


gui = Gui.gui_window(folder, Data_length, folder_number, UDP_MAX, COLUMN_NUM, TARGET_IP, TARGET_PORT)

gui.Start_gui()<file_sep>/Draw.py
import Data as DT
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

name = 'temp'
flag = False
lflag = False
ymax = 0
fs = 125e6
stop_thread = False
fp = 5
tau_d = 226e-9  # 1025e-9  # 226e-9
vp = 2e8  # The light speed in fiber
f0 = 43e3  # corresponding with L0


class DRAW:
    def __init__(self, DT):
        self.data_src = DT
        self.fig = plt.figure(figsize=(3, 2), dpi=100)
        self.fig.set_tight_layout(True)
        self.i = 0

    def Test(self):
        self.fig.clf()
        self.i += 5
        fig1 = plt.subplot(111)
        t = np.arange(1024)
        t = t*np.pi/512
        y = np.sin(t+self.i)
        plt.plot(t, y)
        plt.xlim(0, 6)
        plt.ylim(-1, 1)
        plt.grid()
        # SMALL_SIZE = 4
        # MEDIUM_SIZE = 10
        # BIGGER_SIZE = 12
        # plt.rc('font', size=SMALL_SIZE)  # controls default text sizes
        # plt.rc('axes', titlesize=SMALL_SIZE)  # fontsize of the axes title
        # plt.rc('axes', labelsize=SMALL_SIZE)  # fontsize of the x and y labels
        # plt.rc('xtick', labelsize=SMALL_SIZE)  # fontsize of the tick labels
        # plt.rc('ytick', labelsize=SMALL_SIZE)  # fontsize of the tick labels
        # plt.rc('legend', fontsize=SMALL_SIZE)  # legend fontsize
        # plt.rc('figure', titlesize=SMALL_SIZE)  # fontsize of the figure title
        # fig1.plot.grid()

    def Test_stop(self):
        self.fig.clf()

    def Work_moniter(self):
        print('started\n')
        self.fig.clf()
        index = np.arange(0, self.data_src.Data_length)
        t_us = index / fs * 1e6
        ADC_data_A, ADC_data_B, DAC_data, CMP_Delay, Trigger, COMP_in, Phase_error, Up, Dn = self.data_src.get_data()

        fig1 = plt.subplot(231)
        plt.plot(t_us, DAC_data / 39.7727, linewidth=0.8)
        plt.xlim(0, max(t_us))
        plt.grid()
        plt.xlabel('Time(\u03BCs)')
        plt.ylabel('Current(mA)')
        plt.title('Driving Current')

        fig2 = plt.subplot(232)
        plt.plot(t_us, ADC_data_A * 1000 / pow(2, 13), linewidth=0.8)
        plt.grid()
        plt.xlim(0, max(t_us))
        plt.xlabel('Time(\u03BCs)')
        plt.ylabel('Voltage (mV)')
        plt.title('MZI time domain signal')

        fig3 = plt.subplot(233)
        plt.plot(t_us, (Phase_error) / fp, linewidth=0.8)
        plt.grid()
        plt.xlim(0, max(t_us))
        plt.xlabel('Time(\u03BCs)')
        plt.ylabel('Phase error(\u03C0)')
        plt.title('Phase error over Time')

        f, t, Zxx = signal.stft(ADC_data_A, fs, nperseg=1000, noverlap=990)
        fig4 = plt.subplot(234)
        plt.pcolormesh(t * 1e6, f / 1e6, np.abs(Zxx))
        plt.ylabel('Frequency(MHz)')
        plt.xlabel('Time(\u03BCs)')
        plt.title('MZI STFFT')
        plt.xlim(0, max(t_us))
        plt.grid()
        plt.ylim(0, 30)

        fig5 = plt.subplot(2, 3, 5)
        freq = np.arange(int(self.data_src.Data_length))
        freq = freq * fs / self.data_src.Data_length
        sp = np.abs(np.fft.fft(ADC_data_A)) / self.data_src.Data_length
        # print(np.max(sp))
        sp_dB = 20 * np.log10(sp)
        plt.plot(freq / 1e6, sp_dB)
        plt.title('MZI FFT')
        plt.xlabel('Frequency(MHz)')
        plt.ylabel('magnitude(real dB)')
        plt.xlim(0, 30)
        # plt.ylim(max(sp_dB) - 40, max(sp_dB))
        plt.grid()

        fig6 = plt.subplot(2, 3, 6)
        sp = np.abs(np.fft.fft(ADC_data_B)) / self.data_src.Data_length
        # print(np.max(sp))
        sp_dB = 20 * np.log10(sp)
        distance = (freq - f0) / fs * tau_d * fp * vp
        plt.plot(distance, sp_dB)
        plt.title('Fiber length')
        plt.xlabel('Fiber length(m)')
        plt.ylabel('magnitude(real dB)')
        plt.xlim(-0.1, 6)
        # plt.ylim(max(sp_dB) - 70, max(sp_dB))
        plt.grid()


<file_sep>/Data.py
import numpy as np
import socket
import math
import Gui


# folder = './data/'

# Socket part capture the data

class Data:
    Data_length = 0
    UDP_MAX = 1
    TARGET_IP = ''
    TARGET_PORT = 8001
    TARGET = (TARGET_IP, TARGET_PORT)
    COLUMN_NUM = 0
    ADC_data_A = 0
    ADC_data_B = 0
    DAC_data = 0
    CMP_Delay = 0
    Dn = 0
    CMP_in = 0
    Trigger = 0
    Up = 0
    Phase_error = 0
    folder_number = 0
    folder = 0
    ss = 0
    Depth = 1
    data_ready = False
    i = 0
    data = 0

    def __init__(self, folder, Data_length, folder_number, UDP_MAX, COLUMN_NUM, TARGET_IP, TARGET_PORT):
        self.ss = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.TARGET = (TARGET_IP, TARGET_PORT)
        self.ss.bind(self.TARGET)
        self.folder = folder
        self.folder_number = folder_number
        self.ADC_data_A = np.zeros(Data_length, dtype=np.int16)
        self.ADC_data_B = np.zeros(Data_length, dtype=np.int16)
        self.DAC_data = np.zeros(Data_length, dtype=np.uint16)
        self.Other = np.zeros(COLUMN_NUM, dtype=np.uint16)
        self.Trigger = np.zeros(Data_length, dtype=np.uint8)
        self.Up = np.zeros(Data_length, dtype=np.uint8)
        self.Dn = np.zeros(Data_length, dtype=np.uint8)
        self.CMP_in = np.zeros(Data_length, dtype=np.uint8)
        self.CMP_Delay = np.zeros(Data_length, dtype=np.uint8)
        self.Phase_error = np.zeros(Data_length, dtype=np.int16)
        self.data_ready = False
        self.temp_buffer = np.zeros([math.floor(Data_length * 8 / UDP_MAX), UDP_MAX], dtype=np.uint8)
        self.Data_length = Data_length
        self.UDP_MAX = UDP_MAX
        self.Depth = math.floor(self.Data_length*8/self.UDP_MAX)

    def close(self):
        self.stop_thread = True

    def reset(self):
        self.i = self.Depth - 1

    def Try_data_run(self):
        self.ss.settimeout(0.05)
        try:
            data, addrRsv = self.ss.recvfrom(self.UDP_MAX)
        except:
            return False
        else:
            # print(self.i)
            if not self.data_ready:
                if data[7] == 0x5a:
                    self.i = 0

            if data[7] == 0xa5:
                if self.i == self.Depth - 1:
                    self.data_ready = True
                    # print('Ready')

            self.temp_buffer[self.i, :] = np.frombuffer(data, dtype=np.uint8)
            self.i = (self.i + 1) % self.Depth
            if self.data_ready:
                self.data_ready = False
                data = self.temp_buffer.tobytes()
                self.data = np.frombuffer(data, np.int16)
                data_temp = np.reshape(self.data, [self.Data_length, 4])
                self.ADC_data_A = data_temp[:, 0]
                self.ADC_data_B = data_temp[:, 1]
                DAC_data_temp = data_temp[:, 2]
                self.DAC_data = DAC_data_temp.astype(np.uint16)
                Other = data_temp[:, 3]
                Other = Other.astype(np.uint16)
                self.CMP_Delay = Other % 2
                self.Dn = ((Other // 2) % 16)
                self.CMP_in = (Other // pow(2, 5)) % 2
                self.Trigger = (Other // pow(2, 6)) % 2
                self.Up = (Other // pow(2, 7)) % 2
                Upcumsum = self.Up.cumsum()
                Dncumsum = self.Dn.cumsum()
                self.data_ready = False
                self.Phase_error = np.int16(Upcumsum - Dncumsum)
                return True
            else:
                return False
            # print(self.i)
            # Debug_test = self.DAC_data
            # print(Debug_test)
            # break

    def save_data(self, name):
        print('Saving')
        np.savetxt(name + '/MZI.txt', self.ADC_data_A)
        np.savetxt(name + '/Reflect.txt', self.ADC_data_B)
        np.savetxt(name + '/Up.txt', self.Up)
        np.savetxt(name + '/Dn.txt', self.Dn)
        np.savetxt(name + '/CMP_Delay.txt', self.CMP_Delay)
        np.savetxt(name + '/CMP_in.txt', self.CMP_in)
        np.savetxt(name + '/DAC.txt', self.DAC_data)
        np.savetxt(name + '/Trigger.txt', self.Trigger)
        return 'Saved'

    def get_shot(self):
        return self.DAC_data

    def if_ready(self):
        return self.data_ready

    def get_data(self):
        return (self.ADC_data_A - np.mean(self.ADC_data_A)), (
                self.ADC_data_B - np.mean(
            self.ADC_data_B)), self.DAC_data, self.CMP_Delay, self.Trigger, self.CMP_in, self.Phase_error, self.Up, self.Dn
