from Tkinter import *
from getsound import GetSound
from scipy.fftpack import fft
from scipy.signal import blackmanharris, iirdesign, lfilter, kaiser
from scipy import vdot, array, var, std, log10, zeros, asarray
import struct, os.path, msvcrt, scipy, math, Queue, threading, msvcrt, re, random, time
import datetime
import Gnuplot
from myentry import MyEntry
from sdb import DB
from simpleFilter import Filter
from iirFilterGui import editIIRParams, editWeighting
import numpy


"""
from Tkinter import *
from myentry import MyEntry
from getsound import GetSound
from scipy.fftpack import fft
from scipy.signal import blackmanharris, iirdesign, lfilter, kaiser
from scipy import vdot, array, var, std, log10, zeros, asarray
import struct, os.path, msvcrt, scipy, math, Queue, threading, msvcrt, re, random, time
import datetime
import Gnuplot
from simpleFilter import Filter
from iirFilterGui import editIIRParams, editWeighting
import numpy
"""

### Attribute names:
SPECTRUMPLOTENABLE	= 'spectrumPlotEnable'
SPECTRUMAVGENABLE = 'spectrumavgenable'
PROCESSUPDATEINTERVAL = 'processUpdateInterval'
PRINTENABLE = 'diagprintenable'
PRINTOUTTYPE = 'printouttype'
PROCESSCOUNT = 'processcount'
IDATASTDFACTOR = 'idatastdfactor'
IIRPARAMS = 'iirparams'
PRINTOUTDIAG = 'printoutdiag'
BPFILTENABLE = 'bpfiltenable'
WEIGHTINGTYPE = 'weightingtype'		# 1 - blackmanharris, 2 - kaiser
KAISERPARAM = 'kaiserparam'
###

NOPRINT = 0
NORMALPRINT = 1
RAWPRINT = 2
EXPRINT	= 3
DIAGPRINT = 4

BGCOLOR = 'ivory'

class EstNoise(object):
	def __init__(self, sampleRate, transformSize, fbands):
		# sampleRate	-	Hz
		# transformSize -	Typically 4096
		# fbands	-       A tuple of frequency pairs over which to estimate the noise, KHz

		df = float(sampleRate) / (transformSize - 1)
		self.bands = []
		self.total = 0
		for sf, ef in fbands:
			ks = int(sf * 1e3 / df) -1
			ke = int(ef * 1e3 / df)
			self.bands.append((ks, ke))
			self.total += ke - ks

	def estimate(self, data):
		rss = 0.0
		for ks, ke in self.bands:
			for x in data[ks:ke]:
				rss += x * x
		return math.sqrt(rss / self.total)

class IIRFilter(object):
	"""
	"""
	def __init__(self):
		pass

	def init(self, wp, ws, passBandLoss, stopBandAtt):
		"""
		wp, ws  -- Passband and stopband edge frequencies, normalized from 0
						to 1 (1 corresponds to pi radians / sample).

		For an explaination of this code see
			"Digital Control System Analysis and Design", Phillips and Nagle, page 45.
			and the documentation for scipy signal.iirdesign.
		"""

		f = iirdesign(wp, ws, passBandLoss, stopBandAtt, ftype='butter')
		self.A = f[0]		# Numerator of transfer function	: An, An-1, An-2, ... A1, A0
		self.B = f[1]		# Denominator				: 1,  Bn-1, Bn-2, ... B1, B0
		self.C = []		# Coefficients for calculation of yk
		self.D = []		# Coefficients for calculation of ek
		self.an = self.A[0]
		n = len(f[0])
		self.N = n - 1		# number of delays in filter
		for k in range(self.N):
			j = n - k - 1
			c = self.A[j] - self.A[0]*self.B[j]
			self.C.append(c)
			self.D.append(self.B[j])
		self.X = zeros(self.N)		#array([0.0 for k in range(self.N)])
		self.D = array(self.D)
		self.currentValue = 0.0

	def next(self, u):
		ek = u - vdot(self.D, self.X)
		if self.N > 1:
			for k in range(self.N-1):
				self.X[k] = self.X[k+1]
			self.X[self.N-1] = ek
		else:
			self.X[0] = ek
		yk = (self.an * u) + vdot(self.C, self.X)
		self.currentValue = yk
		return yk

