Index: src/sas/sascalc/dataloader/readers/sesans_reader.py
===================================================================
--- src/sas/sascalc/dataloader/readers/sesans_reader.py	(revision 9a5097cd1c76689d1f997b85ba43d12a95d8f243)
+++ src/sas/sascalc/dataloader/readers/sesans_reader.py	(revision 2b31060287b81e5967b03f6148ee39bbe5d30c20)
@@ -1,8 +1,8 @@
 """
     SESANS reader (based on ASCII reader)
-    
+
     Reader for .ses or .sesans file format
-    
-    Jurrian Bakker 
+
+    Jurrian Bakker
 """
 import numpy as np
@@ -18,31 +18,29 @@
 _ZERO = 1e-16
 
+
 class Reader:
     """
     Class to load sesans files (6 columns).
     """
-    ## File type
+    # File type
     type_name = "SESANS"
-    
-    ## Wildcards
+
+    # Wildcards
     type = ["SESANS files (*.ses)|*.ses",
             "SESANS files (*..sesans)|*.sesans"]
-    ## List of allowed extensions
+    # List of allowed extensions
     ext = ['.ses', '.SES', '.sesans', '.SESANS']
-    
-    ## Flag to bypass extension check
+
+    # Flag to bypass extension check
     allow_all = True
-    
+
     def read(self, path):
