import tkinter as tk from tkinter import * from tkinter import ttk import platform import argparse from threading import Thread import time # For sleep, clock, time and perf_counter from datetime import datetime, timedelta import numpy as np import matplotlib.pyplot as plt from matplotlib.figure import Figure from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk) import csv import ue9qol from funcGenerator import Sweeper, SinGen, TriangleGen, RampGen, PulseGen from rfGen import rfGenLMX2487 class Experiment: def __init__(self, root, args): self.root = root self.tic = 0 self.channelsNames2grab={'tic', 'x','rfFreq','dac0', 'dac1', 'adc0', 'adc1', 'adc2', 'adc3'} #self.channelsNames2plot={'dac0', 'dac1', 'adc0', 'adc1', 'adc2', 'adc3'} if args.test: self.channelsNames2plot={'adc0', 'adc1'} else: self.channelsNames2plot={'adc0'} self.xChannelName='rfFreq' # can be also 'tic' or any of above self.xlabel='' self.lines2plot={} self.clearData() self.guiSetup(root) self.guiSweeper = Sweeper(self.root, Npoints=2, SweepTime=1, onTicCallbacks=[self.updatePlot]) self.guiSweeper.cmdStart() self.hardware = {} self.hardwareSetup(args) self.sweeper = Sweeper(self.root, Npoints=100, SweepTime=10, onTicCallbacks=[self.onTic]) # self.funcGen = SinGen(2, 2, sweeper = self.sweeper) # self.funcGen = RampGen(0, 5, sweeper = self.sweeper) self.funcGen = TriangleGen(0, 5, sweeper = self.sweeper) fCent=6.83468e9 self.fCent=fCent fSpan=50e3 self.fSpan=fSpan self.rfGenFunc = RampGen(fCent-fSpan/2, fCent+fSpan/2, sweeper = self.sweeper) def hardwareSetup(self,args): if args.test: print("Test mode, run with fake hardware") self.hardware['LabJack'] = ue9qol.UE9qolDummy() else: self.hardware['LabJack'] = ue9qol.UE9qol() if platform.system() == 'Linux': rf=rfGenLMX2487(port='/dev/ttyUSB0', speed=115200, timeout=1) else: rf=rfGenLMX2487(port='COM5', speed=115200, timeout=1) self.hardware['rfGen'] = rf def guiSetup(self, root): self.cntrlPannel=ttk.LabelFrame(root, text='controls') self.cntrlPannel.pack() self.bAutoZoom=Button(self.cntrlPannel,text="AutoZoom",command=self.autoZoom,font=('Arial','24')) self.bAutoZoom.pack(side='left') self.bRestart=Button(self.cntrlPannel,text="RESTART",command=self.restart,font=('Arial','24')) self.bRestart.pack(side='left') self.bStart=Button(self.cntrlPannel,text="START",command=self.start,font=('Arial','24')) self.bStart.pack(side='left') self.bStop=Button(self.cntrlPannel,text="STOP",command=self.stop,font=('Arial','24')) self.bStop.pack(side='left') self.bSave=Button(self.cntrlPannel,text="SAVE",command=self.saveCmd,font=('Arial','24')) self.bSave.pack(side='left') self.bExit=Button(self.cntrlPannel,text="EXIT",command=exit,font=('Arial','24')) self.bExit.pack(side='left') self.dataDisplay=ttk.LabelFrame(root, text='data') self.dataDisplay.pack() self.fig=plt.figure(figsize=[32, 24]) self.ax = self.fig.add_subplot(1,1,1) # self.ax.set_xlim([0,20]) # self.ax.set_ylim([0,20]) # self.ax.plot([i for i in range(10)],[i for i in range(10)]) self.line, = self.ax.plot(self.data['tic'], self.data['adc1'], '.') self.canvas = FigureCanvasTkAgg(self.fig, master = self.dataDisplay) self.canvas.draw() # placing the canvas on the Tkinter window # self.canvas.get_tk_widget().pack() # creating the Matplotlib toolbar self.toolbar = NavigationToolbar2Tk(self.canvas, self.dataDisplay) self.toolbar.update() # placing the toolbar on the Tkinter window self.canvas.get_tk_widget().pack() def clearData(self): self.data = {} for ch in self.channelsNames2grab: self.data[ch] = [] def stop(self): self.sweeper.cmdStop() def start(self): self.sweeper.cmdStart() def restart(self): self.clearData() self.sweeper.cmdRestart() def saveCmd(self): csv_file = 'data.csv' data = self.data try: with open(csv_file, 'w') as csvfile: writer = csv.writer(csvfile) writer.writerow(data.keys()) writer.writerows(zip(*data.values())) except IOError: print('I/O error') def onTic(self,swp=None): start = datetime.now() if swp is None: swp = self.sweeper # global tic counter tic = self.sweeper.getCnt() self.data['tic'].append(tic) # RF generator rfFreq = self.rfGenFunc.getValue(swp) self.hardware['rfGen'].setFreq(rfFreq) self.data['rfFreq'].append(rfFreq) # DAQ daq0 = self.hardware['LabJack'] # dac0 # dac0 = self.funcGen.getValue(swp) dac0 = 0 dac0 = self.funcGen.getValue(swp) daq0.setOutputCh(0, dac0) self.data['dac0'].append(dac0) # dac1 # dac1 = PulseGen(ampl=5, sweeper=swp).getValue() dac1 = 0 daq0.setOutputCh(1, dac1) self.data['dac1'].append(dac1) # adc0 adc0= daq0.getInputCh(0) # adc0 = SinGen(ampl=4, sweeper=swp).getValue() self.data['adc0'].append( adc0 ) # adc1 adc1= daq0.getInputCh(1) # adc1 = SinGen(ampl=1, sweeper=swp).getValue() self.data['adc1'].append( adc1 ) # adc2 adc2= daq0.getInputCh(2) # adc2 = SinGen(ampl=2, sweeper=swp).getValue() self.data['adc2'].append( adc2 ) # adc3 adc3= daq0.getInputCh(3) # adc3 = SinGen(ampl=3, sweeper=swp).getValue() self.data['adc3'].append( adc3 ) # X-axis (i.e. independent variable) # self.data['x'].append(tic) # self.data['x']=self.data[self.xChannelName] x=self.data[self.xChannelName][-1] x=(x-self.fCent)/1e3; # shift and convert to kHz self.xlabel=f'Frequency offset (kHz) relative center {self.fCent/1e6} MHz ' self.data['x'].append(x) stop = datetime.now() runTime = (stop-start).seconds + float((stop-start).microseconds)/1000000 # print("onTic DAQ took %s seconds." % (runTime) ) def autoZoom(self): self.ax.cla() x = self.data['x'] for name in self.channelsNames2plot: if name not in self.data: continue y = self.data[name] self.lines2plot[name], = self.ax.plot(x, y, '.', label=name) self.ax.legend() plt.xlabel(self.xlabel) self.canvas.draw() def updatePlot(self,swp=None): start = datetime.now() # self.ax.cla() # self.line, = self.ax.plot(self.data['tic'], self.data['adc1'], '.') # t = Thread(target=self.canvas.draw) # self.line.set_data([.1, .2, .3], [.1, .2, .3]) x = self.data['x'] for name in self.channelsNames2plot: if name not in self.data: continue y = self.data[name] if name in self.lines2plot: ln = self.lines2plot[name] ln.set_data(x, y) self.ax.draw_artist(ln) # self.canvas.update() self.canvas.draw() self.fig.canvas.flush_events() stop = datetime.now() runTime = (stop-start).seconds + float((stop-start).microseconds)/1000000 print("Replot took %s seconds to plot %s points." % (runTime, len(self.data['adc1'])) ) if __name__ == '__main__': parser = argparse.ArgumentParser(description='Perform EIT based experiment.') parser.add_argument('--test', '-t', action='store_true', help='test mode, use fake/dummy hardware') args = parser.parse_args() root=Tk() root.geometry("800x600") experiment=Experiment(root, args) root.mainloop()