Index: DataLoader/data_info.py
===================================================================
--- DataLoader/data_info.py	(revision 99d1af6082f75428716f6bace3bc5a668ba7a9b6)
+++ DataLoader/data_info.py	(revision b99ac22702d9634282d084e8a7da3aa3064bccf2)
@@ -14,5 +14,9 @@
 project funded by the US National Science Foundation. 
 
-See the license text in license.txt
+If you use DANSE applications to do scientific research that leads to 
+publication, we ask that you acknowledge the use of the software with the 
+following sentence:
+
+"This work benefited from DANSE software developed under NSF award DMR-0520547." 
 
 copyright 2008, University of Tennessee
@@ -307,4 +311,33 @@
     errors = []
             
+    def __init__(self):
+        """
+            Initialization
+        """
+        ## Title 
+        self.title      = ''
+        ## Run number
+        self.run        = None
+        ## File name
+        self.filename   = ''
+        ## Notes
+        self.notes      = []
+        ## Processes (Action on the data)
+        self.process    = []
+        ## Instrument name
+        self.instrument = ''
+        ## Detector information
+        self.detector   = []
+        ## Sample information
+        self.sample     = Sample()
+        ## Source information
+        self.source     = Source()
+        ## Collimation information
+        self.collimation = []
+        ## Additional meta-data
+        self.meta_data  = {}
+        ## Loading errors
+        self.errors = []        
+        
     def __str__(self):
         """
@@ -429,5 +462,9 @@
     
     def __init__(self, x, y, dx=None, dy=None):
+        DataInfo.__init__(self)
         plottable_1D.__init__(self, x, y, dx, dy)
+        if len(self.detector)>0:
+            raise RuntimeError, "Data1D: Detector bank already filled at init"
+        
         
     def __str__(self):
@@ -553,5 +590,8 @@
     
     def __init__(self, data=None, err_data=None):
+        DataInfo.__init__(self)
         plottable_2D.__init__(self, data, err_data)
+        if len(self.detector)>0:
+            raise RuntimeError, "Data2D: Detector bank already filled at init"
 
     def __str__(self):
Index: DataLoader/readers/IgorReader.py
===================================================================
--- DataLoader/readers/IgorReader.py	(revision 68f6ae249434566dbc018908720451e6f12c11ca)
+++ DataLoader/readers/IgorReader.py	(revision b99ac22702d9634282d084e8a7da3aa3064bccf2)
@@ -1,35 +1,74 @@
+"""
+    IGOR 2D reduced file reader
+"""
+
+"""
+This software was developed by the University of Tennessee as part of the
+Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+project funded by the US National Science Foundation. 
+
+If you use DANSE applications to do scientific research that leads to 
+publication, we ask that you acknowledge the use of the software with the 
+following sentence:
+
+"This work benefited from DANSE software developed under NSF award DMR-0520547." 
+
+copyright 2008, University of Tennessee
+"""
+
 import os, sys
-import pylab
-from copy import deepcopy
-import math,logging
+import numpy
+import math, logging
+from DataLoader.data_info import Data2D, Detector
+
+# Look for unit converter
+has_converter = True
+try:
+    from data_util.nxsunit import Converter
+except:
+    has_converter = False
+
 class Reader:
     """ Simple data reader for Igor data files """
-    ext=['.ASC']
-    def __init__(self, filename=None):
-        """ Init
-            @param filename: Name of Igor data file to read
-        """
-        self.file = filename
-        self.x = []
-        self.y = []
-        self.image = []
-        
-        # Detector info
-        self.wavelength = 0.0
-        self.distance   = 0.0
-        self.center_x   = 63.5
-        self.center_y   = 63.5
-        
+    ## File type
+    type = ["IGOR 2D files (*.ASC)|*.ASC"]
+    ## Extension
+    ext=['.ASC', '.asc']
+
     def read(self,filename=None):
         """ Read file """
-        # Check if the file is there
-        self.file=filename
-        if not os.path.isfile(self.file):
+        if not os.path.isfile(filename):
             raise ValueError, \
-            "Specified file %s is not a regular file" % self.file
+            "Specified file %s is not a regular file" % filename
         
         # Read file
-        f = open(self.file,'r')
+        f = open(filename,'r')
         buf = f.read()
+        
+        # Instantiate data object
+        output = Data2D()
+        output.filename = os.path.basename(filename)
+        detector = Detector()
+        if len(output.detector)>0: print str(output.detector[0])
+        output.detector.append(detector)
+        
+        size_x = 128
+        size_y = 128
+        output.data = numpy.zeros([size_x,size_y])
+        output.err_data = numpy.zeros([size_x,size_y])
+        
+        data_conv_q = None
+        data_conv_i = None
+        
+        if has_converter == True and output.Q_unit != '1/A':
+            data_conv_q = Converter('1/A')
+            # Test it
+            data_conv_q(1.0, output.Q_unit)
+            
+        if has_converter == True and output.I_unit != '1/cm':
+            data_conv_i = Converter('1/cm')
+            # Test it
+            data_conv_i(1.0, output.I_unit)            
+    
         
         # Get content
@@ -39,16 +78,8 @@
         lines = buf.split('\n')
         itot = 0
-        self.x = []
-        self.y = []
-        self.image = []
+        x = []
+        y = []
         
         ncounts = 0
-        
-        #x = pylab.arange(0, 128, 1)
-        #y = pylab.arange(0, 128, 1)
-        x = pylab.arange(-.5, .5, 1.0/128)
-        y = pylab.arange(-.5, .5, 1.0/128)
-        X, Y = pylab.meshgrid(x, y)
-        Z = deepcopy(X)
         
         xmin = None
@@ -79,4 +110,10 @@
                     raise ValueError,"IgorReader: can't read this file, missing distance"
                 
+                # Distance in meters
+                try:
+                    transmission = float(line_toks[4])
+                except:
+                    raise ValueError,"IgorReader: can't read this file, missing transmission"
+                
             if line.count("LAMBDA")>0:
                 isInfo = True
@@ -109,4 +146,5 @@
                     value = float(line)
                 except:
+                    # Found a non-float entry, skip it
                     continue
                 
@@ -118,5 +156,5 @@
                     i_x += 1
                     
-                Z[i_y][i_x] = value
+                output.data[i_y][i_x] = value
                 ncounts += 1 
                 
@@ -126,4 +164,8 @@
                 theta = (i_x-center_x+1)*0.5 / distance / 100.0
                 qx = 4.0*math.pi/wavelength * math.sin(theta/2.0)
+
+                if has_converter == True and output.Q_unit != '1/A':
+                    qx = data_conv_q(qx, units=output.Q_unit)
+
                 if xmin==None or qx<xmin:
                     xmin = qx
@@ -133,4 +175,8 @@
                 theta = (i_y-center_y+1)*0.5 / distance / 100.0
                 qy = 4.0*math.pi/wavelength * math.sin(theta/2.0)
+
+                if has_converter == True and output.Q_unit != '1/A':
+                    qy = data_conv_q(qy, units=output.Q_unit)
+                
                 if ymin==None or qy<ymin:
                     ymin = qy
@@ -138,9 +184,8 @@
                     ymax = qy
                 
-                
-                if not qx in self.x:
-                    self.x.append(qx)
-                if not qy in self.y:
-                    self.y.append(qy)
+                if not qx in x:
+                    x.append(qx)
+                if not qy in y:
+                    y.append(qy)
                 
                 itot += 1
@@ -153,33 +198,70 @@
         ystep = 4.0*math.pi/wavelength * math.sin(theta/2.0)
         
-        # Store q max 
-        if xmax>ymax:
-            self.qmax = xmax
+        # Store all data ######################################
+        # Store wavelength
+        if has_converter==True and output.source.wavelength_unit != 'A':
+            conv = Converter('A')
+            wavelength = conv(wavelength, units=output.source.wavelength_unit)
+        output.source.wavelength = wavelength
+
+        # Store distance
+        if has_converter==True and detector.distance_unit != 'm':
+            conv = Converter('m')
+            distance = conv(distance, units=detector.distance_unit)
+        detector.distance = distance
+  
+        # Store transmission
+        output.sample.transmission = transmission
+        
+        # Store pixel size
+        pixel = 5.0
+        if has_converter==True and detector.pixel_size_unit != 'mm':
+            conv = Converter('mm')
+            pixel = conv(pixel, units=detector.pixel_size_unit)
+        detector.pixel_size.x = pixel
+        detector.pixel_size.y = pixel
+  
+        # Store beam center in distance units
+        detector.beam_center.x = center_x*pixel
+        detector.beam_center.y = center_y*pixel
+  
+        
+        # Store limits of the image (2D array)
+        xmin    =xmin-xstep/2.0
+        xmax    =xmax+xstep/2.0
+        ymin    =ymin-ystep/2.0
+        ymax    =ymax+ystep/2.0
+        if has_converter == True and output.Q_unit != '1/A':
+            xmin = data_conv_q(xmin, units=output.Q_unit)
+            xmax = data_conv_q(xmax, units=output.Q_unit)
+            ymin = data_conv_q(ymin, units=output.Q_unit)
+            ymax = data_conv_q(ymax, units=output.Q_unit)
+        output.xmin = xmin
+        output.xmax = xmax
+        output.ymin = ymin
+        output.ymax = ymax
+        
+        # Store x and y axis bin centers
+        output.x_bins     = x
+        output.y_bins     = y
+        
+        # Units
+        if data_conv_q is not None:
+            output.xaxis("\\rm{Q}", output.Q_unit)
+            output.yaxis("\\rm{Q}", output.Q_unit)
         else:
-            self.qmax = ymax
-        
-        #config.printEVT("Read %g points from file %s" % (ncounts, self.file))
-  
-        self.wavelength = wavelength
-        self.distance   = distance*1000.0
-        self.center_x = center_x
-        self.center_y = center_y
-        
-        from readInfo import ReaderInfo   
-        output = ReaderInfo()
-        output.Z=Z
-        output.xmin    =xmin-xstep/2.0
-        output.xmax    = xmax+xstep/2.0
-        output.ymin    =ymin-ystep/2.0
-        output.ymax    =ymax+ystep/2.0
-        output.x          = x
-        output.y          = y
-        output.wavelength = wavelength
-        output.distance   = distance*1000.0
-        output.center_x = center_x
-        output.center_y = center_y
-        output.type    ="2D"
-        
-        logging.info("IgorReader reading %s"%self.file)
+            output.xaxis("\\rm{Q}", 'A^{-1}')
+            output.yaxis("\\rm{Q}", 'A^{-1}')
+            
+        if data_conv_i is not None:
+            output.zaxis("\\{I(Q)}", output.I_unit)
+        else:
+            output.zaxis("\\rm{I(Q)}","cm^{-1}")
+    
+        
         return output
-     
+    
+if __name__ == "__main__": 
+    reader = Reader()
+    print reader.read("../test/MAR07232_rest.ASC") 
+    
Index: DataLoader/readers/abs_reader.py
===================================================================
--- DataLoader/readers/abs_reader.py	(revision 99d1af6082f75428716f6bace3bc5a668ba7a9b6)
+++ DataLoader/readers/abs_reader.py	(revision b99ac22702d9634282d084e8a7da3aa3064bccf2)
@@ -53,5 +53,5 @@
                 detector = Detector()
                 output.detector.append(detector)
-                self.filename = output.filename = basename
+                output.filename = basename
                 
                 is_info = False
@@ -111,6 +111,6 @@
                         try:
                             value = float(line_toks[5])
-                            if has_converter==True and output.sample.thickness_unit != 'mm':
-                                conv = Converter('mm')
+                            if has_converter==True and output.sample.thickness_unit != 'cm':
+                                conv = Converter('cm')
                                 output.sample.thickness = conv(value, units=output.sample.thickness_unit)
                             else:
Index: DataLoader/readers/danse_reader.py
===================================================================
--- DataLoader/readers/danse_reader.py	(revision 99d1af6082f75428716f6bace3bc5a668ba7a9b6)
+++ DataLoader/readers/danse_reader.py	(revision b99ac22702d9634282d084e8a7da3aa3064bccf2)
@@ -1,4 +1,18 @@
 """
     DANSE/SANS file reader
