Automatic commit. Thu Aug 9 11:00:03 WST 2012
authorSam Moore <[email protected]>
Thu, 9 Aug 2012 03:00:03 +0000 (11:00 +0800)
committerSam Moore <[email protected]>
Thu, 9 Aug 2012 03:00:03 +0000 (11:00 +0800)
Q: What do you call a WASP who doesn't work for his father, isn't a
lawyer, and believes in social causes?
A: A failure.

research/TCS/2012-08-08/checklist [new file with mode: 0644]
research/TCS/2012-08-09/105433.dat [new file with mode: 0644]
research/TCS/2012-08-09/105927.dat [new file with mode: 0644]
research/TCS/2012-08-09/105938.dat [new file with mode: 0644]
research/TCS/2012-08-09/checklist [new file with mode: 0644]
research/TCS/2012-08-09/checklist.old [new file with mode: 0644]
research/TCS/interface.py
research/TCS/interface.pyc [new file with mode: 0644]
research/TCS/odict.py [new file with mode: 0644]
research/TCS/odict.pyc [new file with mode: 0644]

diff --git a/research/TCS/2012-08-08/checklist b/research/TCS/2012-08-08/checklist
new file mode 100644 (file)
index 0000000..999e436
--- /dev/null
@@ -0,0 +1,19 @@
+# Accelerating Voltage = 38.4
+# Focus Voltage = 0.17
+# Deflection Voltage = 1.346
+# Venault Voltage = 12.0
+# Initial Voltage = Sweep
+# Heating Current = 1.140
+# Heating Voltage = 1.141
+# Chamber Pressure = 3.89e-8
+# 610B Zero = 0.00
+# 602 Zero = 0.00
+# 610B Scale = 1e-7 x 0.03
+# 602 Scale = 1e-5 x 0.3
+# 602 0.1 Battery = 8.40
+# 602 0.03 Battery = 7.85
+# 602 0.01 Battery = 8.05
+# 602 0.003 Battery = 8.00
+# 602 0.001 Battery = 8.10
+# ADC Regulator = 3.30
+# Checklist updated 2012-08-09 10:32
diff --git a/research/TCS/2012-08-09/105433.dat b/research/TCS/2012-08-09/105433.dat
new file mode 100644 (file)
index 0000000..4c0fe94
--- /dev/null
@@ -0,0 +1,46 @@
+# File opened at 2012-08-09 10:54:33.262534
+# aquire[DAC_Sweep] = 0.0 + 50.0*int(step/60)
+# aquire[ADC_Averages] = 200
+# aquire[DAC_Settle] = 0.0
+# aquire[ADC_Ie] = 4
+# aquire[open_files] = [<open file '2012-08-09/checklist', mode 'w' at 0x7f6530b1e660>, <open file '2012-08-09/105433.dat', mode 'w' at 0x7f6530b1e5d0>]
+# aquire[ADC_Vi] = 5
+# aquire[start_date] = 2012-08-09
+# aquire[ADC_Is] = 4
+# Parameters:
+# Accelerating Voltage = 38.4
+# Focus Voltage = 0.17
+# Deflection Voltage = 1.346
+# Venault Voltage = 12.0
+# Initial Voltage = Sweep
+# Heating Current = 1.140
+# Heating Voltage = 1.141
+# Chamber Pressure = 3.89e-8
+# 610B Zero = 0.00
+# 602 Zero = 0.00
+# 610B Scale = 1e-7 x 0.03
+# 602 Scale = 1e-5 x 0.3
+# 602 0.1 Battery = 8.40
+# 602 0.03 Battery = 7.85
+# 602 0.01 Battery = 8.05
+# 602 0.003 Battery = 8.00
+# 602 0.001 Battery = 8.10
+# ADC Regulator = 3.30
+# Title = Testing
+# Comment = test
+# Data = TEST
+# Update Parameters = 2012-08-09 10:32
+
+# Experiment 2012-08-09 10:54:33.263732
+# Polling for Nones.
+
+# Data:
+# time DAC     ADC4    ADC5
+0.792319536209 0       8.0     7.56    914.9   111.90
+1.472417593    0       7.56    6.80    913.88  112.16
+2.151907444    0       7.44    7.39    913.9   112.9
+2.83043909073  0       7.90    7.88    914.20  112.15
+3.51444911957  0       9.28    8.47    910.77  112.90
+4.19797611237  0       9.13    7.97    914.16  112.9
+# Program exits.
+# File closed at 2012-08-09 10:54:41.063138
diff --git a/research/TCS/2012-08-09/105927.dat b/research/TCS/2012-08-09/105927.dat
new file mode 100644 (file)
index 0000000..6658fee
--- /dev/null
@@ -0,0 +1,40 @@
+# File opened at 2012-08-09 10:59:27.786538
+# aquire[DAC_Sweep] = 0.0 + 50.0*int(step/60)
+# aquire[ADC_Averages] = 200
+# aquire[DAC_Settle] = 0.0
+# aquire[ADC_Ie] = 4
+# aquire[open_files] = [<open file '2012-08-09/checklist', mode 'w' at 0x7f5d9cedc660>, <open file '2012-08-09/105927.dat', mode 'w' at 0x7f5d9cedc5d0>]
+# aquire[ADC_Vi] = 5
+# aquire[start_date] = 2012-08-09
+# aquire[ADC_Is] = 4
+# Parameters:
+# Accelerating Voltage = 38.4
+# Focus Voltage = 0.17
+# Deflection Voltage = 1.346
+# Venault Voltage = 12.0
+# Initial Voltage = Sweep
+# Heating Current = 1.140
+# Heating Voltage = 1.141
+# Chamber Pressure = 3.89e-8
+# 610B Zero = 0.00
+# 602 Zero = 0.00
+# 610B Scale = 1e-7 x 0.03
+# 602 Scale = 1e-5 x 0.3
+# 602 0.1 Battery = 8.40
+# 602 0.03 Battery = 7.85
+# 602 0.01 Battery = 8.05
+# 602 0.003 Battery = 8.00
+# 602 0.001 Battery = 8.10
+# ADC Regulator = 3.30
+# Title = Testing
+# Comment = test
+# Data = TEST
+# Parameters last checked = None
+
+# Experiment 2012-08-09 10:59:27.787749
+# Polling for Nones.
+
+# Data:
+# time DAC     ADC4    ADC5
+0.792268037796 0       7.89    7.42    913.27  111.80
+1.47629332542  0       7.48    7.16    913.85  111.99
diff --git a/research/TCS/2012-08-09/105938.dat b/research/TCS/2012-08-09/105938.dat
new file mode 100644 (file)
index 0000000..44f65f5
--- /dev/null
@@ -0,0 +1,41 @@
+# File opened at 2012-08-09 10:59:38.870702
+# aquire[DAC_Sweep] = 0.0 + 50.0*int(step/60)
+# aquire[ADC_Averages] = 200
+# aquire[DAC_Settle] = 0.0
+# aquire[ADC_Ie] = 4
+# aquire[open_files] = [<open file '2012-08-09/checklist.old', mode 'w' at 0x7f1990cef660>, <open file '2012-08-09/checklist', mode 'w' at 0x7f1990cef5d0>, <open file '2012-08-09/105938.dat', mode 'w' at 0x7f1990cef6f0>]
+# aquire[ADC_Vi] = 5
+# aquire[start_date] = 2012-08-09
+# aquire[ADC_Is] = 4
+# Parameters:
+# Accelerating Voltage = 38.4
+# Focus Voltage = 0.17
+# Deflection Voltage = 1.346
+# Venault Voltage = 12.0
+# Initial Voltage = Sweep
+# Heating Current = 1.140
+# Heating Voltage = aasdf
+# Chamber Pressure = 3.89e-8
+# 610B Zero = 0.00
+# 602 Zero = 0.00
+# 610B Scale = 1e-7 x 0.03
+# 602 Scale = 1e-5 x 0.3
+# 602 0.1 Battery = 8.40
+# 602 0.03 Battery = 7.85
+# 602 0.01 Battery = 8.05
+# 602 0.003 Battery = 8.00
+# 602 0.001 Battery = 8.10
+# ADC Regulator = 3.30
+# Title = Testing
+# Comment = adsf
+# Data = TEST
+# Parameters last checked = 2012-08-09 10:59:38.865447
+
+# Experiment 2012-08-09 10:59:38.871908
+# Polling for Nones.
+
+# Data:
+# time DAC     ADC4    ADC5
+0.785655975342 0       8.30    7.56    913.95  111.67
+# Recieved KILL signal.
+# Reason: test again# File closed at 2012-08-09 10:59:41.581763
diff --git a/research/TCS/2012-08-09/checklist b/research/TCS/2012-08-09/checklist
new file mode 100644 (file)
index 0000000..7f273a6
--- /dev/null
@@ -0,0 +1,23 @@
+# File opened at 2012-08-09 10:59:38.865710
+# Accelerating Voltage = 38.4
+# Focus Voltage = 0.17
+# Deflection Voltage = 1.346
+# Venault Voltage = 12.0
+# Initial Voltage = Sweep
+# Heating Current = 1.140
+# Heating Voltage = aasdf
+# Chamber Pressure = 3.89e-8
+# 610B Zero = 0.00
+# 602 Zero = 0.00
+# 610B Scale = 1e-7 x 0.03
+# 602 Scale = 1e-5 x 0.3
+# 602 0.1 Battery = 8.40
+# 602 0.03 Battery = 7.85
+# 602 0.01 Battery = 8.05
+# 602 0.003 Battery = 8.00
+# 602 0.001 Battery = 8.10
+# ADC Regulator = 3.30
+# Title = Testing
+# Comment = adsf
+# Data = TEST
+# Parameters last checked = 2012-08-09 10:59:38.865447
diff --git a/research/TCS/2012-08-09/checklist.old b/research/TCS/2012-08-09/checklist.old
new file mode 100644 (file)
index 0000000..f2a8467
--- /dev/null
@@ -0,0 +1,26 @@
+# File opened at 2012-08-09 10:59:34.993650
+# Accelerating Voltage = 38.4
+# Focus Voltage = 0.17
+# Deflection Voltage = 1.346
+# Venault Voltage = 12.0
+# Initial Voltage = Sweep
+# Heating Current = 1.140
+# Heating Voltage = 1.141
+# Chamber Pressure = 3.89e-8
+# 610B Zero = 0.00
+# 602 Zero = 0.00
+# 610B Scale = 1e-7 x 0.03
+# 602 Scale = 1e-5 x 0.3
+# 602 0.1 Battery = 8.40
+# 602 0.03 Battery = 7.85
+# 602 0.01 Battery = 8.05
+# 602 0.003 Battery = 8.00
+# 602 0.001 Battery = 8.10
+# ADC Regulator = 3.30
+# Title = Testing
+# Comment = test
+# Data = TEST
+# Parameters last checked = None
+
+# Recieved KILL signal.
+# Reason: test again# File closed at 2012-08-09 10:59:41.581576
index 86c5e82..11ed9b2 100755 (executable)
@@ -12,7 +12,7 @@ import time
 import serial
 import datetime
 
