diff options
author | Eugeniy E. Mikhailov <evgmik@gmail.com> | 2021-04-08 23:47:21 -0400 |
---|---|---|
committer | Eugeniy E. Mikhailov <evgmik@gmail.com> | 2021-04-08 23:47:21 -0400 |
commit | 1fbf0bb826f88f63e84010c629b2f768f8d5e6cd (patch) | |
tree | eb4b19bcc57c30265e0730626162c0fd5899227f /panel.py | |
parent | 9c09d346a0120241e1a99537b0b58768f95d1843 (diff) | |
download | qolab-1fbf0bb826f88f63e84010c629b2f768f8d5e6cd.tar.gz qolab-1fbf0bb826f88f63e84010c629b2f768f8d5e6cd.zip |
renamed file
Diffstat (limited to 'panel.py')
-rw-r--r-- | panel.py | 368 |
1 files changed, 0 insertions, 368 deletions
diff --git a/panel.py b/panel.py deleted file mode 100644 index 23c611e..0000000 --- a/panel.py +++ /dev/null @@ -1,368 +0,0 @@ -import tkinter as tk -from tkinter import * -from tkinter import ttk - -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 - -class SinGen: - def __init__(self, ampl=1, offset=0, phase=0, sweeper=None): - self.ampl = ampl - self.phase = phase - self.sweeper = sweeper - self.offset = offset - - def getValue(self, sweeper=None): - if sweeper is None and self.sweeper is None: - print("Error: generator needs sweeper") - return 0 - if sweeper is None: - sweeper = self.sweeper - return self.ampl * np.sin( 2*np.pi*sweeper.getRelPos()) + self.offset - -class RampGen: - # monotonically goes from start to stop, at final point move to start - def __init__(self, start=0, stop=0, sweeper=None): - self.start = start - self.stop = stop - self.sweeper = sweeper - - def getValue(self, sweeper=None): - if sweeper is None and self.sweeper is None: - print("Error: generator needs sweeper") - return 0 - if sweeper is None: - sweeper = self.sweeper - return self.start + sweeper.getRelPos()*(self.stop - self.start) - -class TriangleGen: - # monotonically goes from start to stop, once reaches stop goes back to start - def __init__(self, start=0, stop=0, sweeper=None): - self.start = start - self.stop = stop - self.sweeper = sweeper - - def getValue(self, sweeper=None): - if sweeper is None and self.sweeper is None: - print("Error: generator needs sweeper") - return 0 - if sweeper is None: - sweeper = self.sweeper - if sweeper.getRelPos() < 0.5: - return self.start + 2*sweeper.getRelPos()*(self.stop - self.start) - return self.start + 2*(1-sweeper.getRelPos())*(self.stop - self.start) - -class PulseGen: - # monotonically goes from start to stop, once reaches stop goes back to start - def __init__(self, ampl=1, sweeper=None): - self.ampl = ampl - self.sweeper = sweeper - - def getValue(self, sweeper=None): - if sweeper is None and self.sweeper is None: - print("Error: generator needs sweeper") - return 0 - if sweeper is None: - sweeper = self.sweeper - if sweeper.getRelPos() < 0.5: - return self.ampl - return 0 - -class Sweeper: - def __init__(self, widget, Npoints, SweepTime, onTicCallbacks=[]): - # walk from start to stop with Npoints - # cnt = 1 corresponds to start - # cnt = Npoints corresponds to stop - # variables like relVar are relative to the start of the period - self.cnt = 0 # onTic will increase it right away - self.widget = widget - self.Npoints = Npoints - self.start = 1 - self.stop = self.Npoints - self.SweepTime = SweepTime - self.onTicCallbacks = onTicCallbacks - self.isOn = False - self.isRestart = True - self.isTicRunning = False - - self.span = self.stop - self.start - self.center = (self.stop + self.start)/2 - self.dPos = self.span/(self.Npoints-1) - self.dT = self.SweepTime/(self.Npoints-1) - self.dTmS = round(self.dT*1000) # dT in milliseconds - - def reset(self): - self.cnt = 0 # onTic will increase it right away - self.isRestart = False - self.startTime = datetime.now() - - def onTic(self): - start = datetime.now() - deadline = start + timedelta(milliseconds=self.dTmS) - - if not self.isOn: - self.isTicRunning = False - return - self.isTicRunning = True - if self.isRestart: - self.reset() - self.isRestart = False - self.incr() - for cb in self.onTicCallbacks: - cb(self) - stop = datetime.now() - self.isTicRunning = False - if stop > deadline: - runTime = (stop-start).seconds + float((stop-start).microseconds)/1000000 - print("Overrun: Callbacks took %s seconds instead of %s" % (runTime, self.dTmS/1000) ) - self.widget.after(0, self.onTic) - - idleTime_mS = round((deadline-stop).seconds * 1000 + (deadline-stop).microseconds/1000) - # print("Will idle for %s" % (idleTime_mS) ) - self.widget.after(idleTime_mS, self.onTic) - - - def cmdRestart(self): - self.cnt = 0 - if self.isOn: - self.isRestart = True - return - self.reset() - self.isOn = True - self.onTic() - - def cmdStart(self): - self.isOn = True - self.onTic() - - def cmdStop(self): - self.isOn = False - - def incr(self): - self.cnt += 1 - self.updPos() - - def updPos(self): - self.relCnt = 1 + ((self.cnt-1) % self.Npoints) - self.pos = self.start + self.dPos * (self.relCnt - 1) - self.relPos = (self.pos-self.start)/self.span - - def getCnt(self): - return self.cnt - - def getRelCnt(self): - return self.relCnt - - def getPos(self): - return self.pos - - def getRelPos(self): - return self.relPos - - -class Experiment: - - def __init__(self, root): - self.root = root - self.tic = 0 - self.channelsNames2plot={'dac0', 'dac1', 'adc1', 'adc2', 'adc3', 'adc4'} - self.xChannelName='dac0' # can be also 'tic' or any of above - self.xlabel='Frequency (Hz)' - 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() - self.sweeper = Sweeper(self.root, Npoints=100, SweepTime=1, 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) - - - - def hardwareSetup(self): - self.hardware['LabJack'] = ue9qol.UE9qol() - - 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 = {} - self.data['tic'] = [] - self.data['x'] = [] - self.data['dac0'] = [] - self.data['dac1'] = [] - self.data['adc1'] = [] - self.data['adc2'] = [] - self.data['adc3'] = [] - self.data['adc4'] = [] - - 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) - - # DAQ - # daq0 = self.hardware['LabJack'] - - # dac0 - dac0 = self.funcGen.getValue(swp) - # daq0.setOutputCh(0, out0) - self.data['dac0'].append(dac0) - - # dac1 - dac1 = PulseGen(ampl=5, sweeper=swp).getValue() - # daq0.setOutputCh(0, dac1) - self.data['dac1'].append(dac1) - - # 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 ) - - # adc4 - # adc4= daq0.getInputCh(4) - adc4 = SinGen(ampl=4, sweeper=swp).getValue() - self.data['adc4'].append( adc4 ) - - # X-axis (i.e. independent variable) - # self.data['x'].append(tic) - self.data['x']=self.data[self.xChannelName] - - 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__': - root=Tk() - - experiment=Experiment(root) - - root.mainloop() - |