+"""
+
+"""
+This software was developed by the University of Tennessee as part of the
+Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+project funded by the US National Science Foundation. 
+
+If you use DANSE applications to do scientific research that leads to 
+publication, we ask that you acknowledge the use of the software with the 
+following sentence:
+
+"This work benefited from DANSE software developed under NSF award DMR-0520547." 
+
+copyright 2008, University of Tennessee
 """
 
@@ -24,5 +38,5 @@
     type = ["DANSE files (*.sans)|*.sans"]
     ## Extension
-    ext  = ['.sans']    
+    ext  = ['.sans', '.SANS']    
         
     def read(self, filename=None):
@@ -140,13 +154,4 @@
             xmax = None
             
-            #x = numpy.zeros(size_x)
-            #y = numpy.zeros(size_y)
-            #X, Y = pylab.meshgrid(x, y)
-            #Z = copy.deepcopy(X)
-            #E = copy.deepcopy(X)
-            itot = 0
-            i_x = 0
-            i_y = 0
-            
             # Qx and Qy vectors
             for i_x in range(size_x):
@@ -179,4 +184,8 @@
             
             # Store the data in the 2D array
+            itot = 0
+            i_x  = 0
+            i_y  = -1
+            
             for i_pt in range(len(data)):
                 try:
@@ -188,5 +197,5 @@
                 
                 # Get bin number
-                if math.fmod(itot, size_x)==0:
+                if math.fmod(i_pt, size_x)==0:
                     i_x = 0
                     i_y += 1
@@ -194,9 +203,10 @@
                     i_x += 1
                     
-                output.data[size_y-1-i_y][i_x] = value
+                output.data[i_y][i_x] = value       
+                #output.data[size_y-1-i_y][i_x] = value
                 if fversion>1.0:
-                    output.err_data[size_y-1-i_y][i_x] = error[i_pt]
-                
-                itot += 1
+                    output.err_data[i_y][i_x] = error[i_pt]
+                    #output.err_data[size_y-1-i_y][i_x] = error[i_pt]
+                
                 
             # Store all data ######################################
Index: DataLoader/test/sequence_tests.py
===================================================================
--- DataLoader/test/sequence_tests.py	(revision b99ac22702d9634282d084e8a7da3aa3064bccf2)
+++ DataLoader/test/sequence_tests.py	(revision b99ac22702d9634282d084e8a7da3aa3064bccf2)
@@ -0,0 +1,30 @@
+from DataLoader.loader import Loader
+from DataLoader.readers.IgorReader import Reader as igor_reader
+from DataLoader.readers.abs_reader import Reader as abs_reader
+
+
+def consecutive_loader():
+    out1 =  Loader().load("jan08002.ABS")
+    out2 = Loader().load("MAR07232_rest.ASC")
+    if len(out2.detector)>1:
+        print "Consecutive reads using Loader failed"
+
+def consecutive_reader():
+    out1 = abs_reader().read("jan08002.ABS")
+    out2 = igor_reader().read("MAR07232_rest.ASC")
+    if len(out2.detector)>1:
+        print "Consecutive reads using Readers failed"
+        print out1
+        print out2
+
+def single_abs():
+    out1 = abs_reader().read("jan08002.ABS")
+    
+def single_igor():
+    out1 = igor_reader().read("MAR07232_rest.ASC")
+
+if __name__ == "__main__": 
+    #consecutive_loader()
+    #consecutive_reader()
+    single_igor()
+    single_abs()
Index: DataLoader/test/testLoad.py
===================================================================
--- DataLoader/test/testLoad.py	(revision 8bd8ea439767ebb5cd5480a4da37e8e080d4f3df)
+++ DataLoader/test/testLoad.py	(revision b99ac22702d9634282d084e8a7da3aa3064bccf2)
@@ -107,5 +107,5 @@
         output=self.L.load('MP_New.sans')
         
-        self.assertEqual(output.wavelength,7.5)
+        self.assertEqual(output.source.wavelength,7.5)
         
         #tested corrupted file.sans
Index: DataLoader/test/utest_abs_reader.py
===================================================================
--- DataLoader/test/utest_abs_reader.py	(revision b99ac22702d9634282d084e8a7da3aa3064bccf2)
+++ DataLoader/test/utest_abs_reader.py	(revision b99ac22702d9634282d084e8a7da3aa3064bccf2)
@@ -0,0 +1,143 @@
+"""
+    Unit tests for data manipulations
+"""
+
+import unittest
+import numpy, math
+from DataLoader.loader import  Loader
+from DataLoader.data_info import Data1D
+ 
+import os.path
+
+class abs_reader(unittest.TestCase):
+    
+    def setUp(self):
+        self.data = Loader().load("jan08002.ABS")
+        
+    def test_checkdata(self):
+        """
+            Check the data content to see whether 
+            it matches the specific file we loaded.
+            Check the units too to see whether the
+            Data1D defaults changed. Otherwise the
+            tests won't pass
+        """
+        self.assertEqual(self.data.filename, "jan08002.ABS")
+        
+        self.assertEqual(self.data.source.wavelength_unit, 'A')
+        self.assertEqual(self.data.source.wavelength, 6.0)
+        
+        self.assertEqual(self.data.detector[0].distance_unit, 'mm')
+        self.assertEqual(self.data.detector[0].distance, 1000.0)
+        
+        self.assertEqual(self.data.sample.transmission, 0.5667)
+        
+        self.assertEqual(self.data.detector[0].beam_center_unit, 'mm')
+        center_x = 114.58*5.0
+        center_y = 64.22*5.0
+        self.assertEqual(self.data.detector[0].beam_center.x, center_x)
+        self.assertEqual(self.data.detector[0].beam_center.y, center_y)
+        
+        self.assertEqual(self.data.y_unit, '1/cm')
+        self.assertEqual(self.data.x[0], 0.002618)
+        self.assertEqual(self.data.x[1], 0.007854)
+        self.assertEqual(self.data.x[2], 0.01309)
+        self.assertEqual(self.data.x[126], 0.5828)
+        
+        self.assertEqual(self.data.y[0], 0.02198)
+        self.assertEqual(self.data.y[1], 0.02201)
+        self.assertEqual(self.data.y[2], 0.02695)
+        self.assertEqual(self.data.y[126], 0.2958)
+        
+        self.assertEqual(self.data.dy[0], 0.002704)
+        self.assertEqual(self.data.dy[1], 0.001643)
+        self.assertEqual(self.data.dy[2], 0.002452)
+        self.assertEqual(self.data.dy[126], 1)
+        
+    def test_checkdata2(self):
+        self.assertEqual(self.data.dy[126], 1)
+
+class igor_reader(unittest.TestCase):
+    
+    def setUp(self):
+        self.data = Loader().load("MAR07232_rest.ASC")
+        
+    def test_checkdata(self):
+        """
+            Check the data content to see whether 
+            it matches the specific file we loaded.
+            Check the units too to see whether the
+            Data1D defaults changed. Otherwise the
+            tests won't pass
+        """
+        self.assertEqual(self.data.filename, "MAR07232_rest.ASC")
+        
+        self.assertEqual(self.data.source.wavelength_unit, 'A')
+        self.assertEqual(self.data.source.wavelength, 8.4)
+        
+        self.assertEqual(self.data.detector[0].distance_unit, 'mm')
+        self.assertEqual(self.data.detector[0].distance, 13705)
+        
+        self.assertEqual(self.data.sample.transmission, 0.84357)
+        
+        self.assertEqual(self.data.detector[0].beam_center_unit, 'mm')
+        center_x = 68.76*5.0
+        center_y = 62.47*5.0
+        self.assertEqual(self.data.detector[0].beam_center.x, center_x)
+        self.assertEqual(self.data.detector[0].beam_center.y, center_y)
+        
+        self.assertEqual(self.data.I_unit, '1/cm')
+        self.assertEqual(self.data.data[0][0], 0.279783)
+        self.assertEqual(self.data.data[0][1], 0.28951)
+        self.assertEqual(self.data.data[0][2], 0.167634)
+        
+class danse_reader(unittest.TestCase):
+    
+    def setUp(self):
+        self.data = Loader().load("MP_New.sans")
+
+    def test_checkdata(self):
+        """
+            Check the data content to see whether 
+            it matches the specific file we loaded.
+            Check the units too to see whether the
+            Data1D defaults changed. Otherwise the
+            tests won't pass
+        """
+        self.assertEqual(self.data.filename, "MP_New.sans")
+        
+        self.assertEqual(self.data.source.wavelength_unit, 'A')
+        self.assertEqual(self.data.source.wavelength, 7.5)
+        
+        self.assertEqual(self.data.detector[0].distance_unit, 'mm')
+        self.assertAlmostEqual(self.data.detector[0].distance, 5414.99, 3)
+        
+        self.assertEqual(self.data.detector[0].beam_center_unit, 'mm')
+        center_x = 68.74*5.0
+        center_y = 64.77*5.0
+        self.assertEqual(self.data.detector[0].beam_center.x, center_x)
+        self.assertEqual(self.data.detector[0].beam_center.y, center_y)
+        
+        self.assertEqual(self.data.I_unit, '1/cm')
+        self.assertEqual(self.data.data[0][0], 1.57831)
+        self.assertEqual(self.data.data[0][1], 2.70983)
+        self.assertEqual(self.data.data[0][2], 3.83422)
+
+        self.assertEqual(self.data.err_data[0][0], 1.37607)
+        self.assertEqual(self.data.err_data[0][1], 1.77569)
+        self.assertEqual(self.data.err_data[0][2], 2.06313)
+
+ 
+class cansas_reader(unittest.TestCase):
+    
+    def setUp(self):
+        self.data = Loader().load("cansas1d.xml")
+ 
+        
+        
+        
+            
+
+if __name__ == '__main__':
+    unittest.main()
+   