class Screen:
	# Remove short transisent spikes from data
	def __init__(self, alpha):
		self.alpha = alpha
		self.X = [0 for k in range(7)]
		self.R = range(6)
		self.k = 5

	def next(self, x):
		if self.k:
			self.k -= 1
			self.X[self.k] = x
			return x
		else:
			self.X[6] = x
			xb = (sum(self.X) - self.X[3]) / 6.0
			self.xb = xb
			if abs(xb - self.X[3]) > self.alpha * abs(xb):
				self.X[3] = xb
			for j in self.R:
				self.X[j] = self.X[j+1]
			return self.X[2]

class Track(object):
	names = []
	scaleFactors = []
	updates = []
	filters = []
	def __init__(self, frequency, bw, df, iirparams, salpha, name, scaleFactor=1.0, printEnable=False):
		"""
			frequency	-	Frequency of signal to monitor
			bw			-	Frequency extent
			df			-	Frequency resolution
			iirargs		-	IIR filter coefficients (dict)
		"""
		Track.names.append(name)
		Track.scaleFactors.append(scaleFactor)
		Track.updates.append(self.update)

		self.scaleFactor = scaleFactor
		self.printEnable = printEnable
		k = frequency / df
		dk = bw / df
		self.start = int(k - dk/2 ) + 1
		self.end = int(k + dk/2 ) + 2
		numBins = self.end - self.start
		if numBins & 1 == 0:
			numBins += 1
			self.end += 1
		self.filter = IIRFilter()
		self.filter.init(**iirparams)
		Track.filters.append(self.filter)
		self.screen = Screen(salpha)

	def update(self, data):
		# data contains magnitude-squared values of the PSD
		s = sum(data[self.start : self.end])
		s = math.sqrt(s)
		self.rawValue = s
		s = self.screen.next(s)
		self.currentValue = self.filter.next(s) * self.scaleFactor
		if self.printEnable:
			for k in range(self.start, self.end):
				print '%6.1f' % (data[k],),
			print

