Automatic commit. Sun Oct 14 00:00:08 WST 2012
[matches/honours.git] / research / TCS / interface.py
index 1a1e925..7553ab4 100755 (executable)
@@ -12,7 +12,11 @@ import time
 import serial
 import datetime
 
+import odict
+import Gnuplot, Gnuplot.funcutils
+import subprocess
 
+gnuplot = Gnuplot.Gnuplot()
 
 # TODO: Insert variables for calibration purposes here.
 calibrate = {
@@ -31,14 +35,15 @@ calibrate = {
 }
 
 # TODO: Adjust aqcuisition parameters here
-aquire = { "DAC_Sweep" : "0.0 + 250.0*int(step/1000)", # DAC Sweep value (t is in STEPS, not seconds!)
-       "ADC_Averages" : 200,
-       "ADC_Vi" : 5, # ADC channel to read back Vi (set by DAC) through
-       "ADC_Is" : 4, # ADC channel to read back Is through
-       "ADC_Ie" : 4, # ADC channel to read back Ie through
+aquire = { "DAC_Sweep" : "0.0 + 1.0*int(step)", # DAC Sweep value (t is in STEPS, not seconds!)
+       "ADC_Averages" : 100,
+       #"ADC_Vi" : 5, # ADC channel to read back Vi (set by DAC) through
+       #"ADC_Is" : 4, # ADC channel to read back Is through
+       #"ADC_Ie" : 4, # ADC channel to read back Ie through
        "DAC_Settle" : 0.0, # Time in seconds to wait for DAC to stabilise
        #"response_wait" : 0.2, # Time to wait in seconds between sending data and reading back
-       "start_date" : None
+       "start_date" : None,
+       "open_files" : []
 }
 
 #Setup the serial connection parameters
@@ -54,22 +59,37 @@ ser = serial.Serial(
        xonxoff=0,
        rtscts=0
 )
-
-parameters = {
-       "Accelerating Voltage" : None,
-       "Focus Voltage" : None,
-       "Deflection Voltage" : None,
-       "Venault Voltage" : None,
-       "Initial Voltage" : None,
-       "Heating Current" : None,
-       "Heating Voltage" : None,
-       "Chamber Pressure" : None,
-       "602 0.1 Battery" : None,
-       "602 0.03 Battery" : None,
-       "602 0.01 Battery" : None,
-       "602 0.003 Battery" : None,
-       "602 0.001 Battery" : None
-}
+#Using an ordered dictionary, so results will be determined (or prompted for) in this order.
+# Put things that are being changed a lot near the top of the list.
+parameters = odict.odict([
+       ("Chamber Pressure" , None), # Chamber pressure now automatically determined
+       ("Deflection Voltage" , None),
+       ("Title" , None),
+       ("Comment" , None),
+       ("602 Scale" , None),
+       ("Venault Voltage" , None),
+       ("Accelerating Voltage" , None),
+       ("Focus Voltage" , None),
+       
+       ("Initial Voltage" , None),
+       ("Heating Current" , None),
+       ("Heating Voltage (across filament)" , None),
+       ("Heating Voltage (across power supply)", None),
+       #("610B Zero" , None),
+       ("602 Zero" , None),
+       #("610B Scale" , None),
+       
+       ("602 0.1 Battery" , None),
+       ("602 0.03 Battery" , None),
+       ("602 0.01 Battery" , None),
+       ("602 0.003 Battery" , None),
+       ("602 0.001 Battery" , None), 
+       ("Sample", None),
+       ("Sample Angle", None),
+       ("ADC Regulator" , None),
+       ("Data" , None),
+       ("Parameters last checked", None)
+])
 
 def getTime():
        return str(datetime.datetime.now()).split(" ")[1].split(".")[0].replace(":","")
@@ -77,9 +97,68 @@ def getTime():
 def getDate():
        return str(datetime.datetime.now()).split(" ")[0]
 
-def init():
+def getPressure():
+       
+       try:
+               p = subprocess.Popen("./pressure/get_pressure.sh", stdout=subprocess.PIPE)
+               #p = subprocess.Popen("./this_program_does_not_exist.sh", stdout=subprocess.PIPE)
+               #result = float("a")
+               result = float(p.stdout.readline().strip(" \r\n\t"))
+       except:
+               return 0.0
+       return result
+       
+
+# Used for when I press Control-C to stop things
+def set_exit_handler(func):
+    if os.name == "nt":
+        try:
+            import win32api
+            win32api.SetConsoleCtrlHandler(func, True)
+        except ImportError:
+            version = ".".join(map(str, sys.version_info[:2]))
+            raise Exception("pywin32 not installed for Python " + version)
+    else:
+        import signal
+        signal.signal(signal.SIGTERM, func)
+       signal.signal(signal.SIGINT, func)
+
+def killed_handler(signal, frame):
+       reason = ""
+       sys.stdout.write("\n# Reason for killing program? ")
+       reason = sys.stdin.readline().strip("\r\n ")
+       for out in aquire["open_files"]:
+               sys.stdout.write("# Closing file " + str(out) + "\n")
+               out.write("# Recieved KILL signal.\n# Reason: " + str(reason) + "\n")
+               log_close(out)
 
        
+
+def cleanup():
+       for out in aquire["open_files"]:
+               out.write("# Program exits.\n")
+               log_close(out)
+
+def log_open(a, b):
+       result = open(a, b,0)
+       if (b == "w"):
+               result.write("# File opened at " + str(datetime.datetime.now()) + "\n")
+               aquire["open_files"].append(result)
+       return result
+
+def log_close(afile):
+       if (afile in aquire["open_files"]):
+               afile.write("# File closed at " + str(datetime.datetime.now()) + "\n")
+               aquire["open_files"].remove(afile)
+       
+       afile.close()
+
+
+def init():
+       #import atexit
+       #atexit.register(cleanup)
+       set_exit_handler(killed_handler)
+       
        aquire["start_date"] = getDate()
 
 
@@ -92,90 +171,173 @@ def init():
 #              pass
        #while (ser.readline().strip("\r\n ") != "#"):
        #       pass
-       time.sleep(1.0)
+       #time.sleep(1.0)
 
        ser.write("a "+str(aquire["ADC_Averages"]) + "\r\n")
-       print(ser.readline().strip("\r\n"))
-       print(ser.readline().strip("\r\n"))
-       print(ser.readline().strip("\r\n"))
+       ser.readline().strip("\r\n")
+       ser.readline().strip("\r\n")
+       ser.readline().strip("\r\n")
+       #print(ser.readline().strip("\r\n"))
+       #print(ser.readline().strip("\r\n"))
+       #print(ser.readline().strip("\r\n"))
 
-       print("Writing config information to config.dat...")
-       output = open("config.dat", "w", 1)
+       #print("Writing config information to config.dat...")
+       #output = log_open("config.dat", "w", 1)
 
-       output.write("# Initialise " + str(datetime.datetime.now()) + "\n")
+       #output.write("# Initialise " + str(datetime.datetime.now()) + "\n")
 
-       for field in calibrate:
-               output.write("# calibrate["+str(field)+"] = "+str(calibrate[field]) + "\n")
-       output.write("\n")
-       for field in aquire:
-               output.write("# aquire["+str(field)+"] = "+str(aquire[field]) + "\n")
+       #for field in calibrate:
+       #       output.write("# calibrate["+str(field)+"] = "+str(calibrate[field]) + "\n")
+       #output.write("\n")
+       #for field in aquire:
+       #       output.write("# aquire["+str(field)+"] = "+str(aquire[field]) + "\n")
 
-       output.write("# Ready " + str(datetime.datetime.now()) + "\n# EOF\n")
-       output.close()
+       #output.write("# Ready " + str(datetime.datetime.now()) + "\n# EOF\n")
+       #output.close()
 
 def main():
 
        init()
        
-       if (loadCalibration_DAC() == False):
-               if (calibrateDAC() == False):
-                       return -1
-       if (loadCalibration_ADC(aquire["ADC_Is"]) == False):
-               if (calibrateADC_usingDAC(aquire["ADC_Is"], False) == False):
-                       if (calibrateADC(aquire["ADC_Is"]) == False):
-                               return -1
-
-       if (loadCalibration_ADC(aquire["ADC_Vi"]) == False):
-               if (calibrateADC_usingDAC(aquire["ADC_Vi"], True) == False):
-                       if (calibrateADC(aquire["ADC_Vi"]) == False):
-                               return -1
+       # I haven't ever used calibrated results, and yet this code is still here, why???
+       #if (loadCalibration_DAC() == False):
+       #       if (calibrateDAC() == False):
+       #               return -1
+       #if (loadCalibration_ADC(aquire["ADC_Is"]) == False):
+       #       if (calibrateADC_usingDAC(aquire["ADC_Is"], False) == False):
+       #               if (calibrateADC(aquire["ADC_Is"]) == False):
+       #                       return -1
+
+       #if (loadCalibration_ADC(aquire["ADC_Vi"]) == False):
+       #       if (calibrateADC_usingDAC(aquire["ADC_Vi"], True) == False):
+       #               if (calibrateADC(aquire["ADC_Vi"]) == False):
+       #                       return -1
        
 
        # Make directory for today, backup calibration files
        os.system("mkdir -p " + getDate())
-       os.system("cp *.dat " + getDate() +"/")
+       #os.system("cp *.dat " + getDate() +"/")
 
-       #checkList()
+       checkList()
 
        
        
+               
 
        # Experiment
        # TODO: Modify data to record here
        sweep = 1
-       #record_data([4, 5], getDate()+"/"+str(getTime())+".dat", None, None, "Measure emission&sample current varying with time, constant initial energy.")
+       #for i in range(0,1):
        while True:
                os.system("mkdir -p " + getDate())
-               record_data([4, 5], getDate()+"/"+str(getTime())+".dat", None, 2250, " Sweep " + str(sweep) + " (started on " + aquire["start_date"]+")")
+               record_data([5], getDate()+"/"+str(getTime())+".dat", None, 4001)
+
+               try:
+                       pass
+                       #os.system("echo \"Sweep number " + str(sweep) + " completed\" | festival --tts")
+               except:
+                       pass
                sweep += 1
+       #setDAC(500)
+
+       try:
+               os.system("echo \"Experiment complete\" | festival --tts")
+       except:
+               pass
        
 
 def checkList():
+       try:
+               input_file = log_open(getDate()+"/checklist", "r")
+       except:
+               input_file = None
+
+       if (input_file != None):
+               for line in input_file:
+                       k = line.split("=")
+                       item = None
+                       if (len(k) >= 2):
+                               item = k[0].strip("# \r\n")
+                               value = k[1].strip("# \r\n")
+
+                       if (item in parameters):
+                               if item == "Chamber Pressure":
+                                       parameters[item] = getPressure()
+                               else:
+                                       parameters[item] = value
        
-       output = open(getDate()+"/checklist", "w", 0)
+               #print("Checklist found. Overwrite? [Y/n]")
+               response = "" #sys.stdin.readline().strip(" \r\n")
+               if (response == "" or response == "y" or response == "Y"):
+                       input_file = log_open(getDate()+"/checklist.old", "w")
+                       for item in parameters:
+                               input_file.write("# " + str(item) + " = " + str(parameters[item]) + "\n")
+                       input_file.write("\n")
+                       log_close(input_file)
+                       input_file = None
+       
+       if (input_file == None):
+               for item in parameters:
+                       if item == "Parameters last checked":
+                               continue
+                       if item == "Chamber Pressure":
+                               #sys.stdout.write("\""+str(item)+"\" = " + str(parameters[item]) + " - get new pressure... ")
+                               parameters[item] = getPressure()
+                               #sys.stdout.write(str(parameters[item]) + "\n")
+                               continue
+
+                       sys.stdout.write("\""+str(item)+"\" = " + str(parameters[item]) + " New value?: ")
+                       response = sys.stdin.readline().strip("\r\n ")
+                       if (response == "!"):
+                               break
+                       if (response != ""):
+                               parameters[item] = response
+                       sys.stdout.write("\n")
+               parameters["Parameters last checked"] = str(datetime.datetime.now())
+                       
+
+       checklist = log_open(getDate()+"/checklist", "w")
        for item in parameters:
-               sys.stdout.write("Enter value for \""+str(item)+"\": ")
-               parameters[item] = sys.stdin.readline().strip("\r\n ")
-               sys.stdout.write("\n")
-               output.write(str(parameters[item]) + "\n")
-
+               checklist.write("# "+str(item) + " = " + str(parameters[item]) + "\n")
+               #output_file.write("# "+str(item) + " = " + str(parameters[item]) + "\n")
+       log_close(checklist)
+       
 
-def record_data(ADC_channels, output, pollTime = None, dac_max = None, comment = None):
+def record_data(ADC_channels, output, pollTime = None, dac_max = None):
+       
        if (output != None):
-               output = [open(output, "w", 0), sys.stdout]
-               if (comment == None):
-                       print("Enter a comment for the experiment.")
-                       comment = sys.stdin.readline().strip("\r\n ")
-               output[0].write("# Comment: "+str(comment)+"\n")
+               gnuplot("set title \""+str(output)+"\"")
+               output = [log_open(output, "w"), sys.stdout]
+
        else:
+               gnuplot("set title \"<No file>\"")
                output = [sys.stdout]
 
+       for field in aquire:
+               for out in output:
+                       out.write("# aquire["+str(field)+"] = "+str(aquire[field]) + "\n")
+       
+       for out in output:
+               out.write("# Parameters:\n")
+
+       parameters["Chamber Pressure"] = getPressure() # Update chamber pressure
+
+       for field in parameters:
+               for out in output:
+                       out.write("# "+str(field)+" = " + str(parameters[field]) + "\n")
+
+
        start_time = time.time()
        
+       gnuplot("set xlabel \"DAC (counts)\"")
+       gnuplot("set ylabel \"ADC (counts)\"")
+       
+       
        for out in output:
+               out.write("\n")
                out.write("# Experiment " + str(datetime.datetime.now()) + "\n")
                out.write("# Polling for " + str(pollTime) + "s.\n")
-               out.write("# DAC = " + str(aquire["DAC_Sweep"]) + "\n")
+               out.write("\n")
                out.write("# Data:\n")
                out.write("# time\tDAC")
                for channel in ADC_channels:
@@ -183,16 +345,22 @@ def record_data(ADC_channels, output, pollTime = None, dac_max = None, comment =
                out.write("\n")
 
        step = 0
+       data = [] # Keep track of data for dynamic plotting
        dacValue = int(eval(aquire["DAC_Sweep"]))
        if (setDAC(dacValue) == False):
                setDAC(dacValue)
+       time.sleep(2.0)
        while (pollTime == None or time.time() < start_time + pollTime):
                if (aquire["DAC_Sweep"] != None):
                        nextDacValue = int(eval(aquire["DAC_Sweep"]))
                        if (nextDacValue != dacValue):
                                dacValue = nextDacValue
+                               if (dacValue < 0):
+                                       break
                                setDAC(dacValue)
                        step += 1
+               
+
                if (dac_max != None and dacValue >= dac_max):
                        break
 
@@ -203,28 +371,40 @@ def record_data(ADC_channels, output, pollTime = None, dac_max = None, comment =
                for channel in ADC_channels:
                        read = readADC(channel)
                        if read == False:
-                               print("Abort data collection")
-                               return False
+                               for out in output:              
+                                       print("# Abort data collection due to failed ADC read")                                 
+                                       if out != sys.stdout:
+                                               log_close(out)
+                                       return False
                        raw_adc.append((channel, read[0], read[1]))
 
                end_time = time.time()
 
                for out in output:
-                       out.write(str((measure_start + (end_time - measure_start)/2.0 - start_time)))
+                       measure_time = measure_start + (end_time - measure_start)/2.0 - start_time
+                       out.write(str(measure_time))
                        out.write("\t"+str(dacValue))
+                       data.append([measure_time, dacValue])
+
                        for adc in raw_adc:
                                out.write("\t" + str(adc[1]) + "\t" + str(adc[2]))
+                               data[len(data)-1].append(adc[1])
+                               data[len(data)-1].append(adc[2])
                        out.write("\n") 
        
-               
+               #gnuplot("set yrange [0:1023]")
+               #gnuplot("set xrange [0:4000]")
+               gnuplot("set xlabel \"DAC (counts)\"")
+               gnuplot("set ylabel \"Sample Current (ADC counts)\"")
+               gnuplot.plot(Gnuplot.Data(data, title="t = "+str(measure_time), with_="lp", using="2:3"))
        for out in output:              
                if out != sys.stdout:
-                       out.close()
+                       log_close(out)
        return True
 
 def loadCalibration_ADC(channel):
        try:
-               input_file = open("calibrateADC"+str(channel)+".dat")
+               input_file = log_open("calibrateADC"+str(channel)+".dat")
        except:
                print("Couldn't find calibration file for ADC " + str(channel))
                return False
@@ -237,7 +417,7 @@ def loadCalibration_ADC(channel):
                else:
                        split_line = l.split("\t")
                        calibrate["ADC"][channel].append((float(split_line[0]), float(split_line[1])))
-       input_file.close()
+       log_close(input_file)
 
        if (len(calibrate["ADC"][channel]) <= 0):
                print("Empty calibration file for ADC " + str(channel))
@@ -246,7 +426,7 @@ def loadCalibration_ADC(channel):
 
 def loadCalibration_DAC():
        try:
-               input_file = open("calibrateDAC.dat")
+               input_file = log_open("calibrateDAC.dat")
        except:
                print("Couldn't find calibration file for DAC")
                return False
@@ -265,7 +445,7 @@ def loadCalibration_DAC():
                                calibrate["DAC"].append((int(split_line[0]), float(split_line[1])))
 
 
-       input_file.close()
+       log_close(input_file)
 
        if (len(calibrate["DAC"]) <= 0):
                print("Empty calibration file for DAC")
@@ -374,7 +554,7 @@ def calibrateADC_usingDAC(channel, gain = True):
                return False
 
        calibrate["ADC"][channel] = []
-       outfile = open("calibrateADC"+str(channel)+".dat", "w", 1)
+       outfile = log_open("calibrateADC"+str(channel)+".dat", "w")
        outfile.write("# Calibrate ADC " + str(channel) + "\n")
        outfile.write("# Start " + str(datetime.datetime.now()) + "\n")
 
@@ -413,7 +593,7 @@ def calibrateADC_usingDAC(channel, gain = True):
                        calibrate["ADC"][channel].append((value[0], input_value, value[1]))
 
        outfile.write("# Stop " + str(datetime.datetime.now()) + "\n# EOF\n")
-       outfile.close()
+       log_close(outfile)
        if (setDAC(0) == False):
                return False
        if (len(calibrate["ADC"][channel]) <= 0):
@@ -423,7 +603,7 @@ def calibrateADC_usingDAC(channel, gain = True):
 
 def calibrateADC(channel):     
        calibrate["ADC"][channel] = []
-       outfile = open("calibrateADC"+str(channel)+".dat", "w", 1)
+       outfile = log_open("calibrateADC"+str(channel)+".dat", "w")
        outfile.write("# Calibrate ADC " + str(channel) + "\n")
        outfile.write("# Start " + str(datetime.datetime.now()) + "\n")
 
@@ -448,7 +628,7 @@ def calibrateADC(channel):
        
 
        outfile.write("# Stop " + str(datetime.datetime.now()) + "\n# EOF\n")
-       outfile.close()
+       log_close(outfile)
        if (len(calibrate["ADC"][channel]) <= 0):
                print("Error: No calibration points taken for ADC " + str(channel))
                return False
@@ -458,7 +638,7 @@ def calibrateADC(channel):
 def calibrateDAC():
        calibrate["DAC"] = []
 
-       outfile = open("calibrateDAC.dat", "w", 1)
+       outfile = log_open("calibrateDAC.dat", "w")
        outfile.write("# Calibrate DAC\n")
        outfile.write("# Start " + str(datetime.datetime.now()) + "\n")
 
@@ -500,7 +680,7 @@ def calibrateDAC():
                level += stepSize
 
        outfile.write("# Stop " + str(datetime.datetime.now()) + "\n# EOF\n")
-       outfile.close()
+       log_close(outfile)
        if (len(calibrate["DAC"]) <= 0):
                print("Error: No calibration points taken for DAC")
                return False

UCC git Repository :: git.ucc.asn.au