aboutsummaryrefslogtreecommitdiff
path: root/funcGenerator.py
diff options
context:
space:
mode:
Diffstat (limited to 'funcGenerator.py')
-rw-r--r--funcGenerator.py274
1 files changed, 0 insertions, 274 deletions
diff --git a/funcGenerator.py b/funcGenerator.py
deleted file mode 100644
index cd33f0b..0000000
--- a/funcGenerator.py
+++ /dev/null
@@ -1,274 +0,0 @@
-import time # For sleep, clock, time and perf_counter
-from datetime import datetime, timedelta
-import numpy as np
-
-try:
- from pyqtgraph.Qt import QtCore
-except:
- pass
-
-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 setCenterAndSpan(self, center, span):
- self.start = center-span/2
- self.stop = center+span/2
-
- def setCenter(self, center):
- span = self.stop - self.start;
- self.setCenterAndSpan(center, span)
-
- def getCenter(self):
- return (self.stop + self.start)/2
-
- def setSpan(self, span):
- center = (self.stop + self.start)/2
- self.setCenterAndSpan(center, span)
-
- def getSpan(self):
- return self.stop - self.start;
-
- 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 SawGen(RampGen):
- # monotonically goes from start to stop, once reaches stop goes back to start
- # does it with duty_cycle,
- # i.e duty_cycle*period we go up, the other time we go down
- def __init__(self, duty_cycle=0.5, **kwds):
- self.duty_cycle = duty_cycle;
- super().__init__(**kwds)
-
- 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() < self.duty_cycle:
- return self.start + sweeper.getRelPos()/self.duty_cycle*(self.stop - self.start)
- return self.start + (1-sweeper.getRelPos())/(1-self.duty_cycle)*(self.stop - self.start)
- def getSweepDirection(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() < self.duty_cycle:
- return 1; # increasing value direction
- return 0; # decreasing value direction
-
-class TriangleGen(SawGen):
- # monotonically goes from start to stop, once reaches stop goes back to start
- # does it with 50% duty cycle, i.e half of period we go up, the other half down
- def __init__(self, **kwds):
- super().__init__(duty_cycle=0.5, **kwds)
-
-class PulseGen:
- # produce ampl for the first half a period and 0 for the other half
- 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:
- # main clock sweeper for any function generator
- 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.after(0, self.onTic)
-
- idleTime_mS = round((deadline-stop).seconds * 1000 + (deadline-stop).microseconds/1000)
- # print("Will idle for %s" % (idleTime_mS) )
- self.after(idleTime_mS, self.onTic)
-
- def after(self, idleTime_mS, cmnd):
- # this function modelled after Tk.after
- # it is execute 'cmnd' after idle time given in mS
- # idleTime_mS = 0 means execute immediately
- try:
- # Tk style
- self.widget.after(idleTime_mS, cmnd)
- return
- except AttributeError:
- pass
-
- try:
- # PyQt style
- t = QtCore.QTimer()
- t.singleShot( idleTime_mS, cmnd )
- return
- except NameError:
- pass
-
- raise Exception("Something went horribly wrong: we have no mechanism for Sweeper.after()")
-
-
- 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
-
-def testOnTicTk(sweeper):
- print( sweeper.getPos() )
- if sweeper.getPos() == sweeper.Npoints:
- print("Tk sweeper is done")
- sweeper.cmdStop()
- sweeper.widget.destroy()
- sweeper.widget.quit()
-
-def testSweeperTk():
- print("test Sweeper with Tk")
- root=Tk()
- root.geometry("800x600")
- root.withdraw(); # do not show window
-
- Np = 10
- SweepTime = Np
- print(f'Test sweeper: you should see a sequence of {Np} numbers updating about every {SweepTime/Np} seconds')
- sweeper = Sweeper(root, Npoints=Np, SweepTime=SweepTime, onTicCallbacks=[testOnTicTk])
- sweeper.cmdStart()
-
- root.mainloop()
-
-def testOnTicPyQtGraph(sweeper):
- print( sweeper.getPos() )
- if sweeper.getPos() == sweeper.Npoints:
- print("PyQtGraph sweeper is done")
- sweeper.cmdStop()
- sweeper.widget.exit()
-
-def testSweeperPyQtGraph():
- print("test Sweeper with PyQtGraph")
- app = QtGui.QApplication([])
-
- Np = 10
- SweepTime = Np
- print(f'Test sweeper: you should see a sequence of {Np} numbers updating about every {SweepTime/Np} seconds')
- sweeper = Sweeper(app, Npoints=Np, SweepTime=SweepTime, onTicCallbacks=[testOnTicPyQtGraph])
- sweeper.cmdStart()
-
- app.exec()
-
-if __name__ == '__main__':
- try:
- from tkinter import Tk
- testSweeperTk()
- except ModuleNotFoundError:
- print("Tk module not found, skipping testSweeperTk")
-
- try:
- from pyqtgraph.Qt import QtGui, QtCore
- testSweeperPyQtGraph()
- except ModuleNotFoundError:
- print("pyqtgraph.Qt module not found, skipping testSweeperPyQtGraph")
- print("Done with tests")
-