import Gnuplot, Gnuplot.funcutils
import string
+import time
+import math
+import cmath
+import random
+import numpy
gnuplot = Gnuplot.Gnuplot()
a = f.split("/")
return string.join(a[start:(len(a)-back)], "/")
-def GetData(filename):
+def GetData(filename, key=1):
input_file = open(filename, "r")
- data = []
+ data = {}
for line in input_file:
line = re.sub("#.*", "", line).strip("\r\n ")
if len(line) == 0:
continue
- data.append(map(lambda e : float(e), line.split("\t")))
- return data
+
+ line = map(lambda e : float(e), line.split("\t"))
+
+ if line[key] in data:
+ for i in range(len(line)):
+ data[line[key]][0][i] += line[i]
+ data[line[key]][1] += 1
+ else:
+ data.update({line[key] : [line, 1]})
+
+ d = map(lambda e : map(lambda f : float(f) / float(e[1][1]), e[1][0]), data.items())
+ d.sort(key = lambda e : e[key])
+ #for l in d:
+ # print str(l)
+ return d
def DoNothing(data):
return data
deltaI += dI[1]
count += 1
- deltaI /= float(count)
- deltaE /= float(count)
+ if (count > 0):
+ deltaI /= float(count)
+ deltaE /= float(count)
- if (deltaE != 0):
- result[len(result)-1][b] = (deltaI / deltaE)
+ if (deltaE != 0):
+ result[len(result)-1][b] = (deltaI / deltaE)
+ else:
+ result[len(result)-1][b] = 0.0
else:
result[len(result)-1][b] = 0.0
result.append([])
out.write("\t")
out.write("\n")
-def AverageAllData(directory, save=None)
+def AverageAllData(directory, save=None):
data_sets = []
- if save == None: save = directory+"/average.dat":
+ if save == None: save = directory+"/average.dat"
for d in FindDataFiles(directory):
data_sets.append(GetData(d))
data[i][3] = ammeter_scale * 0.170 * float(data[i][3]) / 268.0
return data
-def ShowTCS(filename, calibrate=True, normalise=False, show_error=False, plot=gnuplot.plot,with_="lp", step=1, output=None, title=""):
+def ShowTCS(filename, raw=True,calibrate=True, normalise=False, show_error=False, plot=gnuplot.plot,with_="lp", step=1, output=None, title="", master_title="", smooth=0, show_peak=True, inflection=1):
+
+ if raw == False:
+ calibrate = False
+ normalise = False
+
if type(filename) == type(""):
data = GetData(filename)
else:
if (len(data) <= 0):
return data
+ if (smooth > 0):
+ if type(smooth) == type([]):
+ for i in range(smooth[0]):
+ data = Smooth(data, m=smooth[1])
+ else:
+ data = Smooth(data, m=smooth)
+
+
if calibrate:
data = CalibrateData(data)
units = ["V", "uA / V"]
gnuplot("set term png size 640,480")
gnuplot("set output \""+str(output)+"\"")
- gnuplot("set title \"Total Current Spectrum S(E)\"")
+ if master_title == "":
+ master_title = "Total Current Spectrum S(E)"
+ if type(filename) == type("") and plot == gnuplot.plot:
+ if filename != "tcs data":
+ p = ReadParameters(filename)
+ if "Sample" in p:
+ master_title += "\\nSample: "+p["Sample"]
+
+ gnuplot("set title \""+str(master_title)+"\"")
gnuplot("set xlabel \"U ("+str(units[0])+")\"")
- d = Derivative(data, 1, 2, step=step)
+ if raw:
+ d = Derivative(data, 1, 2, step=step)
+ else:
+ d = data
+
+ ymax = 0.01 + 1.2 * max(d, key=lambda e : e[2])[2]
+ ymin = -0.01 + 1.2 * min(d, key=lambda e : e[2])[2]
+ gnuplot("set yrange ["+str(ymin)+":"+str(ymax)+"]")
+
+ plotList = []
+ plotList.append(Gnuplot.Data(d, using="2:3", with_=with_,title=title))
- plot(Gnuplot.Data(d, using="2:3", with_=with_,title=title))
if (show_error):
error1 = Derivative(data, 1, 2, -3,step=step)
error2 = Derivative(data, 1, 2, +3,step=step)
- gnuplot.replot(Gnuplot.Data(error1, using="2:3", with_=w,title="-sigma/2"))
- gnuplot.replot(Gnuplot.Data(error2, using="2:3", with_=w, title="+sigma/2"))
+ plotList.append(Gnuplot.Data(error1, using="2:3", with_=w,title="-sigma/2"))
+ plotList.append(Gnuplot.Data(error2, using="2:3", with_=w, title="+sigma/2"))
+ if (show_peak):
+ peak = SmoothPeakFind(d, ap=DoNothing, stop=1, inflection=inflection)
+ plotList += PlotPeaks(peak,with_="l lt -1", plot=None)
+
+
+
+ if (plot != None):
+ plot(*plotList)
+ time.sleep(0.2)
+
if (output != None and type(output) == type("")):
gnuplot("set term wxt")
+
+ if (plot == None):
+ return plotList
return data
-def ShowData(filename,calibrate=True, normalise=False, show_error=False, plot=gnuplot.plot,with_="lp", step=1, output=None, title=""):
+def ShowData(filename,calibrate=True, normalise=False, show_error=False, plot=gnuplot.plot,with_="lp", step=1, output=None, title="", master_title="Sample Current I(E)", smooth=0):
if type(filename) == type(""):
data = GetData(filename)
else:
if (title == ""):
title = BaseName(filename)
+
if len(data) <= 0:
return data
+
+
+ if (smooth > 0):
+ data = Smooth(data)
+
if calibrate:
data = CalibrateData(data)
units = ["V", "uA"]
gnuplot("set term png size 640,480")
gnuplot("set output \""+str(output)+"\"")
- gnuplot("set title \"Sample Current I(E)\"")
+ gnuplot("set title \""+str(master_title)+"\"")
gnuplot("set xlabel \"U ("+str(units[0])+")\"")
#d = Derivative(data, 1, 2, step=step)
+
+ plotList = []
- plot(Gnuplot.Data(data, using="2:3", with_=with_,title=title))
+ plotList.append(Gnuplot.Data(data, using="2:3", with_=with_,title=title))
+ time.sleep(0.1)
if (show_error):
error1 = copy.deepcopy(data)
error2 = copy.deepcopy(data)
#print str(data[i])
error1[i][2] -= 0.50*float(data[i][3])
error2[i][2] += 0.50*float(data[i][3])
- gnuplot.replot(Gnuplot.Data(error1, using="2:3", with_=w,title="Error : Low bound"))
- gnuplot.replot(Gnuplot.Data(error2, using="2:3", with_=w, title="Error : Upper bound"))
+ plotList.append(Gnuplot.Data(error1, using="2:3", with_=w,title="Error : Low bound"))
+ plotList.append(Gnuplot.Data(error2, using="2:3", with_=w, title="Error : Upper bound"))
+
+ if plot != None:
+
+ plot(*plotList)
+ if (output != None and type(output) == type("")):
+ gnuplot("set term wxt")
+ return data
+ else:
+ return plotList
+
+def ReadParameters(filename):
+ parameters = odict.odict()
+ input_file = open(filename, "r")
+ for line in input_file:
+ k = line.split("=")
+ item = None
+ #print str(k)
+ if (len(k) >= 2):
+ item = k[0].strip("# \r\n")
+ value = k[1].strip("# \r\n")
+ if (item in parameters):
+ parameters[item] = value
+ else:
+ parameters.update({str(item) : value})
+ input_file.close()
+ return parameters
+
+def PlotParameters(filename):
+ ReadParameters(filename)
+
+def Smooth(data, m, k=2):
+ smooth = copy.deepcopy(data)
+ for i in range(len(smooth)):
+ count = 0
+ smooth[i][k] = 0.0
+ for j in range(i-m,i+m):
+ if j >= 0 and j < len(smooth):
+ count += 1
+ smooth[i][k] += data[j][k]
+ if count > 0:
+ smooth[i][k] = smooth[i][k] / float(count)
+ else:
+ smooth[i][k] = data[i][k]
+
+ return smooth
+
+def PeakFind(data, k=2,threshold=0.00, inflection=0):
+ results = []
+ for i in range(len(data)):
+ if i == 0 or i == len(data)-1:
+ continue
+ #if abs(data[i][k]) < threshold * abs(max(data, key = lambda e : abs(e[k]))[k]):
+ # continue
+
+ left = data[i-1][k] - data[i][k]
+ right = data[i+1][k] - data[i][k]
+ if abs(left) < threshold*abs(data[i][k]):
+ continue
+ if abs(right) < threshold*abs(data[i][k]):
+ continue
+ if left*right > 0:
+ results.append(data[i] + [inflection])
+
+ if inflection > 0:
+ results += PeakFind(Derivative(data), k=k, threshold=threshold, inflection=inflection-1)
+
+ return results
+
+def SmoothPeakFind(data, a=1, k=2, ap=DoNothing, stop=10,smooth=5, inflection=0):
+ s = data
+ #results = []
+
+ peakList = []
+
+ m = 0
+ while m < stop:
+ #results.append([])
+ peaks = PeakFind(ap(s),k=k, inflection=inflection)
+ #print "m = " +str(m)
+ for p in peaks:
+ add = [m]
+ [add.append(f) for f in p]
+
+ if m == 0:
+ #print "*New peak at " + str(p)
+ peakList.append([add])
+ else:
+ score = []
+ for i in range(len(peakList)):
+ p2 = peakList[i][len(peakList[i])-1]
+ if m - p2[0] > 1:
+ continue
+ score.append([i, abs(p[a] - p2[1+a])])
+
+ score.sort(key = lambda e : e[1])
+ if len(score) == 0 or score[0][1] > 100:
+ #print "New peak at " + str(p)
+ peakList.append([add])
+ else:
+ #print "Peak exists near " + str(p) + " ("+str(score[0][1])+") " + str(peakList[score[0][0]][len(peakList[score[0][0]])-1])
+ peakList[score[0][0]].append(add)
+
+
+
+ #results.append([m, []])
+ #[results[len(results)-1].append(f) for f in p]
+ m += 1
+ s = Smooth(s, m=smooth,k=k)
+
+ #results.sort(key = lambda e : e[2])
+
+ #peaks = []
+ return peakList
+
+
+
+def PlotPeaks(peaks, calibrate=True, with_="lp", plot=gnuplot.replot):
+
+ plotList = []
+ for p in peaks:
+ p.append(copy.deepcopy(p[len(p)-1]))
+
+ p[len(p)-1][0] += 1
+
+
+ #print "Adding " + str(p) + " to list"
+ if len(p) >= 0:
+ l = p[len(p)-1]
+ if l[len(l)-1] < 1:
+ with_ = with_.split(" lt")[0] + " lt 9"
+ plotList.append(Gnuplot.Data(p, using="3:1", with_=with_))
+
- if (output != None and type(output) == type("")):
- gnuplot("set term wxt")
- return data
+ if len(plotList) > 0 and plot != None:
+ plot(*plotList)
+ time.sleep(0.2)
+
+ #print str(plotList)
+ #for p in peaks:
+ # p = p[0:len(p)-1]
+ return plotList
+
def main():
- return 0
+
if (len(sys.argv) < 2):
sys.stderr.write(sys.argv[0] + " - Require arguments (filename)\n")
return 1
- tcs = []
- gnuplot("set style data lp")
- gnuplot("set key outside right")
- #gnuplot("set title \"Au on Si (50min 3.5A 3-6 e-8mbar)\"")
- #gnuplot("set xlabel \"E (DAC Counts)\"")
- #gnuplot("set ylabel \"S(E) (ADC/DAC Counts)\"")
- #gnuplot("set term postscript colour")
- #gnuplot("set output \"test.eps\"")
- for i in range(1, len(sys.argv)):
- if (len(tcs[i-1]) > 0):
- gnuplot.replot(Gnuplot.Data(tcs[i-1], title=sys.argv[i], with_="lp"))
-
- # Now average the data
+ i = 1
+ plotFunc = ShowTCS
+ normalise = False
+ title = ""
+ master_title = ""
+ while i < len(sys.argv):
+ if sys.argv[i] == "--raw":
+ plotFunc = ShowData
+ elif sys.argv[i] == "--tcs":
+ plotFunc = ShowTCS
+ elif sys.argv[i] == "--output":
+ if i+1 >= len(sys.argv):
+ sys.stderr.write("Need argument for "+sys.argv[i]+" switch\n")
+ sys.exit(1)
+ gnuplot("set term postscript colour")
+ gnuplot("set output \""+sys.argv[i+1]+"\"")
+ i += 1
+ elif sys.argv[i] == "--wxt":
+ gnuplot("set term wxt")
+ elif sys.argv[i] == "--normalise":
+ normalise = True
+ elif sys.argv[i] == "--unnormalise":
+ normalise = False
+ elif sys.argv[i] == "--title":
+ if i+1 >= len(sys.argv):
+ sys.stderr.write("Need argument for "+sys.argv[i]+" switch\n")
+ sys.exit(1)
+ title = sys.argv[i+1]
+ i += 1
+ elif sys.argv[i] == "--master_title":
+ if i+1 >= len(sys.argv):
+ sys.stderr.write("Need argument for "+sys.argv[i]+" switch\n")
+ sys.exit(1)
+ master_title = sys.argv[i+1]
+ i += 1
+ else:
+ plotFunc(sys.argv[i], plot=gnuplot.replot, normalise=normalise, title=title, master_title=master_title)
+
+ i += 1
+
+ print "Done. Press enter to exit, or type name of file to save as."
+ out = sys.stdin.readline().strip("\t\r\n #")
+ if out != "":
+ gnuplot("set term postscript colour")
+ gnuplot("set output \""+out+"\"")
+ gnuplot.replot()
+
+
+def ModelTCS(f, sigma, Emin, Emax, dE):
+ data = []
+ E = Emin
+ while E < Emax:
+ S = (1 - sigma(0))*f(-E) + FuncIntegrate(lambda e : f(e - E) * FuncDerivative(sigma, E, dE), Emin, Emax, dE)
+ data.append([0.00, E, S,0.00])
+ E += dE
+ return data
+
+def IntegrateTCS(data, imin, imax=0, di=1):
+ i = imin
+ if imax == 0:
+ imax = len(data)-1
+ total = 0.0
+ while i < imax:
+ total += data[i][2] * (data[i+1][1] - data[i][1])
+ i += di
+ return total
+
+def FuncIntegrate(f, xmin, xmax, dx):
+ x = xmin
+ total = 0.0
+ while x <= xmax:
+ total += f(x) * dx
+ x += dx
+ return total
+
+def FuncDerivative(f, x, dx):
+ return 0.50*(f(x+dx) - f(x-dx))/dx
+
+def FitTCS(data, min_mse=1e-4, max_fail=100, max_adjust=4,divide=10, plot=gnuplot.plot,smooth=0):
+ if type(data) == type(""):
+ d = GetData(data)
+ d = CalibrateData(d)
+ d = MaxNormalise(d)
+ d = Derivative(d)
+ else:
+ d = data
+
+ if smooth != 0:
+ if type(smooth) == type([]):
+ for _ in range(smooth[0]):
+ d = Smooth(d, m=smooth[1])
+ else:
+ d = Smooth(d, m=smooth)
- avg = Average(tcs)
- for a in avg:
- sys.stdout.write(str(a[0]) + "\t" + str(a[1]) + "\t" + str(a[1]) + "\n")
- gnuplot.replot(Gnuplot.Data(avg, title="Average", with_="l lw 2"))
+
+ plotItems = ShowTCS(d, raw=False,smooth=smooth,plot=None)
+ plotItems.append(None)
- sys.stdout.write("Save averaged data as (blank for no save): ")
- filename = sys.stdin.readline().strip(" \r\n\t")
- if (filename != ""):
- SaveData(filename, avg)
+ peaks = SmoothPeakFind(d, smooth=5, stop=1, inflection=0)
+ peaks.sort(key = lambda e : e[len(e)-1][1])
+
+ fits = []
+
+ for i in range(0,len(peaks)):
- return 0
+ p = peaks[i]
+ l = p[len(p)-1]
+ if l[len(l)-1] == 0:
+ fits.append([l[3], l[2], 1.0])
+ else:
+ if i-2 >= 0:
+ l = peaks[i-2][len(peaks[i-2])]
+ if l[len(l)-1] == 0:
+ fits.append([l[3], l[2], 1.0])
+ if i+2 <= len(peaks)-1:
+ l = peaks[i+2][len(peaks[i+2])]
+ if l[len(l)-1] == 0:
+ fits.append([l[3], l[2], 1.0])
+
+ for i in range(len(fits)):
+ left = 2.0
+ right = 2.0
+ if i > 0:
+ left = fits[i-1][1] - fits[i][1]
+ if i < len(fits)-1:
+ right = fits[i+1][1] - fits[i][1]
+
+ fits[i][2] = min([abs(0.5*left), abs(0.5*right)])
+
+
+ #print "Fits are " + str(fits)
+ #stdin.readline()
+
+
+
+ def tcs(E):
+ total = 0.0
+ for f in fits:
+ dt = f[0] * gaussian(E - f[1], f[2])
+ #print " Increase total by " + str(dt)
+ total += dt
+ #print "tcs returns " + str(total)
+ return total
+
+ mse = 1
+ old_mse = 1
+ cycle = 0
+ failcount = 0
+
+
+ adjust = 1.0
+
+ iterations = 0
+
+ while failcount < max_fail and mse > min_mse:
+ i = random.randint(0, len(fits)-1)
+ j = random.randint(0, len(fits[i])-1)
+ #while j == 1:
+ # j = random.randint(0, len(fits[i])-1)
+
+ #print "Adjust " + str(i) + ","+str(j) + ": Iteration " + str(iterations) + " mse: " + str(mse)
+
+ old = fits[i][j]
+ old_mse = mse
+
+ fits[i][j] += adjust * (random.random() - 0.50)
+ if i == 2:
+ while fits[i][j] <= 0.0005:
+ fits[i][j] = adjust * (random.random() - 0.50)
+
+
+ model = table(lambda e : [0.00, e, tcs(e), 0.00], 0, 16.8, divide*d[len(d)-1][1]/(len(d)))
+ mse = MeanSquareError(model, d[0::divide])
+ if mse >= old_mse:
+ fits[i][j] = old
+ failcount += 1
+ if failcount > max_fail / 2:
+ if adjust > 1.0/(2.0**max_adjust):
+ adjust /= 2
+ mse = old_mse
+ else:
+ #adjust /= 2.0
+ failcount = 0
+
+
+ iterations += 1
+
+
+ #model = table(lambda e : [0.00, e, tcs(e), 0.00], 0, 16.8, 16.8/len(d))
+ plotItems[len(plotItems)-1] = Gnuplot.Data(model, using="2:3", with_="l lt 3", title="model")
+ time.sleep(0.1)
+
+ fits.sort(key = lambda e : e[0] * gaussian(0, e[2]), reverse=True)
+
+ if plot != None:
+ gnuplot("set title \"MSE = "+str(mse)+"\\nfailcount = "+str(failcount)+"\\nadjust = "+str(adjust)+"\"")
+ gnuplot.plot(*plotItems)
+
+ return [fits, model]
+ else:
+ return [fits, model,plotItems]
+
+
+ #return model
+
+def SaveFit(filename, fit):
+ out = open(filename, "w", 0)
+ out.write("# TCS Fit\n")
+
+ for f in fit:
+ out.write(str(f[0]) + "\t" + str(f[1]) + "\t" + str(f[2]) + "\n")
+
+ out.close()
+
+
+def LoadFit(filename):
+ infile = open(filename, "r")
+ if (infile.readline() != "# TCS Fit\n"):
+ sys.stderr.write("Error loading fit from file " + str(filename) + "\n")
+ sys.exit(0)
+
+ fit = []
+ while True:
+ f = infile.readline().strip("# \r\n\t").split("\t")
+ if len(f) != 3:
+ break
+ fit.append(map(float, f))
+
+ infile.close()
+ fit.sort(key = lambda e : e[0] * gaussian(0, e[2]), reverse=True)
+ #def model(e):
+ # total = 0.0
+ # for f in fit:
+ # total += f[0] * gaussian(e - f[1], f[2])
+ # return total
+
+ #return table(lambda e : [0.0, e, model(e), 0.0], 0.0, 16.8, 16.8/400)
+ return fit
+
+def MeanSquareError(model, real, k = 2):
+ mse = 0.0
+ for i in range(len(real)):
+
+ mse += (model[i][k] - real[i][k])**2
+
+ mse /= len(model)
+ return mse
+
+def delta(x):
+ if (x == 0):
+ return 1.0
+ else:
+ return 0.0
+
+def table(f, xmin, xmax, dx):
+ result = []
+ x = xmin
+ while (x <= xmax):
+ result.append(f(x))
+ x += dx
+ return result
+
+def gaussian(x, sigma):
+ if (sigma == 0.0):
+ return 0.0
+ return math.exp(- (x**2.0)/(2.0 * sigma**2.0)) / (sigma * (2.0 * math.pi)**0.50)
+def step(x, sigma, T):
+ if T == 0:
+ return 1.0
+ return 1.0 / (math.exp((x - sigma)/T) + 1.0)
if __name__ == "__main__":
sys.exit(main())