class Sid(threading.Thread):
	def __init__(self, parent, dirname, sampleRate, transformSize):
		threading.Thread.__init__(self)
		self.parent = parent
		self.dirname = dirname
		#self.sampleRate = sampleRate
		self.transformSize = transformSize

		self.update = True		# enable process() update

		# IIRFilter params default values - step response ~ 5.3 steps (@ 0.5 sec / sample)
		iirparams = {'wp': 0.025, 'ws':0.03, 'passBandLoss':0.1, 'stopBandAtt':40.0}	# IIRFilter params default values
		params =  ((SPECTRUMPLOTENABLE, 1), (SPECTRUMAVGENABLE, 1), (PROCESSUPDATEINTERVAL, 5.0),
					(PRINTOUTTYPE, 1), (PROCESSCOUNT, 10), (IIRPARAMS, iirparams),
					(IDATASTDFACTOR, 2.0), (PRINTOUTDIAG, 0), (BPFILTENABLE, 1),
					(WEIGHTINGTYPE, 1), (KAISERPARAM, 7))
		if sys.version_info[1] == 4:
			filename = 'sidMonitorDb.dat'
		else:
			filename = 'sidMonitorDb'
		self.db = DB(filename, params)
		for name, value in params:
			v = self.db.getValue(name)
			setattr(self, name, v)

		self.canvas = Canvas(self.parent, width=450, height=280, bg=BGCOLOR)
		self.canvas.pack(side=TOP)
		tag = 'none'

		# button for iirfilter coefficients GUI
		XBU = 20
		YBU = 30
		f = Frame(parent)
		button = Button(f, text='Track\nFilter', \
			command=lambda s=self, p=parent, c=self.updateIIRParams, n=IIRPARAMS: editIIRParams(s, p, c, n))
		button.pack(side=LEFT)
		f.pack(side=LEFT)
		self.canvas.create_window(XBU, YBU, window=f, anchor=W)

		# button for weighting type GUI
		XWT = XBU + 60
		YWT = YBU
		f = Frame(parent)
		button = Button(f, text='Weighting',
			command=lambda s=self : editWeighting(s, WEIGHTINGTYPE, KAISERPARAM))
		button.pack(side=LEFT)
		f.pack(side=LEFT)
		self.canvas.create_window(XWT, YWT, window=f, anchor=W)

		# Checkbutton for bandpass filter enable
		XLD = XBU
		YLD = YWT + 40
		f = Frame(self.parent)
		label = Label(f, text='BP Filter: ', bg=BGCOLOR, relief=FLAT, font=('Courier New', 10))
		label.pack(side=LEFT)
		self.bpFiltEnableVar = IntVar()
		self.bpFiltEnableVar.set(getattr(self, BPFILTENABLE))
		rb  = Checkbutton(f, text='', variable=self.bpFiltEnableVar, bg=BGCOLOR,
							command=self.bpFiltEnableProc)
		rb.pack(side=LEFT, anchor=W)
		f.pack(side=LEFT)
		self.canvas.create_window(XLD, YLD, window=f, anchor=W)

		# Entry fields for spectrum display
		XS = XLD
		YS = YLD + 30
		f = Frame(self.parent)
		label = Label(f, text='Display spectrum: ', bg=BGCOLOR, relief=FLAT, font=('Courier New', 10))
		label.pack(side=LEFT)
		self.spectrumPlotVar = IntVar()
		self.spectrumPlotVar.set(getattr(self, SPECTRUMPLOTENABLE))
		cb = Checkbutton(f, text='', state=NORMAL, anchor=W, variable=self.spectrumPlotVar, bg=BGCOLOR,
						 command=self.spectrumPlotProc)
		cb.pack(side=LEFT)

		# Entry field for spectrum display type (averaged or raw)
		label = Label(f, text='Avg: ', bg=BGCOLOR, relief=FLAT, font=('Courier New', 10))
		label.pack(side=LEFT)
		self.spectrumAvgEnableVar = IntVar()
		self.spectrumAvgEnableVar.set(getattr(self, SPECTRUMAVGENABLE))
		cb = Checkbutton(f, text='', state=NORMAL, anchor=W, variable=self.spectrumAvgEnableVar, bg=BGCOLOR,
						 command=self.spectrumAvgEnableProc)
		cb.pack(side=LEFT)
		f.pack(side=LEFT)
		self.canvas.create_window(XS, YS, window=f, anchor=W)

		# Radiobutton for print control
		XL = XS
		YL = YS + 25
		f = Frame(self.parent)
		label = Label(f, text='Print output:     ', bg=BGCOLOR, relief=FLAT, font=('Courier New', 10))
		label.pack(side=LEFT)
		self.printTypeRbVar = IntVar()
		self.printTypeRbVar.set(getattr(self, PRINTOUTTYPE))
		for text, value in (('None', NOPRINT), ('Normal', NORMALPRINT), ('Raw', RAWPRINT), ('exTime', EXPRINT)):
			rb  = Radiobutton(f, text=text, value=value, variable=self.printTypeRbVar, bg=BGCOLOR,
								command=lambda ix=value : self.printTypeRbProc(ix))
			rb.pack(side=LEFT, anchor=W)
		f.pack(side=LEFT)
		self.canvas.create_window(XL, YL, window=f, anchor=W)

		"""
		# Checkbutton for diagnostic print out
		XLD = XL + 380
		YLD = YL
		self.printTypeDiagVar = IntVar()
		self.printTypeDiagVar.set(getattr(self, PRINTOUTDIAG))
		f = Frame(parent)
		rb  = Checkbutton(f, text='Diag', variable=self.printTypeDiagVar, bg=BGCOLOR,
							command=self.printDiagOutProc)
		rb.pack(side=LEFT, anchor=W)
		f.pack(side=LEFT)
		self.canvas.create_window(XLD, YLD, window=f, anchor=W)
		"""

		XE = XS - 5
		YE = YS + 50
		self.intervalEntry = MyEntry(self, self.canvas,  XE, YE, 'Update interval:  ', 'Seconds', PROCESSUPDATEINTERVAL, tag, '%3.1f', width=5)
		self.countEntry = MyEntry(self, self.canvas,  XE, YE+25, 'Process average:  ', 'Cycles', PROCESSCOUNT, tag, '%3d', width=4)

		#Label for process update rate
		XP = XE + 5
		YP = YE + 50
		f = Frame(self.parent)
		Label(f, text='Actual interval:', bg=BGCOLOR, relief=FLAT, font=('Courier New', 10)).pack(side=LEFT)
		self.procIntervalLabel = Label(f, text='', bg=BGCOLOR, relief=FLAT, font=('Courier New', 10))
		self.procIntervalLabel.pack(side=RIGHT)
		f.pack(side=LEFT)
		self.canvas.create_window(XP, YP, window=f, anchor=W)

		# Labels for station names.
		XL1 = XE + 5
		YL1 = YP + 25
		f = Frame(self.parent)
		self.monLabel = Label(f, text='', bg=BGCOLOR, relief=FLAT, font=('Courier New', 10))	# Station name txt updated below.
		self.monLabel.pack(side=LEFT)
		f.pack(side=LEFT)
		self.canvas.create_window(XL1, YL1, window=f, anchor=W)

		# Labels for scalefactors
		XL2 = XL1
		YL2 = YL1 + 20
		f = Frame(self.parent)
		self.sfLabel = Label(f, text='', bg=BGCOLOR, relief=FLAT, font=('Courier New', 10))	# Scale factor text updated below.
		self.sfLabel.pack(side=LEFT)
		f.pack(side=LEFT)
		self.canvas.create_window(XL2, YL2, window=f, anchor=W)

		self.weightingType = None	# Updated in process()

		self.fmt = '%dh' % (transformSize, )
		parent.protocol("WM_DELETE_WINDOW", self.cleanup)

		self._stopEvent = threading.Event()
		self.updateEvent = threading.Event()

		self.months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')
		self.timePat = re.compile(r'\d\d\d\d-(\d\d)-(\d\d)T(\d\d:\d\d:\d\d)')		# for file time :: month, day, time(h:m:s)
		#self.timePat = re.compile(r'\d\d\d\d-(\d\d)-(\d\d)T(\d\d-\d\d)')		# for file time :: month, day, time(h:m)

		self.df = float(sampleRate) / transformSize

		# stations to be tracked.
		salpha = 0.25
		self.st1 = Track(20.900e3, 200.0, self.df, self.iirparams, salpha, scaleFactor=1.0, name='FTA')			# Lualualei, HI
		self.st2 = Track(23.400e3, 200.0, self.df, self.iirparams, salpha, scaleFactor=1.0, name='DHO38')	        # Harold E. Holt, Western Australia
		self.st3 = Track(26.700e3, 100.0, self.df, self.iirparams, salpha, scaleFactor=1.0, name='TBB')			# Cutler, ME
		self.st4 = Track(22.600e3, 100.0, self.df, self.iirparams, salpha, scaleFactor=1.0, name='HWU')			# Jim Creek, WA
		self.st5 = Track(19.580e3, 050.0, self.df, self.iirparams, salpha, scaleFactor=1.0, name='GBZ')			# LaMoure, ND

		#self.st1 = Track(18.1e3, 200.0, self.df, self.iirparams, salpha, scaleFactor=1.0, name='RLO')			# RDL
		#self.st2 = Track(18.2e3, 200.0, self.df, self.iirparams, salpha, scaleFactor=1.0, name='VTX')			# UNK
		#self.st3 = Track(18.3e3, 200.0, self.df, self.iirparams, salpha, scaleFactor=1.0, name='HWU')			# UNK
		#self.st4 = Track(18.6e3, 175.0, self.df, self.iirparams, salpha, scaleFactor=1.0, name='UNK')			# VTX
		#self.st5 = Track(18.9e3, 175.0, self.df, self.iirparams, salpha, scaleFactor=1.0, name='RKS')			# NWC Harold E. Holt, Western Australia

		self.plotDataSize = transformSize / 2

		# Class to handle plot generation
		#self.plotit = PlotIt(self.df, -30.0, 4, self.plotDataSize, 'monPlot.tmp')

		tmp = 'Tracking: '
		sftmp = 'SF:     '
		for k in range(len(Track.names)):
			name = Track.names[k]
			tmp += name + '  '
			sf = Track.scaleFactors[k]
			sftmp += '%5.1f' % (sf,)
		self.monLabel.configure(text=tmp)
		self.sfLabel.configure(text=sftmp)

		t = datetime.datetime.utcnow().isoformat()		# eg: 2011-04-17T16:02:08.328000
		print t
		dataFilename, self.dfile, header = self.getDataFile(t)
		print 'Filename=%s    df=%4.2f Hz' % (dataFilename, self.df)
		rawFilename = dataFilename.split('.')[0] + '.raw'
		#self.rfile = file(rawFilename, 'w')
		#self.rfile.write(header)

		self.s = GetSound(sampleRate, transformSize*2, 1)
		self.s.get()			# Discard first sample

		# Parameters for bandpass filter
		hsr = sampleRate / 2
		fp1 = 18e3; fs1 = 6e3
		wp1 = fp1 / hsr; ws1 = fs1 / hsr
		fp2 = 26e3; fs2 = 36e3
		wp2 = fp2 / hsr; ws2 = fs2 / hsr
		wp = [wp1, wp2]
		ws = [ws1, ws2]
		# wp, ws have must values 0 to 1 with 1 equivalent to half the sampling frequency
		self.bandPassFilt = iirdesign(wp, ws, 1.0, 60.0, ftype='butter')

		self.fftSf = transformSize * transformSize		# FFT scalefactor

	def updateIIRParams(self):
		# Callback function from iir filter params edit GUI.
		for f in Track.filters:
			f.init(**self.iirparams)

	def getDataFile(self, t):
		# Generate a new filename based on the date & time and open the file.
		dir = 'C:/garyr/sid'
		ye = t[2:4]
		mo = int(t[5:7])
		da = t[8:10]
		hr = t[11:13]
		filename = 'SM%s%s%s%s.dat' % (ye, self.months[mo-1], da, hr)
		pathname = os.path.join(dir, filename)
		dfile = file(pathname, 'w')

		tmp = Track.names[0]
		tmpsf = '%4.1f' % (Track.scaleFactors[0],)
		for k in range(1, len(Track.names)):
			tmp = '%s, %s' % (tmp, Track.names[k])
			tmpsf = '%s,  %4.1f' % (tmpsf, Track.scaleFactors[k])
		tmp = '# %s\n# %s\n# %s\n' % (t, tmp, tmpsf)
		dfile.write(tmp)							# Add comments to beginning of file (date/time, stations being monitored, scale factors)
		return pathname, dfile, tmp

	def printTypeRbProc(self, v):
		self.db.updateValue(PRINTOUTTYPE, v)
		setattr(self, PRINTOUTTYPE, v)
		if v == 0:
			# None rb clicked
			self.db.updateValue(PRINTOUTDIAG, v)
			setattr(self, PRINTOUTDIAG, v)
			#self.printTypeDiagVar.set(0)

	def bpFiltEnableProc(self):
		v = self.bpFiltEnableVar.get()
		self.db.updateValue(BPFILTENABLE, v)
		setattr(self, BPFILTENABLE, v)

	def printDiagOutProc(self):
		v = self.printTypeDiagVar.get()
		self.db.updateValue(PRINTOUTDIAG, v)
		setattr(self, PRINTOUTDIAG, v)

	def spectrumPlotProc(self):
		v = self.spectrumPlotVar.get()
		self.db.updateValue(SPECTRUMPLOTENABLE, v)
		setattr(self, SPECTRUMPLOTENABLE, v)

	def spectrumAvgEnableProc(self):
		v = self.spectrumAvgEnableVar.get()
		self.db.updateValue(SPECTRUMAVGENABLE, v)
		setattr(self, SPECTRUMAVGENABLE, v)

	def printEnableProc(self):
		v = self.printEnableVar.get()
		self.db.updateValue(PRINTENABLE, v)
		setattr(self, PRINTENABLE, v)

	def cleanup(self):
		self.dfile.close()
		#self.rfile.close()
		self.parent.destroy()

	def process(self):
		# This file invoked once each processing interval.
		t2 = time.clock()

		if self.weightingType != getattr(self, WEIGHTINGTYPE):
			self.weightingType = getattr(self, WEIGHTINGTYPE)
			if self.weightingType == 1:
				self.weighting = array(blackmanharris(transformSize))
			else:
				kp = getattr(self, KAISERPARAM)
				self.weighting = array(kaiser(transformSize, kp))

		avgPsd = zeros(self.plotDataSize)
		times = []
		rms = 0.0
		nAvg = 0
		maxIval = 0.0
		for k in range(int(getattr(self, PROCESSCOUNT))):
			t1 = time.clock()
			data = self.s.get()			# get the soundcard data
			t2 = time.clock()
			idata = array(struct.unpack(self.fmt, data))	# unpack it

			if (getattr(self, BPFILTENABLE)):
				# Pass the input data through a band-pass filter
				idata = lfilter(self.bandPassFilt[0], self.bandPassFilt[1], idata)

			mx = abs(max(idata))
			maxIval = max(maxIval, mx)
			rms += var(idata)

			wdat = idata * self.weighting		# Apply the weighting
			fdat = numpy.fft.rfft(wdat)			# Transform

			#mag = [(z.real * z.real) + (z.imag * z.imag) for z in fdat[:self.plotDataSize]]
			mag = fdat[:self.plotDataSize] * fdat[:self.plotDataSize].conj()
			mag = asarray(mag, dtype='d')	# Ignore warning, imaginary part is zero
			mag /= self.fftSf
			avgPsd = avgPsd + mag				#avgPsd = map(lambda x, y: x+y, avgPsd, mag)
			nAvg += 1
			t3 = time.clock()
			t12 = (t2 - t1) * 1000.0
			t23 = (t3 - t2) * 1000.0
			times.append((t12, t23))

		if (getattr(self, PRINTOUTTYPE) == EXPRINT):
			for t in times:
				t12, t23 = t
				print 't12=%8.2f ms   t23=%8.1f ms' % (t12, t23)
			print
		rms = math.sqrt(rms/nAvg)
		avgPsd /= nAvg			#avgPsd = [x / nAvg for x in avgPsd]

		for update in Track.updates:
			update(avgPsd)

		t = datetime.datetime.utcnow().isoformat()		#eg: '2011-04-17T16:02:08.328000'
		mo, da, tod = self.timePat.findall(t)[0]
		mo = self.months[int(mo)-1]
		if tod[:5] == '00:00':
			self.dfile.close()										# Close the current files
			filename, self.dfile, header = self.getDataFile(t)		# Start a new file

			#self.rfile.close()
			#rawFilename = filename.split('.')[0] + '.raw'
			#self.rfile = file(rawFilename, 'w')
			#self.rfile.write(header)

		c1, c2, c3,c4, c5 = self.st1.currentValue, self.st2.currentValue, self.st3.currentValue, self.st4.currentValue, self.st5.currentValue
		tmp = '%s:%s:%s %8.3f %8.3f %8.3f %8.3f %8.3f\n' % (mo, da, tod, c1, c2, c3, c4, c5)
		r1, r2, r3,r4, r5 = self.st1.rawValue, self.st2.rawValue, self.st3.rawValue, self.st4.rawValue, self.st5.rawValue
		rtmp = '%s:%s:%s %8.3f %8.3f %8.3f %8.3f %8.3f\n' % (mo, da, tod, r1, r2, r3, r4, r5)
		try:
			self.dfile.write(tmp)
			#self.rfile.write(rtmp)
		except (IOError, ValueError):			# may occur during shutdown
			return

		hms = t[11:19]		#hh:mm:ss
		ot = getattr(self, PRINTOUTTYPE)
		if ot == RAWPRINT:
			print '%8s %6.1f %6.1f %6.1f %6.1f %6.1f   %6.0f %6.0f' % (hms, r1,r2, r3, r4, r5, rms, maxIval)
		elif ot == NORMALPRINT:
			print '%8s %6.1f %6.1f %6.1f %6.1f %6.1f   %6.0f %6.0f' % (hms, c1,c2, c3, c4, c5, rms, maxIval)

		# Note: in the following avgPsd and mag are numpy arrays.
		if getattr(self, SPECTRUMPLOTENABLE):
			if getattr(self, SPECTRUMAVGENABLE):
				magdb = (10.0*log10(avgPsd))			# Average of all records
			else:
				magdb = (10.0*log10(mag))			# Last record
			self.plotit.next(magdb)

	def run(self):
		# Process control stuff:
		TF = Filter(0.3, startUpCount=1)
		waitTime = getattr(self, PROCESSUPDATEINTERVAL)
		tlast = 0.0
		while 1:
			self.updateEvent.wait(timeout=waitTime)
			if self._stopEvent.isSet():
				break
			if self.update:
				ttop = time.clock()
				if tlast > 0:
					dt = ttop - tlast			# Duration of last process interval
					err = getattr(self, PROCESSUPDATEINTERVAL) - dt
					waitTime = TF.next(waitTime + err)
					waitTime = max(waitTime, 0.0)
					#print 'et: %6.3f   err: %6.3f  waitTime: %6.3f' % (dt, err, waitTime)
					self.procIntervalLabel.configure(text='%4.2f (%4.2f) Sec' % (dt, waitTime))
				tlast = ttop
				self.process()

	def join(self, timeout=None):
		self._stopEvent.set()
		threading.Thread.join(self, timeout)