-        
-#        print "reader triggered"
-        
         """
         Load data file
-        
+
         :param path: file path
-        
+
         :return: SESANSData1D object, or None
-        
+
         :raise RuntimeError: when the file can't be opened
         :raise ValueError: when the length of the data vectors are inconsistent
@@ -51,120 +49,79 @@
             basename = os.path.basename(path)
             _, extension = os.path.splitext(basename)
-            if self.allow_all or extension.lower() in self.ext:
-                try:
-                    # Read in binary mode since GRASP frequently has no-ascii
-                    # characters that brakes the open operation
-                    input_f = open(path,'rb')
-                except:
-                    raise  RuntimeError, "sesans_reader: cannot open %s" % path
-                buff = input_f.read()
-                lines = buff.splitlines()
-                x  = np.zeros(0)
-                y  = np.zeros(0)
-                dy = np.zeros(0)
-                lam  = np.zeros(0)
-                dlam = np.zeros(0)
-                dx = np.zeros(0)
-                
-               #temp. space to sort data
-                tx  = np.zeros(0)
-                ty  = np.zeros(0)
-                tdy = np.zeros(0)
-                tlam  = np.zeros(0)
-                tdlam = np.zeros(0)
-                tdx = np.zeros(0)
-                output = Data1D(x=x, y=y, lam=lam, dy=dy, dx=dx, dlam=dlam, isSesans=True)
-                self.filename = output.filename = basename
+            if not (self.allow_all or extension.lower() in self.ext):
+                raise RuntimeError("{} has an unrecognized file extension".format(path))
+        else:
+            raise RunetimeError("{} is not a file".format(path))
+        with open(path, 'r') as input_f:
+            # Read in binary mode since GRASP frequently has no-ascii
+            # characters that brakes the open operation
+            line = input_f.readline()
+            params = {}
+            while not line.startswith("BEGIN_DATA"):
+                terms = line.split()
+                if len(terms) >= 2:
+                    params[terms[0]] = " ".join(terms[1:])
+                line = input_f.readline()
+            self.params = params
+            headers = input_f.readline().split()
 
-                paramnames=[]
-                paramvals=[]
-                zvals=[]
-                dzvals=[]
-                lamvals=[]
-                dlamvals=[]
-                Pvals=[]
-                dPvals=[]
+            data = np.loadtxt(input_f)
+            if data.size < 1:
+                raise RuntimeError("{} is empty".format(path))
+            x = data[:, headers.index("SpinEchoLength")]
+            dx = data[:, headers.index("SpinEchoLength_error")]
+            lam = data[:, headers.index("Wavelength")]
+            dlam = data[:, headers.index("Wavelength_error")]
+            y = data[:, headers.index("Depolarisation")]
+            dy = data[:, headers.index("Depolarisation_error")]
 
-                for line in lines:
-                    # Initial try for CSV (split on ,)
-                    line=line.strip()
-                    toks = line.split('\t')
-                    if len(toks)==2:
-                        paramnames.append(toks[0])
-                        paramvals.append(toks[1])
-                    if len(toks)>5:
-                        zvals.append(toks[0])
-                        dzvals.append(toks[3])
-                        lamvals.append(toks[4])
-                        dlamvals.append(toks[5])
-                        Pvals.append(toks[1])
-                        dPvals.append(toks[2])
-                    else:
-                        continue
+            lam_unit = self._unit_fetch("Wavelength")
+            x, x_unit = self._unit_conversion(x, "A", self._unit_fetch("SpinEchoLength"))
+            dx, dx_unit = self._unit_conversion(
+                dx, lam_unit,
+                self._unit_fetch("SpinEchoLength"))
+            dlam, dlam_unit = self._unit_conversion(
+                dlam, lam_unit,
+                self._unit_fetch("Wavelength"))
+            y_unit = self._unit_fetch("Depolarisation")
 
-                x=[]
-                y=[]
-                lam=[]
-                dx=[]
-                dy=[]
-                dlam=[]
-                lam_header = lamvals[0].split()
-                data_conv_z = None
-                default_z_unit = "A"
-                data_conv_P = None
-                default_p_unit = " " # Adjust unit for axis (L^-3)
-                lam_unit = lam_header[1].replace("[","").replace("]","")
-                if lam_unit == 'AA':
-                    lam_unit = 'A'
-                varheader=[zvals[0],dzvals[0],lamvals[0],dlamvals[0],Pvals[0],dPvals[0]]
-                valrange=range(1, len(zvals))
-                for i in valrange:
-                    x.append(float(zvals[i]))
-                    y.append(float(Pvals[i]))
-                    lam.append(float(lamvals[i]))
-                    dy.append(float(dPvals[i]))
-                    dx.append(float(dzvals[i]))
-                    dlam.append(float(dlamvals[i]))
+            output = Data1D(x=x, y=y, lam=lam, dy=dy, dx=dx, dlam=dlam,
+                            isSesans=True)
 
-                x,y,lam,dy,dx,dlam = [
-                    np.asarray(v, 'double')
-                   for v in (x,y,lam,dy,dx,dlam)
-                ]
+            output.y_unit = y_unit
+            output.x_unit = x_unit
+            self.filename = output.filename = basename
+            output.xaxis(r"\rm{z}", x_unit)
+            # Adjust label to ln P/(lam^2 t), remove lam column refs
+            output.yaxis(r"\rm{ln(P)/(t \lambda^2)}", y_unit)
+            # Store loading process information
+            output.meta_data['loader'] = self.type_name
+            output.sample.name = params["Sample"]
+            output.sample.ID = params["DataFileTitle"]
+            output.sample.thickness = float(
+                self._unit_conversion(
+                    params["Thickness"], "cm", self._unit_fetch("Thickness"))[0])
 
-                input_f.close()
+            output.sample.zacceptance = (
+                float(params["Theta_zmax"]),
+                self._unit_fetch("Theta_zmax"))
 
-                output.x, output.x_unit = self._unit_conversion(x, lam_unit, default_z_unit)
-                output.y = y
-                output.y_unit = r'\AA^{-2} cm^{-1}'  # output y_unit added
-                output.dx, output.dx_unit = self._unit_conversion(dx, lam_unit, default_z_unit)
-                output.dy = dy
-                output.lam, output.lam_unit = self._unit_conversion(lam, lam_unit, default_z_unit)
-                output.dlam, output.dlam_unit = self._unit_conversion(dlam, lam_unit, default_z_unit)
-                
-                output.xaxis(r"\rm{z}", output.x_unit)
-                output.yaxis(r"\rm{ln(P)/(t \lambda^2)}", output.y_unit)  # Adjust label to ln P/(lam^2 t), remove lam column refs
+            output.sample.yacceptance = (
+                float(params["Theta_ymax"]),
+                self._unit_fetch("Theta_ymax"))
+            return output
 
-                # Store loading process information
-                output.meta_data['loader'] = self.type_name
-                #output.sample.thickness = float(paramvals[6])
-                output.sample.name = paramvals[1]
-                output.sample.ID = paramvals[0]
-                zaccept_unit_split = paramnames[7].split("[")
-                zaccept_unit = zaccept_unit_split[1].replace("]","")
-                if zaccept_unit.strip() == r'\AA^-1' or zaccept_unit.strip() == r'\A^-1':
-                    zaccept_unit = "1/A"
-                output.sample.zacceptance=(float(paramvals[7]),zaccept_unit)
-                output.vars = varheader
+    @staticmethod
+    def _unit_conversion(value, value_unit, default_unit):
+        """
+        Performs unit conversion on a measurement.
 
-                if len(output.x) < 1:
-                    raise RuntimeError, "%s is empty" % path
-                return output
-
-        else:
-            raise RuntimeError, "%s is not a file" % path
-        return None
-
-    def _unit_conversion(self, value, value_unit, default_unit):
-        if has_converter == True and value_unit != default_unit:
+        :param value: The magnitude of the measurement
+        :param value_unit: a string containing the final desired unit
+        :param default_unit: a string containing the units of the original measurement
+        :return: The magnitude of the measurement in the new units
+        """
+        # (float, string, string) -> float
+        if has_converter and value_unit != default_unit:
             data_conv_q = Converter(value_unit)
             value = data_conv_q(value, units=default_unit)
@@ -173,2 +130,5 @@
             new_unit = value_unit
         return value, new_unit
+
+    def _unit_fetch(self, unit):
+        return self.params[unit+"_unit"]