-import collections
+import odict
 
 
 # TODO: Insert variables for calibration purposes here.
@@ -57,7 +57,7 @@ ser = serial.Serial(
        rtscts=0
 )
 
-parameters = OrderedDict([
+parameters = odict.odict([
        ("Accelerating Voltage" , None),
        ("Focus Voltage" , None),
        ("Deflection Voltage" , None),
@@ -75,11 +75,11 @@ parameters = OrderedDict([
        ("602 0.01 Battery" , None),
        ("602 0.003 Battery" , None),
        ("602 0.001 Battery" , None), 
-       ("ADC Battery" , None),
        ("ADC Regulator" , None),
        ("Title" , None),
        ("Comment" , None),
        ("Data" , None),
+       ("Parameters last checked", None)
 ])
 
 def getTime():
@@ -95,17 +95,48 @@ def set_exit_handler(func):
             import win32api
             win32api.SetConsoleCtrlHandler(func, True)
         except ImportError:
-            version = “.”.join(map(str, sys.version_info[:2]))
-            raise Exception(”pywin32 not installed for Python ” + version)
+            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))
+               log_close(out)
 
-def exit_handler():
        
 
-def init():
+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()
 
@@ -126,19 +157,19 @@ def init():
        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 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():
 
@@ -178,46 +209,55 @@ def main():
                sweep += 1
        
 
-def checkList(output_file):
+def checkList():
        try:
-               input_file = open(getDate()+"/checklist", "r")
+               input_file = log_open(getDate()+"/checklist", "r")
        except:
                input_file = None
 
        if (input_file != None):
                for line in input_file:
                        k = line.split("=")
-                       item = k[0].strip(" \r\n")
-                       value = k[1].strip(" \r\n")
+                       item = None
+                       if (len(k) >= 2):
+                               item = k[0].strip("# \r\n")
+                               value = k[1].strip("# \r\n")
+
                        if (item in parameters):
                                parameters[item] = value
        
                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")
                        input_file = None
        
        if (input_file == None):
                for item in parameters:
+                       if item == "Parameters last checked":
+                               continue
                        sys.stdout.write("\""+str(item)+"\" = " + str(parameters[item]) + " New value?: ")
                        response = sys.stdin.readline().strip("\r\n ")
                        if (response != ""):
                                parameters[item] = response
                        sys.stdout.write("\n")
+               parameters["Parameters last checked"] = str(datetime.datetime.now())
                        
 
-       checklist = open(getDate()+"/checklist", "w", 0)
+       checklist = log_open(getDate()+"/checklist", "w")
        for item in parameters:
                checklist.write("# "+str(item) + " = " + str(parameters[item]) + "\n")
-               output_file.write("# "+str(item) + " = " + str(parameters[item]) + "\n")
-
+               #output_file.write("# "+str(item) + " = " + str(parameters[item]) + "\n")
 
+       
 
 def record_data(ADC_channels, output, pollTime = None, dac_max = None):
        
        if (output != None):
-               output = [open(output, "w", 0), sys.stdout]
-               checkList(output[0])
+               output = [log_open(output, "w"), sys.stdout]
        else:
                output = [sys.stdout]
 
@@ -226,11 +266,11 @@ def record_data(ADC_channels, output, pollTime = None, dac_max = None):
                        out.write("# aquire["+str(field)+"] = "+str(aquire[field]) + "\n")
        
        for out in output:
-               out.write("# Checklist:\n")
+               out.write("# Parameters:\n")
 
-       for field in checklist:
+       for field in parameters:
                for out in output:
-                       out.write("# "+str(field)+" = " + str(checklist[field]) + "\n")
+                       out.write("# "+str(field)+" = " + str(parameters[field]) + "\n")
 
 
        start_time = time.time()
@@ -271,8 +311,11 @@ def record_data(ADC_channels, output, pollTime = None, dac_max = None):
                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()
@@ -287,12 +330,12 @@ def record_data(ADC_channels, output, pollTime = None, dac_max = None):
                
        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
@@ -305,7 +348,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))
@@ -314,7 +357,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
@@ -333,7 +376,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")
@@ -442,7 +485,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")
 