class PlotIt(object):
	def __init__(self, df, minPlotVal, plotStart, plotSize, plotFilename):
		self.minPlotVal = minPlotVal
		self.plotStart = plotStart
		self.plotSize = plotSize
		self.plotFilename = plotFilename
		self.xlabels = [df * k for k in range(plotSize)]
		self.plot = Gnuplot.Gnuplot()

	def next(self, dat):
		plotFile = file(self.plotFilename, 'w')
		for k in range(self.plotStart, self.plotSize):
			m = max(dat[k], -30.0)
			tmp = '%6.2f  %6.2f\n' % (self.xlabels[k], m)
			plotFile.write(tmp)
		plotFile.close()
		self.plot('reset')
		self.plot('set style data lines')
		self.plot('set grid')
		self.plot('set ylabel "20*log10(|X|)"')
		self.plot('set xlabel "Frequency - Hz"')
		self.plot('set key top left')
		f = Gnuplot.File(self.plotFilename, title='VLF Spectrum')
		f.set_option(using=(1,2))
		f.set_option(with_='lines')
		self.plot.plot(f)

if __name__ == '__main__':
	root = Tk()
	root.title("Sid Monitor")
	#root.iconbitmap('sid.ico')
	dirname = os.getcwd()
	sampleRate = 96000
	transformSize = 4096
	s = Sid(root, dirname, sampleRate, transformSize)
	s.start()
	root.mainloop()