@@ -481,7 +524,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):
@@ -491,7 +534,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")
 
@@ -516,7 +559,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
@@ -526,7 +569,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")
 
@@ -568,7 +611,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
diff --git a/research/TCS/interface.pyc b/research/TCS/interface.pyc
new file mode 100644 (file)
index 0000000..d7ce380
Binary files /dev/null and b/research/TCS/interface.pyc differ
diff --git a/research/TCS/odict.py b/research/TCS/odict.py
new file mode 100644 (file)
index 0000000..3bf708a
--- /dev/null
@@ -0,0 +1,328 @@
+# -*- coding: utf-8 -*-
+"""
+    odict
+    ~~~~~
+
+    This module is an example implementation of an ordered dict for the
+    collections module.  It's not written for performance (it actually
+    performs pretty bad) but to show how the API works.
+
+
+    Questions and Answers
+    =====================
+
+    Why would anyone need ordered dicts?
+
+        Dicts in python are unordered which means that the order of items when
+        iterating over dicts is undefined.  As a matter of fact it is most of
+        the time useless and differs from implementation to implementation.
+
+        Many developers stumble upon that problem sooner or later when
+        comparing the output of doctests which often does not match the order
+        the developer thought it would.
+
+        Also XML systems such as Genshi have their problems with unordered
+        dicts as the input and output ordering of tag attributes is often
+        mixed up because the ordering is lost when converting the data into
+        a dict.  Switching to lists is often not possible because the
+        complexity of a lookup is too high.
+
+        Another very common case is metaprogramming.  The default namespace
+        of a class in python is a dict.  With Python 3 it becomes possible
+        to replace it with a different object which could be an ordered dict.
+        Django is already doing something similar with a hack that assigns
+        numbers to some descriptors initialized in the class body of a
+        specific subclass to restore the ordering after class creation.
+
+        When porting code from programming languages such as PHP and Ruby
+        where the item-order in a dict is guaranteed it's also a great help
+        to have an equivalent data structure in Python to ease the transition.
+
+    Where are new keys added?
+
+        At the end.  This behavior is consistent with Ruby 1.9 Hashmaps
+        and PHP Arrays.  It also matches what common ordered dict
+        implementations do currently.
+
+    What happens if an existing key is reassigned?
+
+        The key is *not* moved.  This is consitent with existing
+        implementations and can be changed by a subclass very easily::
+
+            class movingodict(odict):
+                def __setitem__(self, key, value):
+                    self.pop(key, None)
+                    odict.__setitem__(self, key, value)
+
+        Moving keys to the end of a ordered dict on reassignment is not
+        very useful for most applications.
+
+    Does it mean the dict keys are sorted by a sort expression?
+
+        That's not the case.  The odict only guarantees that there is an order
+        and that newly inserted keys are inserted at the end of the dict.  If
+        you want to sort it you can do so, but newly added keys are again added
+        at the end of the dict.
+
+    I initializes the odict with a dict literal but the keys are not
+    ordered like they should!
+
+        Dict literals in Python generate dict objects and as such the order of
+        their items is not guaranteed.  Before they are passed to the odict
+        constructor they are already unordered.
+
+    What happens if keys appear multiple times in the list passed to the
+    constructor?
+
+        The same as for the dict.  The latter item overrides the former.  This
+        has the side-effect that the position of the first key is used because
+        the key is actually overwritten:
+
+        >>> odict([('a', 1), ('b', 2), ('a', 3)])
+        odict.odict([('a', 3), ('b', 2)])
+
+        This behavor is consistent with existing implementation in Python
+        and the PHP array and the hashmap in Ruby 1.9.
+
+    This odict doesn't scale!
+
+        Yes it doesn't.  The delitem operation is O(n).  This is file is a
+        mockup of a real odict that could be implemented for collections
+        based on an linked list.
+
+    Why is there no .insert()?
+
+        There are few situations where you really want to insert a key at
+        an specified index.  To now make the API too complex the proposed
+        solution for this situation is creating a list of items, manipulating
+        that and converting it back into an odict:
+
+        >>> d = odict([('a', 42), ('b', 23), ('c', 19)])
+        >>> l = d.items()
+        >>> l.insert(1, ('x', 0))
+        >>> odict(l)
+        odict.odict([('a', 42), ('x', 0), ('b', 23), ('c', 19)])
+
+    :copyright: (c) 2008 by Armin Ronacher and PEP 273 authors.
+    :license: modified BSD license.
+"""
+from itertools import izip, imap
+from copy import deepcopy
+
+missing = object()
+
+
+class odict(dict):
+    """
+    Ordered dict example implementation.
+
+    This is the proposed interface for a an ordered dict as proposed on the
+    Python mailinglist (proposal_).
+
+    It's a dict subclass and provides some list functions.  The implementation
+    of this class is inspired by the implementation of Babel but incorporates
+    some ideas from the `ordereddict`_ and Django's ordered dict.
+
+    The constructor and `update()` both accept iterables of tuples as well as
+    mappings:
+
+    >>> d = odict([('a', 'b'), ('c', 'd')])
+    >>> d.update({'foo': 'bar'})
+    >>> d
+    odict.odict([('a', 'b'), ('c', 'd'), ('foo', 'bar')])
+    
+    Keep in mind that when updating from dict-literals the order is not
+    preserved as these dicts are unsorted!
+
+    You can copy an odict like a dict by using the constructor, `copy.copy`
+    or the `copy` method and make deep copies with `copy.deepcopy`:
+
+    >>> from copy import copy, deepcopy
+    >>> copy(d)
+    odict.odict([('a', 'b'), ('c', 'd'), ('foo', 'bar')])
+    >>> d.copy()
+    odict.odict([('a', 'b'), ('c', 'd'), ('foo', 'bar')])
+    >>> odict(d)
+    odict.odict([('a', 'b'), ('c', 'd'), ('foo', 'bar')])
+    >>> d['spam'] = []
+    >>> d2 = deepcopy(d)
+    >>> d2['spam'].append('eggs')
+    >>> d
+    odict.odict([('a', 'b'), ('c', 'd'), ('foo', 'bar'), ('spam', [])])
+    >>> d2
+    odict.odict([('a', 'b'), ('c', 'd'), ('foo', 'bar'), ('spam', ['eggs'])])
+
+    All iteration methods as well as `keys`, `values` and `items` return
+    the values ordered by the the time the key-value pair is inserted:
+
+    >>> d.keys()
+    ['a', 'c', 'foo', 'spam']
+    >>> d.values()
+    ['b', 'd', 'bar', []]
+    >>> d.items()
+    [('a', 'b'), ('c', 'd'), ('foo', 'bar'), ('spam', [])]
+    >>> list(d.iterkeys())
+    ['a', 'c', 'foo', 'spam']
+    >>> list(d.itervalues())
+    ['b', 'd', 'bar', []]
+    >>> list(d.iteritems())
+    [('a', 'b'), ('c', 'd'), ('foo', 'bar'), ('spam', [])]
+
+    Index based lookup is supported too by `byindex` which returns the
+    key/value pair for an index:
+
+    >>> d.byindex(2)
+    ('foo', 'bar')
+
+    You can reverse the odict as well:
+
+    >>> d.reverse()
+    >>> d
+    odict.odict([('spam', []), ('foo', 'bar'), ('c', 'd'), ('a', 'b')])
+    
+    And sort it like a list:
+
+    >>> d.sort(key=lambda x: x[0].lower())
+    >>> d
+    odict.odict([('a', 'b'), ('c', 'd'), ('foo', 'bar'), ('spam', [])])
+
+    .. _proposal: http://thread.gmane.org/gmane.comp.python.devel/95316
+    .. _ordereddict: http://www.xs4all.nl/~anthon/Python/ordereddict/
+    """
+
+    def __init__(self, *args, **kwargs):
+        dict.__init__(self)
+        self._keys = []
+        self.update(*args, **kwargs)
+
+    def __delitem__(self, key):
+        dict.__delitem__(self, key)
+        self._keys.remove(key)
+
+    def __setitem__(self, key, item):
+        if key not in self:
+            self._keys.append(key)
+        dict.__setitem__(self, key, item)
+
+    def __deepcopy__(self, memo=None):
+        if memo is None:
+            memo = {}
+        d = memo.get(id(self), missing)
+        if d is not missing:
+            return d
+        memo[id(self)] = d = self.__class__()
+        dict.__init__(d, deepcopy(self.items(), memo))
+        d._keys = self._keys[:]
+        return d
+
+    def __getstate__(self):
+        return {'items': dict(self), 'keys': self._keys}
+
+    def __setstate__(self, d):
+        self._keys = d['keys']
+        dict.update(d['items'])
+
+    def __reversed__(self):
+        return reversed(self._keys)
+
+    def __eq__(self, other):
+        if isinstance(other, odict):
+            if not dict.__eq__(self, other):
+                return False
+            return self.items() == other.items()
+        return dict.__eq__(self, other)
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __cmp__(self, other):
+        if isinstance(other, odict):
+            return cmp(self.items(), other.items())
+        elif isinstance(other, dict):
+            return dict.__cmp__(self, other)
+        return NotImplemented
+
+    @classmethod
+    def fromkeys(cls, iterable, default=None):
+        return cls((key, default) for key in iterable)
+
+    def clear(self):
+        del self._keys[:]
+        dict.clear(self)
+
+    def copy(self):
+        return self.__class__(self)
+
+    def items(self):
+        return zip(self._keys, self.values())
+
+    def iteritems(self):
+        return izip(self._keys, self.itervalues())
+
+    def keys(self):
+        return self._keys[:]
+
+    def iterkeys(self):
+        return iter(self._keys)
+
+    def pop(self, key, default=missing):
+        if default is missing:
+            return dict.pop(self, key)
+        elif key not in self:
+            return default
+        self._keys.remove(key)
+        return dict.pop(self, key, default)
+
+    def popitem(self, key):
+        self._keys.remove(key)
+        return dict.popitem(key)
+
+    def setdefault(self, key, default=None):
+        if key not in self:
+            self._keys.append(key)
+        dict.setdefault(self, key, default)
+
+    def update(self, *args, **kwargs):
+        sources = []
+        if len(args) == 1:
+            if hasattr(args[0], 'iteritems'):
+                sources.append(args[0].iteritems())
+            else:
+                sources.append(iter(args[0]))
+        elif args:
+            raise TypeError('expected at most one positional argument')
+        if kwargs:
+            sources.append(kwargs.iteritems())
+        for iterable in sources:
+            for key, val in iterable:
+                self[key] = val
+
+    def values(self):
+        return map(self.get, self._keys)
+
+    def itervalues(self):
+        return imap(self.get, self._keys)
+
+    def index(self, item):
+        return self._keys.index(item)
+
+    def byindex(self, item):
+        key = self._keys[item]
+        return (key, dict.__getitem__(self, key))
+
+    def reverse(self):
+        self._keys.reverse()
+
+    def sort(self, *args, **kwargs):
+        self._keys.sort(*args, **kwargs)
+
+    def __repr__(self):
+        return 'odict.odict(%r)' % self.items()
+
+    __copy__ = copy
+    __iter__ = iterkeys
+
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()
diff --git a/research/TCS/odict.pyc b/research/TCS/odict.pyc
new file mode 100644 (file)
index 0000000..3ade9ba
Binary files /dev/null and b/research/TCS/odict.pyc differ

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