Index: nsdataloader/readers/IgorReader.py
===================================================================
--- sansdataloader/readers/IgorReader.py	(revision aab4e1501beed9965c9e6c08d09fcd8e34a20adb)
+++ 	(revision )
@@ -1,314 +1,0 @@
-
-############################################################################
-#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
-#############################################################################
-
-"""
-    IGOR 2D reduced file reader
-"""
-
-import os
-#import sys
-import numpy
-import math
-#import logging
-from DataLoader.data_info import Data2D
-from DataLoader.data_info import Detector
-from DataLoader.manipulations import reader2D_converter
-
-# 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 """
-    ## File type
-    type_name = "IGOR 2D"   
-    ## Wildcards
-    type = ["IGOR 2D files (*.ASC)|*.ASC"]
-    ## Extension
-    ext=['.ASC', '.asc']
-
-    def read(self,filename=None):
-        """ Read file """
-        if not os.path.isfile(filename):
-            raise ValueError, \
-            "Specified file %s is not a regular file" % filename
-        
-        # Read file
-        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)
-                
-        # Get content
-        dataStarted = False
-        
-        
-        lines = buf.split('\n')
-        itot = 0
-        x = []
-        y = []
-        
-        ncounts = 0
-        
-        xmin = None
-        xmax = None
-        ymin = None
-        ymax = None
-        
-        i_x = 0
-        i_y = -1
-        i_tot_row = 0
-        
-        isInfo = False
-        isCenter = False
-       
-        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)            
-         
-        for line in lines:
-            
-            # Find setup info line
-            if isInfo:
-                isInfo = False
-                line_toks = line.split()
-                # Wavelength in Angstrom
-                try:
-                    wavelength = float(line_toks[1])
-                except:
-                    msg = "IgorReader: can't read this file, missing wavelength"
-                    raise ValueError, msg
-                
-            #Find # of bins in a row assuming the detector is square.
-            if dataStarted == True:
-                try:
-                    value = float(line)
-                except:
-                    # Found a non-float entry, skip it
-                    continue
-                
-                # Get total bin number
-                
-            i_tot_row += 1
-        i_tot_row=math.ceil(math.sqrt(i_tot_row))-1 
-        #print "i_tot", i_tot_row
-        size_x = i_tot_row#192#128
-        size_y = i_tot_row#192#128
-        output.data = numpy.zeros([size_x,size_y])
-        output.err_data = numpy.zeros([size_x,size_y])
-     
-        #Read Header and 2D data
-        for line in lines:
-            # Find setup info line
-            if isInfo:
-                isInfo = False
-                line_toks = line.split()
-                # Wavelength in Angstrom
-                try:
-                    wavelength = float(line_toks[1])
-                except:
-                    msg = "IgorReader: can't read this file, missing wavelength"
-                    raise ValueError, msg
-                # Distance in meters
-                try:
-                    distance = float(line_toks[3])
-                except:
-                    msg = "IgorReader: can't read this file, missing distance"
-                    raise ValueError, msg
-                
-                # Distance in meters
-                try:
-                    transmission = float(line_toks[4])
-                except:
-                    msg = "IgorReader: can't read this file, "
-                    msg += "missing transmission"
-                    raise ValueError, msg
-                                            
-            if line.count("LAMBDA")>0:
-                isInfo = True
-                
-            # Find center info line
-            if isCenter:
-                isCenter = False                
-                line_toks = line.split()
-                
-                # Center in bin number: Must substrate 1 because 
-                #the index starts from 1
-                center_x = float(line_toks[0])-1
-                center_y = float(line_toks[1])-1
-
-            if line.count("BCENT")>0:
-                isCenter = True
-                
-        
-            # Find data start
-            if line.count("***")>0:
-                dataStarted = True
-                
-                # Check that we have all the info
-                if wavelength == None \
-                    or distance == None \
-                    or center_x == None \
-                    or center_y == None:
-                    msg = "IgorReader:Missing information in data file"
-                    raise ValueError, msg
-                
-            if dataStarted == True:
-                try:
-                    value = float(line)
-                except:
-                    # Found a non-float entry, skip it
-                    continue
-                
-                # Get bin number
-                if math.fmod(itot, i_tot_row)==0:
-                    i_x = 0
-                    i_y += 1
-                else:
-                    i_x += 1
-                    
-                output.data[i_y][i_x] = value
-                ncounts += 1 
-                
-                # Det 640 x 640 mm
-                # Q = 4pi/lambda sin(theta/2)
-                # Bin size is 0.5 cm 
-                #REmoved +1 from theta = (i_x-center_x+1)*0.5 / distance 
-                # / 100.0 and 
-                #REmoved +1 from theta = (i_y-center_y+1)*0.5 /
-                # distance / 100.0
-                #ToDo: Need  complete check if the following
-                # covert process is consistent with fitting.py.
-                theta = (i_x-center_x)*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
-                if xmax==None or qx>xmax:
-                    xmax = qx
-                
-                theta = (i_y-center_y)*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
-                if ymax==None or qy>ymax:
-                    ymax = qy
-                
-                if not qx in x:
-                    x.append(qx)
-                if not qy in y:
-                    y.append(qy)
-                
-                itot += 1
-                  
-                  
-        theta = 0.25 / distance / 100.0
-        xstep = 4.0*math.pi/wavelength * math.sin(theta/2.0)
-        
-        theta = 0.25 / distance / 100.0
-        ystep = 4.0*math.pi/wavelength * math.sin(theta/2.0)
-        
-        # 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_{x}}", output.Q_unit)
-            output.yaxis("\\rm{Q_{y}}", output.Q_unit)
-        else:
-            output.xaxis("\\rm{Q_{x}}", 'A^{-1}')
-            output.yaxis("\\rm{Q_{y}}", 'A^{-1}')
-            
-        if data_conv_i is not None:
-            output.zaxis("\\rm{Intensity}", output.I_unit)
-        else:
-            output.zaxis("\\rm{Intensity}","cm^{-1}")
-    
-        # Store loading process information
-        output.meta_data['loader'] = self.type_name
-        output = reader2D_converter(output)
-
-        return output
-    
-if __name__ == "__main__": 
-    reader = Reader()
-    print reader.read("../test/MAR07232_rest.ASC") 
-    
Index: nsdataloader/readers/__init__.py
===================================================================
--- sansdataloader/readers/__init__.py	(revision aab4e1501beed9965c9e6c08d09fcd8e34a20adb)
+++ 	(revision )
@@ -1,13 +1,0 @@
-# Backward compatibility with the previous implementation of the default readers
-from associations import register_readers
-
-# Method to associate extensions to default readers 
-from associations import read_associations
-
-# Method to return the location of the XML settings file
-def get_data_path():
-    """
-        Return the location of the settings file for the data readers.
-    """
-    import os
-    return os.path.dirname(__file__)
Index: nsdataloader/readers/abs_reader.py
===================================================================
--- sansdataloader/readers/abs_reader.py	(revision aab4e1501beed9965c9e6c08d09fcd8e34a20adb)
+++ 	(revision )
@@ -1,263 +1,0 @@
-"""
-"""
-#####################################################################
-#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. 
-#See the license text in license.txt
-#copyright 2008, University of Tennessee
-######################################################################
-
-import numpy
-import os
-from DataLoader.data_info import Data1D
-from DataLoader.data_info import Detector
-
-has_converter = True
-try:
-    from data_util.nxsunit import Converter
-except:
-    has_converter = False
-    
-class Reader:
-    """
-    Class to load IGOR reduced .ABS files
-    """
-    ## File type
-    type_name = "IGOR 1D"   
-    ## Wildcards
-    type = ["IGOR 1D files (*.abs)|*.abs"]
-    ## List of allowed extensions
-    ext = ['.abs', '.ABS']  
-    
-    def read(self, path):
-        """ 
-        Load data file.
-        
-        :param path: file path
-        
-        :return: Data1D object, or None
-        
-        :raise RuntimeError: when the file can't be opened
-        :raise ValueError: when the length of the data vectors are inconsistent
-        """
-        if os.path.isfile(path):
-            basename  = os.path.basename(path)
-            root, extension = os.path.splitext(basename)
-            if extension.lower() in self.ext:
-                try:
-                    input_f =  open(path,'r')
-                except :
-                    raise  RuntimeError, "abs_reader: cannot open %s" % path
-                buff = input_f.read()
-                lines = buff.split('\n')
-                x  = numpy.zeros(0)
-                y  = numpy.zeros(0)
-                dy = numpy.zeros(0)
-                dx = numpy.zeros(0)
-                output = Data1D(x, y, dy=dy, dx=dx)
-                detector = Detector()
-                output.detector.append(detector)
-                output.filename = basename
-                
-                is_info = False
-                is_center = False
-                is_data_started = False
-                
-                data_conv_q = None
-                data_conv_i = None
-                
-                if has_converter == True and output.x_unit != '1/A':
-                    data_conv_q = Converter('1/A')
-                    # Test it
-                    data_conv_q(1.0, output.x_unit)
-                    
-                if has_converter == True and output.y_unit != '1/cm':
-                    data_conv_i = Converter('1/cm')
-                    # Test it
-                    data_conv_i(1.0, output.y_unit)
-                
-                for line in lines:
-                    
-                    # Information line 1
-                    if is_info == True:
-                        is_info = False
-                        line_toks = line.split()
-                        
-                        # Wavelength in Angstrom
-                        try:
-                            value = float(line_toks[1])
-                            if has_converter == True and \
-                                output.source.wavelength_unit != 'A':
-                                conv = Converter('A')
-                                output.source.wavelength = conv(value, 
-                                        units=output.source.wavelength_unit)
-                            else:
-                                output.source.wavelength = value
-                        except:
-                            #goes to ASC reader
-                            msg = "abs_reader: cannot open %s" % path
-                            raise  RuntimeError, msg
-                            #raise ValueError,"IgorReader: can't read this file,
-                            # missing wavelength"
-                        
-                        # Distance in meters
-                        try:
-                            value = float(line_toks[3])
-                            if has_converter == True and \
-                                detector.distance_unit != 'm':
-                                conv = Converter('m')
-                                detector.distance = conv(value, 
-                                                units=detector.distance_unit)
-                            else:
-                                detector.distance = value
-                        except:
-                            #goes to ASC reader
-                            msg = "abs_reader: cannot open %s" % path
-                            raise  RuntimeError, msg
-                        # Transmission 
-                        try:
-                            output.sample.transmission = float(line_toks[4])
-                        except:
-                            # Transmission is not a mandatory entry
-                            pass
-                    
-                        # Thickness in mm
-                        try:
-                            value = float(line_toks[5])
-                            if has_converter == True and \
-                                output.sample.thickness_unit != 'cm':
-                                conv = Converter('cm')
-                                output.sample.thickness = conv(value, 
-                                            units=output.sample.thickness_unit)
-                            else:
-                                output.sample.thickness = value
-                        except:
-                            # Thickness is not a mandatory entry
-                            pass
-                    
-                    #MON CNT   LAMBDA   DET ANG   DET DIST   TRANS   THICK 
-                    #  AVE   STEP
-                    if line.count("LAMBDA") > 0:
-                        is_info = True
-                        
-                    # Find center info line
-                    if is_center == True:
-                        is_center = False                
-                        line_toks = line.split()
-                        # Center in bin number
-                        center_x = float(line_toks[0])
-                        center_y = float(line_toks[1])
-                        
-                        # Bin size
-                        if has_converter == True and \
-                            detector.pixel_size_unit != 'mm':
-                            conv = Converter('mm')
-                            detector.pixel_size.x = conv(5.0, 
-                                                units=detector.pixel_size_unit)
-                            detector.pixel_size.y = conv(5.0,
-                                                units=detector.pixel_size_unit)
-                        else:
-                            detector.pixel_size.x = 5.0
-                            detector.pixel_size.y = 5.0
-                        
-                        # Store beam center in distance units
-                        # Det 640 x 640 mm
-                        if has_converter==True and \
-                            detector.beam_center_unit != 'mm':
-                            conv = Converter('mm')
-                            detector.beam_center.x = conv(center_x * 5.0,
-                                             units=detector.beam_center_unit)
-                            detector.beam_center.y = conv(center_y * 5.0, 
-                                            units=detector.beam_center_unit)
-                        else:
-                            detector.beam_center.x = center_x * 5.0
-                            detector.beam_center.y = center_y * 5.0
-                        
-                        # Detector type
-                        try:
-                            detector.name = line_toks[7]
-                        except:
-                            # Detector name is not a mandatory entry
-                            pass
-                    
-                    #BCENT(X,Y)   A1(mm)   A2(mm)   A1A2DIST(m)   DL/L 
-                    #  BSTOP(mm)   DET_TYP 
-                    if line.count("BCENT") > 0:
-                        is_center = True
-                        
-                    # Parse the data
-                    if is_data_started == True:
-                        toks = line.split()
-
-                        try:  
-                            _x  = float(toks[0])
-                            _y  = float(toks[1]) 
-                            _dy = float(toks[2])
-                            _dx = float(toks[3])
-                            
-                            if data_conv_q is not None:
-                                _x = data_conv_q(_x, units=output.x_unit)
-                                _dx = data_conv_i(_dx, units=output.x_unit)
-                                
-                            if data_conv_i is not None:
-                                _y = data_conv_i(_y, units=output.y_unit)
-                                _dy = data_conv_i(_dy, units=output.y_unit)
-                           
-                            x  = numpy.append(x,   _x) 
-                            y  = numpy.append(y,   _y)
-                            dy = numpy.append(dy, _dy)
-                            dx  = numpy.append(dx, _dx)
-                            
-                        except:
-                            # Could not read this data line. If we are here
-                            # it is because we are in the data section. Just
-                            # skip it.
-                            pass
-                            
-                    #The 6 columns are | Q (1/A) | I(Q) (1/cm) | std. dev.
-                    # I(Q) (1/cm) | sigmaQ | meanQ | ShadowFactor|
-                    if line.count("The 6 columns")>0:
-                        is_data_started = True
-            
-                # Sanity check
-                if not len(y) == len(dy):
-                    msg = "abs_reader: y and dy have different length"
-                    raise ValueError, msg
-                # If the data length is zero, consider this as
-                # though we were not able to read the file.
-                if len(x) == 0:
-                    raise ValueError, "ascii_reader: could not load file"
-                
-                # Zeros in dx, dy 
-                if not numpy.all(dx==0):
-                    dx[dx==0] = _ZERO
-                if not numpy.all(dy==0):
-                    dy[dy==0] = _ZERO
-
-                output.x = x[x!=0]
-                output.y = y[x!=0]
-                output.dy = dy[x!=0]
-                output.dx = dx[x!=0]
-                if data_conv_q is not None:
-                    output.xaxis("\\rm{Q}", output.x_unit)
-                else:
-                    output.xaxis("\\rm{Q}", 'A^{-1}')
-                if data_conv_i is not None:
-                    output.yaxis("\\rm{Intensity}", output.y_unit)
-                else:
-                    output.yaxis("\\rm{Intensity}","cm^{-1}")
-                    
-                # Store loading process information
-                output.meta_data['loader'] = self.type_name                       
-                return output
-        else:
-            raise RuntimeError, "%s is not a file" % path
-        return None
-    
-if __name__ == "__main__": 
-    reader = Reader()
-    print reader.read("../test/jan08002.ABS")
-    
-    
-            
Index: nsdataloader/readers/ascii_reader.py
===================================================================
--- sansdataloader/readers/ascii_reader.py	(revision aab4e1501beed9965c9e6c08d09fcd8e34a20adb)
+++ 	(revision )
@@ -1,361 +1,0 @@
-
-
-############################################################################
-#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 numpy
-import os
-from DataLoader.data_info import Data1D
-
-# Check whether we have a converter available
-has_converter = True
-try:
-    from data_util.nxsunit import Converter
-except:
-    has_converter = False
-_ZERO = 1e-16
-
-class Reader:
-    """
-    Class to load ascii files (2, 3 or 4 columns).
-    """
-    ## File type
-    type_name = "ASCII"
-    
-    ## Wildcards
-    type = ["ASCII files (*.txt)|*.txt",
-            "ASCII files (*.dat)|*.dat",
-            "ASCII files (*.abs)|*.abs"]
-    ## List of allowed extensions
-    ext = ['.txt', '.TXT', '.dat', '.DAT', '.abs', '.ABS']  
-    
-    ## Flag to bypass extension check
-    allow_all = True
-    
-    def read(self, path):
-        """ 
-        Load data file
-        
-        :param path: file path
-        
-        :return: Data1D object, or None
-        
-        :raise RuntimeError: when the file can't be opened
-        :raise ValueError: when the length of the data vectors are inconsistent
-        """
-        if os.path.isfile(path):
-            basename  = os.path.basename(path)
-            _, extension = os.path.splitext(basename)
-            if self.allow_all or extension.lower() in self.ext:
-                try:
-                    input_f =  open(path,'r')
-                except :
-                    raise  RuntimeError, "ascii_reader: cannot open %s" % path
-                buff = input_f.read()
-                lines = buff.split('\n')
-                
-                #Jae could not find python universal line spliter: 
-                #keep the below for now
-                # some ascii data has \r line separator,
-                # try it when the data is on only one long line
-                if len(lines) < 2 : 
-                    lines = buff.split('\r')
-                 
-                x  = numpy.zeros(0)
-                y  = numpy.zeros(0)
-                dy = numpy.zeros(0)
-                dx = numpy.zeros(0)
-                
-               #temp. space to sort data
-                tx  = numpy.zeros(0)
-                ty  = numpy.zeros(0)
-                tdy = numpy.zeros(0)
-                tdx = numpy.zeros(0)
-                
-                output = Data1D(x, y, dy=dy, dx=dx)
-                self.filename = output.filename = basename
-           
-                data_conv_q = None
-                data_conv_i = None
-                
-                if has_converter == True and output.x_unit != '1/A':
-                    data_conv_q = Converter('1/A')
-                    # Test it
-                    data_conv_q(1.0, output.x_unit)
-                    
-                if has_converter == True and output.y_unit != '1/cm':
-                    data_conv_i = Converter('1/cm')
-                    # Test it
-                    data_conv_i(1.0, output.y_unit)
-           
-                
-                # The first good line of data will define whether
-                # we have 2-column or 3-column ascii
-                has_error_dx = None
-                has_error_dy = None
-                
-                #Initialize counters for data lines and header lines.
-                is_data = False #Has more than 5 lines
-                # More than "5" lines of data is considered as actual
-                # data unless that is the only data
-                mum_data_lines = 5 
-                # To count # of current data candidate lines
-                i = -1  
-                # To count total # of previous data candidate lines          
-                i1 = -1 
-                # To count # of header lines          
-                j = -1
-                # Helps to count # of header lines            
-                j1 = -1
-                #minimum required number of columns of data; ( <= 4).           
-                lentoks = 2     
-                for line in lines:
-                    toks = line.split()
-                    try:
-                        #Make sure that all columns are numbers.
-                        for colnum in range(len(toks)):
-                            float(toks[colnum])
-                            
-                        _x = float(toks[0])
-                        _y = float(toks[1])
-                        
-                        #Reset the header line counters
-                        if j == j1:
-                            j = 0
-                            j1 = 0
-                            
-                        if i > 1:
-                            is_data = True
-                        
-                        if data_conv_q is not None:
-                            _x = data_conv_q(_x, units=output.x_unit)
-                            
-                        if data_conv_i is not None:
-                            _y = data_conv_i(_y, units=output.y_unit)                        
-                        
-                        # If we have an extra token, check
-                        # whether it can be interpreted as a
-                        # third column.
-                        _dy = None
-                        if len(toks) > 2:
-                            try:
-                                _dy = float(toks[2])
-                                
-                                if data_conv_i is not None:
-                                    _dy = data_conv_i(_dy, units=output.y_unit)
-                                
-                            except:
-                                # The third column is not a float, skip it.
-                                pass
-                            
-                        # If we haven't set the 3rd column
-                        # flag, set it now.
-                        if has_error_dy == None:
-                            has_error_dy = False if _dy == None else True
-                            
-                        #Check for dx
-                        _dx = None
-                        if len(toks) > 3:
-                            try:
-                                _dx = float(toks[3])
-                                
-                                if data_conv_i is not None:
-                                    _dx = data_conv_i(_dx, units=output.x_unit)
-                                
-                            except:
-                                # The 4th column is not a float, skip it.
-                                pass
-                            
-                        # If we haven't set the 3rd column
-                        # flag, set it now.
-                        if has_error_dx == None:
-                            has_error_dx = False if _dx == None else True
-                        
-                        #After talked with PB, we decided to take care of only 
-                        # 4 columns of data for now.
-                        #number of columns in the current line
-                        #To remember the # of columns in the current 
-                        #line of data
-                        new_lentoks = len(toks)
-                        
-                        #If the previous columns not equal to the current, 
-                        #mark the previous as non-data and reset the dependents.  
-                        if lentoks != new_lentoks :
-                            if is_data == True:
-                                break
-                            else:
-                                i = -1
-                                i1 = 0
-                                j = -1
-                                j1 = -1
-                            
-                            
-                        #Delete the previously stored lines of data candidates
-                        # if is not data.
-                        if i < 0 and -1 < i1 < mum_data_lines and \
-                            is_data == False:
-                            try:
-                                x = numpy.zeros(0)
-                                y = numpy.zeros(0)
-                            except:
-                                pass
-                            
-                        x  = numpy.append(x,   _x) 
-                        y  = numpy.append(y,   _y)
-                        
-                        if has_error_dy == True:
-                            #Delete the previously stored lines of
-                            # data candidates if is not data.
-                            if i < 0 and -1 < i1 < mum_data_lines and \
-                                is_data == False:
-                                try:
-                                    dy = numpy.zeros(0)  
-                                except:
-                                    pass                                                               
-                            dy = numpy.append(dy, _dy)
-                            
-                        if has_error_dx == True:
-                            #Delete the previously stored lines of
-                            # data candidates if is not data.
-                            if i < 0 and -1 < i1 < mum_data_lines and \
-                                is_data == False:
-                                try:
-                                    dx = numpy.zeros(0)                            
-                                except:
-                                    pass                                                               
-                            dx = numpy.append(dx, _dx)
-                            
-                        #Same for temp.
-                        #Delete the previously stored lines of data candidates
-                        # if is not data.
-                        if i < 0 and -1 < i1 < mum_data_lines and\
-                            is_data == False:
-                            try:
-                                tx = numpy.zeros(0)
-                                ty = numpy.zeros(0)
-                            except:
-                                pass                                                           
-
-                        tx  = numpy.append(tx,   _x) 
-                        ty  = numpy.append(ty,   _y)
-                        
-                        if has_error_dy == True:
-                            #Delete the previously stored lines of
-                            # data candidates if is not data.
-                            if i < 0 and -1 < i1 < mum_data_lines and \
-                                is_data == False:
-                                try:
-                                    tdy = numpy.zeros(0)
-                                except:
-                                    pass                                                                                                                
-                            tdy = numpy.append(tdy, _dy)
-                        if has_error_dx == True:
-                            #Delete the previously stored lines of
-                            # data candidates if is not data.
-                            if i < 0 and -1 < i1 < mum_data_lines and \
-                                is_data == False:
-                                try:
-                                    tdx = numpy.zeros(0)
-                                except:
-                                    pass                                                                                                          
-                            tdx = numpy.append(tdx, _dx)
-
-                        #reset i1 and flag lentoks for the next
-                        if lentoks < new_lentoks:
-                            if is_data == False:
-                                i1 = -1                            
-                        #To remember the # of columns on the current line
-                        # for the next line of data
-                        lentoks = len(toks)
-                        
-                        #Reset # of header lines and counts # 
-                        # of data candidate lines    
-                        if j == 0 and j1 == 0:
-                            i1 = i + 1                            
-                        i += 1
-                    except:
-
-                        # It is data and meet non - number, then stop reading
-                        if is_data == True:
-                            break    
-                        lentoks = 2
-                        #Counting # of header lines                    
-                        j += 1
-                        if j == j1 + 1:
-                            j1 = j                            
-                        else:                            
-                            j = -1
-                        #Reset # of lines of data candidates
-                        i = -1
-                        
-                        # Couldn't parse this line, skip it 
-                        pass
-                    
-                input_f.close()     
-                # Sanity check
-                if has_error_dy == True and not len(y) == len(dy):
-                    msg = "ascii_reader: y and dy have different length"
-                    raise RuntimeError, msg
-                if has_error_dx == True and not len(x) == len(dx):
-                    msg = "ascii_reader: y and dy have different length"
-                    raise RuntimeError, msg
-                # If the data length is zero, consider this as
-                # though we were not able to read the file.
-                if len(x) == 0:
-                    raise RuntimeError, "ascii_reader: could not load file"
-                
-                #Let's re-order the data to make cal.
-                # curve look better some cases
-                ind = numpy.lexsort((ty, tx))
-                for i in ind:
-                    x[i] = tx[ind[i]]
-                    y[i] = ty[ind[i]]
-                    if has_error_dy == True:
-                        dy[i] = tdy[ind[i]]
-                    if has_error_dx == True:
-                        dx[i] = tdx[ind[i]]
-                # Zeros in dx, dy 
-                if has_error_dx:
-                    dx[dx==0] = _ZERO
-                if has_error_dy:
-                    dy[dy==0] = _ZERO
-                #Data    
-                output.x = x[x!=0]
-                output.y = y[x!=0]
-                output.dy = dy[x!=0] if has_error_dy == True else numpy.zeros(len(output.y))
-                output.dx = dx[x!=0] if has_error_dx == True else numpy.zeros(len(output.x))
-                                
-                if data_conv_q is not None:
-                    output.xaxis("\\rm{Q}", output.x_unit)
-                else:
-                    output.xaxis("\\rm{Q}", 'A^{-1}')
-                if data_conv_i is not None:
-                    output.yaxis("\\rm{Intensity}", output.y_unit)
-                else:
-                    output.yaxis("\\rm{Intensity}","cm^{-1}")
-                    
-                # Store loading process information
-                output.meta_data['loader'] = self.type_name    
-                    
-                return output
-            
-        else:
-            raise RuntimeError, "%s is not a file" % path
-        return None
-    
-if __name__ == "__main__": 
-    reader = Reader()
-    #print reader.read("../test/test_3_columns.txt")
-    print reader.read("../test/empty.txt")
-    
-    
-                        
Index: nsdataloader/readers/associations.py
===================================================================
--- sansdataloader/readers/associations.py	(revision aab4e1501beed9965c9e6c08d09fcd8e34a20adb)
+++ 	(revision )
@@ -1,125 +1,0 @@
-
-
-############################################################################
-#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 2009, University of Tennessee
-#############################################################################
-
-
-"""
-Module to associate default readers to file extensions.
-The module reads an xml file to get the readers for each file extension.
-The readers are tried in order they appear when reading a file.
-"""
-
-import os
-import sys
-import logging
-from lxml import etree 
-# Py2exe compatibility: import _elementpath to ensure that py2exe finds it
-from lxml import _elementpath  
-
-## Format version for the XML settings file
-VERSION = 'sansloader/1.0'
-
-def read_associations(loader, settings='defaults.xml'):
-    """
-    Read the specified settings file to associate
-    default readers to file extension.
-    
-    :param loader: Loader object
-    :param settings: path to the XML settings file [string]
-    """
-    reader_dir = os.path.dirname(__file__)
-    path = os.path.join(reader_dir, settings)
-    
-    # If we can't find the file in the installation
-    # directory, look into the execution directory.
-    if not os.path.isfile(path):
-        path = os.path.join(os.getcwd(), settings)
-    if not os.path.isfile(path):
-        path = os.path.join(os.path.dirname(os.path.sys.path[0]), settings)
-    if os.path.isfile(path):
-        tree = etree.parse(path, parser=etree.ETCompatXMLParser())
-        
-        # Check the format version number
-        # Specifying the namespace will take care of the file format version 
-        root = tree.getroot()
-        
-        # Read in the file extension associations
-        entry_list = root.xpath('/ns:SansLoader/ns:FileType',
-                                 namespaces={'ns': VERSION})
-
-        # For each FileType entry, get the associated reader and extension
-        for entry in entry_list:
-            reader = entry.get('reader')
-            ext    = entry.get('extension')
-            
-            if reader is not None and ext is not None:
-                # Associate the extension with a particular reader
-                # TODO: Modify the Register code to be case-insensitive 
-                # and remove the extra line below.
-                try:
-                    exec "import %s" % reader
-                    exec "loader.associate_file_type('%s', %s)" % (ext.lower(),
-                                                                    reader)
-                    exec "loader.associate_file_type('%s', %s)" % (ext.upper(),
-                                                                    reader)
-                except:
-                    msg = "read_associations: skipping association"
-                    msg += " for %s\n  %s" % (attr['extension'], sys.exc_value)
-                    logging.error(msg)
-         
-         
-def register_readers(registry_function):
-    """
-    Function called by the registry/loader object to register
-    all default readers using a call back function.
-    
-    :WARNING: this method is now obsolete
-
-    :param registry_function: function to be called to register each reader
-    """
-    logging.info("register_readers is now obsolete: use read_associations()")
-    import abs_reader
-    import cansas_reader
-    import ascii_reader
-    import cansas_reader
-    import danse_reader
-    import hfir1d_reader
-    import IgorReader
-    import red2d_reader
-    import tiff_reader
-
-    registry_function(abs_reader)
-    registry_function(cansas_reader)
-    registry_function(ascii_reader)
-    registry_function(cansas_reader)
-    registry_function(danse_reader)
-    registry_function(hfir1d_reader)
-    registry_function(IgorReader)
-    registry_function(red2d_reader)
-    registry_function(tiff_reader)
-    
-    return True            
-
-
-if __name__ == "__main__": 
-    logging.basicConfig(level=logging.INFO,
-                        format='%(asctime)s %(levelname)s %(message)s',
-                        filename='logger.log',
-                        filemode='w')
-    from DataLoader.loader import Loader
-    l = Loader()
-    read_associations(l)
-    
-    
-    print l.get_wildcards()
-    
-    
Index: nsdataloader/readers/cansas_reader.py
===================================================================
--- sansdataloader/readers/cansas_reader.py	(revision aab4e1501beed9965c9e6c08d09fcd8e34a20adb)
+++ 	(revision )
@@ -1,947 +1,0 @@
-
-
-############################################################################
-#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,2009 University of Tennessee
-#############################################################################
-
-# Known issue: reader not compatible with multiple SASdata entries
-# within a single SASentry. Will raise a runtime error.
-
-#TODO: check that all vectors are written only if they have at 
-#    least one non-empty value
-#TODO: Writing only allows one SASentry per file.
-#     Would be best to allow multiple entries.
-#TODO: Store error list
-#TODO: Allow for additional meta data for each section
-#TODO: Notes need to be implemented. They can be any XML 
-#    structure in version 1.0
-#      Process notes have the same problem.
-#TODO: Unit conversion is not complete (temperature units are missing)
-
-
-import logging
-import numpy
-import os
-import sys
-from DataLoader.data_info import Data1D
-from DataLoader.data_info import Collimation
-from DataLoader.data_info import Detector
-from DataLoader.data_info import Process
-from DataLoader.data_info import Aperture
-from lxml import etree
-import xml.dom.minidom
-_ZERO = 1e-16
-has_converter = True
-try:
-    from data_util.nxsunit import Converter
-except:
-    has_converter = False
-
-CANSAS_NS = "cansas1d/1.0"
-
-def write_node(doc, parent, name, value, attr={}):
-    """
-    :param doc: document DOM
-    :param parent: parent node
-    :param name: tag of the element
-    :param value: value of the child text node
-    :param attr: attribute dictionary
-    
-    :return: True if something was appended, otherwise False
-    """
-    if value is not None:
-        node = doc.createElement(name)
-        node.appendChild(doc.createTextNode(str(value)))
-        for item in attr:
-            node.setAttribute(item, attr[item])
-        parent.appendChild(node)
-        return True
-    return False
-
-def get_content(location, node):
-    """
-    Get the first instance of the content of a xpath location.
-    
-    :param location: xpath location
-    :param node: node to start at
-    
-    :return: Element, or None
-    """
-    nodes = node.xpath(location, namespaces={'ns': CANSAS_NS})
-    
-    if len(nodes)>0:
-        return nodes[0]
-    else:
-        return None
-
-def get_float(location, node):
-    """
-    Get the content of a node as a float 
-    
-    :param location: xpath location
-    :param node: node to start at
-    """
-    nodes = node.xpath(location, namespaces={'ns': CANSAS_NS})
-    
-    value = None
-    attr = {}
-    if len(nodes) > 0:
-        try:
-            value = float(nodes[0].text)   
-        except:
-            # Could not pass, skip and return None
-            msg = "cansas_reader.get_float: could not "
-            msg += " convert '%s' to float" % nodes[0].text
-            logging.error(msg)
-        if nodes[0].get('unit') is not None:
-            attr['unit'] = nodes[0].get('unit')
-    return value, attr
-
-            
-class Reader:
-    """
-    Class to load cansas 1D XML files
-    
-    :Dependencies:
-        The CanSas reader requires PyXML 0.8.4 or later.
-    """
-    ## CanSAS version
-    version = '1.0'
-    ## File type
-    type_name = "CanSAS 1D"
-    ## Wildcards
-    type = ["CanSAS 1D files (*.xml)|*.xml",
-                        "CanSAS 1D AVE files (*.AVEx)|*.AVEx",
-                         "CanSAS 1D AVE files (*.ABSx)|*.ABSx"]
-
-    ## List of allowed extensions
-    ext = ['.xml', '.XML','.avex', '.AVEx', '.absx', 'ABSx']  
-    
-    def __init__(self):
-        ## List of errors
-        self.errors = []
-    
-    def read(self, path):
-        """ 
-        Load data file
-        
-        :param path: file path
-        
-        :return: Data1D object if a single SASentry was found, 
-                    or a list of Data1D objects if multiple entries were found,
-                    or None of nothing was found
-                    
-        :raise RuntimeError: when the file can't be opened
-        :raise ValueError: when the length of the data vectors are inconsistent
-        """
-        output = []
-        if os.path.isfile(path):
-            basename  = os.path.basename(path)
-            root, extension = os.path.splitext(basename)
-            if extension.lower() in self.ext:
-                
-                tree = etree.parse(path, parser=etree.ETCompatXMLParser())
-                # Check the format version number
-                # Specifying the namespace will take care of the file
-                # format version 
-                root = tree.getroot()
-                
-                entry_list = root.xpath('/ns:SASroot/ns:SASentry',
-                                         namespaces={'ns': CANSAS_NS})
-                
-                for entry in entry_list:
-                    self.errors = []
-                    sas_entry = self._parse_entry(entry)
-                    sas_entry.filename = basename
-                    
-                    # Store loading process information
-                    sas_entry.errors = self.errors
-                    sas_entry.meta_data['loader'] = self.type_name
-                    output.append(sas_entry)
-                
-        else:
-            raise RuntimeError, "%s is not a file" % path
-        # Return output consistent with the loader's api
-        if len(output) == 0:
-            #cannot return none when it cannot read 
-            #return None
-            raise RuntimeError, "%s cannot be read \n" % path
-        elif len(output) == 1:
-            return output[0]
-        else:
-            return output                
-                
-    def _parse_entry(self, dom):
-        """
-        Parse a SASentry
-        
-        :param node: SASentry node
-        
-        :return: Data1D object
-        """
-        x = numpy.zeros(0)
-        y = numpy.zeros(0)
-        
-        data_info = Data1D(x, y)
-        
-        # Look up title      
-        self._store_content('ns:Title', dom, 'title', data_info)
-        
-        # Look up run number   
-        nodes = dom.xpath('ns:Run', namespaces={'ns': CANSAS_NS})
-        for item in nodes:    
-            if item.text is not None:
-                value = item.text.strip()
-                if len(value) > 0:
-                    data_info.run.append(value)
-                    if item.get('name') is not None:
-                        data_info.run_name[value] = item.get('name')
-                           
-        # Look up instrument name              
-        self._store_content('ns:SASinstrument/ns:name', dom, 'instrument',
-                             data_info)
-
-        # Notes
-        note_list = dom.xpath('ns:SASnote', namespaces={'ns': CANSAS_NS})
-        for note in note_list:
-            try:
-                if note.text is not None:
-                    note_value = note.text.strip()
-                    if len(note_value) > 0:
-                        data_info.notes.append(note_value)
-            except:
-                err_mess = "cansas_reader.read: error processing"
-                err_mess += " entry notes\n  %s" % sys.exc_value
-                self.errors.append(err_mess)
-                logging.error(err_mess)
-        
-        # Sample info ###################
-        entry = get_content('ns:SASsample', dom)
-        if entry is not None:
-            data_info.sample.name = entry.get('name')
-            
-        self._store_content('ns:SASsample/ns:ID', 
-                     dom, 'ID', data_info.sample)                    
-        self._store_float('ns:SASsample/ns:thickness', 
-                     dom, 'thickness', data_info.sample)
-        self._store_float('ns:SASsample/ns:transmission', 
-                     dom, 'transmission', data_info.sample)
-        self._store_float('ns:SASsample/ns:temperature', 
-                     dom, 'temperature', data_info.sample)
-        
-        nodes = dom.xpath('ns:SASsample/ns:details', 
-                          namespaces={'ns': CANSAS_NS})
-        for item in nodes:
-            try:
-                if item.text is not None:
-                    detail_value = item.text.strip()
-                    if len(detail_value) > 0:
-                        data_info.sample.details.append(detail_value)
-            except:
-                err_mess = "cansas_reader.read: error processing "
-                err_mess += " sample details\n  %s" % sys.exc_value
-                self.errors.append(err_mess)
-                logging.error(err_mess)
-        
-        # Position (as a vector)
-        self._store_float('ns:SASsample/ns:position/ns:x', 
-                     dom, 'position.x', data_info.sample)          
-        self._store_float('ns:SASsample/ns:position/ns:y', 
-                     dom, 'position.y', data_info.sample)          
-        self._store_float('ns:SASsample/ns:position/ns:z', 
-                     dom, 'position.z', data_info.sample)          
-        
-        # Orientation (as a vector)
-        self._store_float('ns:SASsample/ns:orientation/ns:roll', 
-                     dom, 'orientation.x', data_info.sample)          
-        self._store_float('ns:SASsample/ns:orientation/ns:pitch', 
-                     dom, 'orientation.y', data_info.sample)          
-        self._store_float('ns:SASsample/ns:orientation/ns:yaw', 
-                     dom, 'orientation.z', data_info.sample)          
-       
-        # Source info ###################
-        entry = get_content('ns:SASinstrument/ns:SASsource', dom)
-        if entry is not None:
-            data_info.source.name = entry.get('name')
-        
-        self._store_content('ns:SASinstrument/ns:SASsource/ns:radiation', 
-                     dom, 'radiation', data_info.source)                    
-        self._store_content('ns:SASinstrument/ns:SASsource/ns:beam_shape', 
-                     dom, 'beam_shape', data_info.source)                    
-        self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength', 
-                     dom, 'wavelength', data_info.source)          
-        self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_min', 
-                     dom, 'wavelength_min', data_info.source)          
-        self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_max', 
-                     dom, 'wavelength_max', data_info.source)          
-        self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_spread', 
-                     dom, 'wavelength_spread', data_info.source)    
-        
-        # Beam size (as a vector)   
-        entry = get_content('ns:SASinstrument/ns:SASsource/ns:beam_size', dom)
-        if entry is not None:
-            data_info.source.beam_size_name = entry.get('name')
-            
-        self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:x', 
-                     dom, 'beam_size.x', data_info.source)    
-        self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:y', 
-                     dom, 'beam_size.y', data_info.source)    
-        self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:z', 
-                     dom, 'beam_size.z', data_info.source)    
-        
-        # Collimation info ###################
-        nodes = dom.xpath('ns:SASinstrument/ns:SAScollimation', 
-                          namespaces={'ns': CANSAS_NS})
-        for item in nodes:
-            collim = Collimation()
-            if item.get('name') is not None:
-                collim.name = item.get('name')
-            self._store_float('ns:length', item, 'length', collim)  
-            
-            # Look for apertures
-            apert_list = item.xpath('ns:aperture', namespaces={'ns': CANSAS_NS})
-            for apert in apert_list:
-                aperture =  Aperture()
-                
-                # Get the name and type of the aperture
-                aperture.name = apert.get('name')
-                aperture.type = apert.get('type')
-                    
-                self._store_float('ns:distance', apert, 'distance', aperture)    
-                
-                entry = get_content('ns:size', apert)
-                if entry is not None:
-                    aperture.size_name = entry.get('name')
-                
-                self._store_float('ns:size/ns:x', apert, 'size.x', aperture)    
-                self._store_float('ns:size/ns:y', apert, 'size.y', aperture)    
-                self._store_float('ns:size/ns:z', apert, 'size.z', aperture)
-                
-                collim.aperture.append(aperture)
-                
-            data_info.collimation.append(collim)
-        
-        # Detector info ######################
-        nodes = dom.xpath('ns:SASinstrument/ns:SASdetector',
-                           namespaces={'ns': CANSAS_NS})
-        for item in nodes:
-            
-            detector = Detector()
-            
-            self._store_content('ns:name', item, 'name', detector)
-            self._store_float('ns:SDD', item, 'distance', detector)    
-            
-            # Detector offset (as a vector)
-            self._store_float('ns:offset/ns:x', item, 'offset.x', detector)    
-            self._store_float('ns:offset/ns:y', item, 'offset.y', detector)    
-            self._store_float('ns:offset/ns:z', item, 'offset.z', detector)    
-            
-            # Detector orientation (as a vector)
-            self._store_float('ns:orientation/ns:roll',  item, 'orientation.x',
-                               detector)    
-            self._store_float('ns:orientation/ns:pitch', item, 'orientation.y',
-                               detector)    
-            self._store_float('ns:orientation/ns:yaw',   item, 'orientation.z',
-                               detector)    
-            
-            # Beam center (as a vector)
-            self._store_float('ns:beam_center/ns:x', item, 'beam_center.x',
-                               detector)    
-            self._store_float('ns:beam_center/ns:y', item, 'beam_center.y', 
-                              detector)    
-            self._store_float('ns:beam_center/ns:z', item, 'beam_center.z',
-                               detector)    
-            
-            # Pixel size (as a vector)
-            self._store_float('ns:pixel_size/ns:x', item, 'pixel_size.x',
-                               detector)    
-            self._store_float('ns:pixel_size/ns:y', item, 'pixel_size.y',
-                               detector)    
-            self._store_float('ns:pixel_size/ns:z', item, 'pixel_size.z',
-                               detector)    
-            
-            self._store_float('ns:slit_length', item, 'slit_length', detector)
-            
-            data_info.detector.append(detector)    
-
-        # Processes info ######################
-        nodes = dom.xpath('ns:SASprocess', namespaces={'ns': CANSAS_NS})
-        for item in nodes:
-            process = Process()
-            self._store_content('ns:name', item, 'name', process)
-            self._store_content('ns:date', item, 'date', process)
-            self._store_content('ns:description', item, 'description', process)
-            
-            term_list = item.xpath('ns:term', namespaces={'ns': CANSAS_NS})
-            for term in term_list:
-                try:
-                    term_attr = {}
-                    for attr in term.keys():
-                        term_attr[attr] = term.get(attr).strip()
-                    if term.text is not None:
-                        term_attr['value'] = term.text.strip()
-                        process.term.append(term_attr)
-                except:
-                    err_mess = "cansas_reader.read: error processing "
-                    err_mess += " process term\n  %s" % sys.exc_value
-                    self.errors.append(err_mess)
-                    logging.error(err_mess)
-            
-            note_list = item.xpath('ns:SASprocessnote', 
-                                   namespaces={'ns': CANSAS_NS})
-            for note in note_list:
-                if note.text is not None:
-                    process.notes.append(note.text.strip())
-            
-            data_info.process.append(process)
-            
-            
-        # Data info ######################
-        nodes = dom.xpath('ns:SASdata', namespaces={'ns': CANSAS_NS})
-        if len(nodes) > 1:
-            msg = "CanSAS reader is not compatible with multiple"
-            msg += " SASdata entries"
-            raise RuntimeError, msg
-        
-        nodes = dom.xpath('ns:SASdata/ns:Idata', namespaces={'ns': CANSAS_NS})
-
-        x  = numpy.zeros(0)
-        y  = numpy.zeros(0)
-        dx = numpy.zeros(0)
-        dy = numpy.zeros(0)
-        dxw = numpy.zeros(0)
-        dxl = numpy.zeros(0)
-        
-        for item in nodes:
-            _x, attr = get_float('ns:Q', item)
-            _dx, attr_d = get_float('ns:Qdev', item)
-            _dxl, attr_l = get_float('ns:dQl', item)
-            _dxw, attr_w = get_float('ns:dQw', item)
-            if _dx == None:
-                _dx = 0.0
-            if _dxl == None:
-                _dxl = 0.0
-            if _dxw == None:
-                _dxw = 0.0
-                
-            if attr.has_key('unit') and \
-                attr['unit'].lower() != data_info.x_unit.lower():
-                if has_converter==True:
-                    try:
-                        data_conv_q = Converter(attr['unit'])
-                        _x = data_conv_q(_x, units=data_info.x_unit)
-                    except:
-                        msg =  "CanSAS reader: could not convert "
-                        msg += "Q unit [%s]; " 
-                        msg += "expecting [%s]\n  %s" % (attr['unit'], 
-                                  data_info.x_unit, sys.exc_value)
-                        raise ValueError, msg
-                        
-                else:
-                    msg = "CanSAS reader: unrecognized Q unit [%s]; "
-                    msg += "expecting [%s]" % (attr['unit'], data_info.x_unit)
-                    raise ValueError, msg
-                        
-            # Error in Q
-            if attr_d.has_key('unit') and \
-                attr_d['unit'].lower() != data_info.x_unit.lower():
-                if has_converter==True:
-                    try:
-                        data_conv_q = Converter(attr_d['unit'])
-                        _dx = data_conv_q(_dx, units=data_info.x_unit)
-                    except:
-                        msg = "CanSAS reader: could not convert dQ unit [%s];"
-                        msg += " expecting " 
-                        msg += "[%s]\n  %s" % (attr['unit'],
-                                                data_info.x_unit, sys.exc_value)
-                        raise ValueError, msg
-                        
-                else:
-                    msg = "CanSAS reader: unrecognized dQ unit [%s]; "
-                    msg += "expecting [%s]" % (attr['unit'], data_info.x_unit)
-                    raise ValueError,  msg
-                        
-            # Slit length
-            if attr_l.has_key('unit') and \
-                attr_l['unit'].lower() != data_info.x_unit.lower():
-                if has_converter == True:
-                    try:
-                        data_conv_q = Converter(attr_l['unit'])
-                        _dxl = data_conv_q(_dxl, units=data_info.x_unit)
-                    except:
-                        msg = "CanSAS reader: could not convert dQl unit [%s];"
-                        msg += " expecting [%s]\n  %s" % (attr['unit'],
-                                             data_info.x_unit, sys.exc_value)
-                        raise ValueError, msg
-                        
-                else:
-                    msg = "CanSAS reader: unrecognized dQl unit [%s];"
-                    msg += " expecting [%s]" % (attr['unit'], data_info.x_unit)
-                    raise ValueError, msg
-                        
-            # Slit width
-            if attr_w.has_key('unit') and \
-            attr_w['unit'].lower() != data_info.x_unit.lower():
-                if has_converter == True:
-                    try:
-                        data_conv_q = Converter(attr_w['unit'])
-                        _dxw = data_conv_q(_dxw, units=data_info.x_unit)
-                    except:
-                        msg = "CanSAS reader: could not convert dQw unit [%s];"
-                        msg += " expecting [%s]\n  %s" % (attr['unit'], 
-                                                data_info.x_unit, sys.exc_value)
-                        raise ValueError, msg
-                        
-                else:
-                    msg = "CanSAS reader: unrecognized dQw unit [%s];"
-                    msg += " expecting [%s]" % (attr['unit'], data_info.x_unit)
-                    raise ValueError, msg   
-            _y, attr = get_float('ns:I', item)
-            _dy, attr_d = get_float('ns:Idev', item)
-            if _dy == None:
-                _dy = 0.0
-            if attr.has_key('unit') and \
-            attr['unit'].lower() != data_info.y_unit.lower():
-                if has_converter==True:
-                    try:
-                        data_conv_i = Converter(attr['unit'])
-                        _y = data_conv_i(_y, units=data_info.y_unit)
-                    except:
-                        if attr['unit'].lower() == 'count':
-                            pass
-                        else:
-                            msg = "CanSAS reader: could not"
-                            msg += " convert I(q) unit [%s];" % str(attr['unit'])
-                            msg += " expecting [%s]\n" % str(data_info.y_unit)
-                            msg += "  %s" % str(sys.exc_value)
-                            raise ValueError, msg
-                else:
-                    msg = "CanSAS reader: unrecognized I(q) unit [%s];"
-                    msg += " expecting [%s]" % (attr['unit'], data_info.y_unit)
-                    raise ValueError, msg 
-                        
-            if attr_d.has_key('unit') and \
-            attr_d['unit'].lower() != data_info.y_unit.lower():
-                if has_converter==True:
-                    try:
-                        data_conv_i = Converter(attr_d['unit'])
-                        _dy = data_conv_i(_dy, units=data_info.y_unit)
-                    except:
-                        if attr_d['unit'].lower() == 'count':
-                            pass 
-                        else:
-                            msg = "CanSAS reader: could not convert dI(q) unit "
-                            msg += "[%s]; expecting [%s]\n  %s"  % (attr_d['unit'],
-                                                 data_info.y_unit, sys.exc_value)
-                            raise ValueError, msg
-                else:
-                    msg = "CanSAS reader: unrecognized dI(q) unit [%s]; "
-                    msg += "expecting [%s]" % (attr_d['unit'], data_info.y_unit)
-                    raise ValueError, msg
-                
-            if _x is not None and _y is not None:
-                x  = numpy.append(x, _x)
-                y  = numpy.append(y, _y)
-                dx = numpy.append(dx, _dx)
-                dy = numpy.append(dy, _dy)
-                dxl = numpy.append(dxl, _dxl)
-                dxw = numpy.append(dxw, _dxw)
-        # Zeros in dx, dy 
-        if not numpy.all(dx==0):
-            dx[dx==0] = _ZERO
-        if not numpy.all(dy==0):
-            dy[dy==0] = _ZERO
-       
-        data_info.x = x[x!=0]
-        data_info.y = y[x!=0]
-        data_info.dx = dx[x!=0]
-        
-        data_info.dy = dy[x!=0]
-        data_info.dxl = dxl[x!=0]
-        data_info.dxw = dxw[x!=0]
-        
-        data_conv_q = None
-        data_conv_i = None
-        
-        if has_converter == True and data_info.x_unit != '1/A':
-            data_conv_q = Converter('1/A')
-            # Test it
-            data_conv_q(1.0, output.Q_unit)
-            
-        if has_converter == True and data_info.y_unit != '1/cm':
-            data_conv_i = Converter('1/cm')
-            # Test it
-            data_conv_i(1.0, output.I_unit)                    
-                
-        if data_conv_q is not None:
-            data_info.xaxis("\\rm{Q}", data_info.x_unit)
-        else:
-            data_info.xaxis("\\rm{Q}", 'A^{-1}')
-        if data_conv_i is not None:
-            data_info.yaxis("\\rm{Intensity}", data_info.y_unit)
-        else:
-            data_info.yaxis("\\rm{Intensity}","cm^{-1}")
-
-        return data_info
-
-    def _to_xml_doc(self, datainfo):
-        """
-        Create an XML document to contain the content of a Data1D
-        
-        :param datainfo: Data1D object
-        """
-        
-        if not issubclass(datainfo.__class__, Data1D):
-            raise RuntimeError, "The cansas writer expects a Data1D instance"
-        
-        doc = xml.dom.minidom.Document()
-        main_node = doc.createElement("SASroot")
-        main_node.setAttribute("version", self.version)
-        main_node.setAttribute("xmlns", "cansas1d/%s" % self.version)
-        main_node.setAttribute("xmlns:xsi",
-                               "http://www.w3.org/2001/XMLSchema-instance")
-        main_node.setAttribute("xsi:schemaLocation",
-                               "cansas1d/%s http://svn.smallangles.net/svn/canSAS/1dwg/trunk/cansas1d.xsd" % self.version)
-        
-        doc.appendChild(main_node)
-        
-        entry_node = doc.createElement("SASentry")
-        main_node.appendChild(entry_node)
-        
-        write_node(doc, entry_node, "Title", datainfo.title)
-        for item in datainfo.run:
-            runname = {}
-            if datainfo.run_name.has_key(item) and \
-            len(str(datainfo.run_name[item]))>1:
-                runname = {'name': datainfo.run_name[item] }
-            write_node(doc, entry_node, "Run", item, runname)
-        
-        # Data info
-        node = doc.createElement("SASdata")
-        entry_node.appendChild(node)
-        
-        for i in range(len(datainfo.x)):
-            pt = doc.createElement("Idata")
-            node.appendChild(pt)
-            write_node(doc, pt, "Q", datainfo.x[i], {'unit':datainfo.x_unit})
-            if len(datainfo.y)>=i:
-                write_node(doc, pt, "I", datainfo.y[i],
-                            {'unit':datainfo.y_unit})
-            if datainfo.dx != None and len(datainfo.dx) >= i:
-                write_node(doc, pt, "Qdev", datainfo.dx[i],
-                            {'unit':datainfo.x_unit})
-            if datainfo.dxl != None and len(datainfo.dxl) >= i:
-                write_node(doc, pt, "dQl", datainfo.dxl[i],
-                            {'unit':datainfo.x_unit})    
-            if datainfo.dxw != None and len(datainfo.dxw) >= i:
-                write_node(doc, pt, "dQw", datainfo.dxw[i],
-                            {'unit':datainfo.x_unit})              
-            if datainfo.dy != None and len(datainfo.dy) >= i:
-                write_node(doc, pt, "Idev", datainfo.dy[i],
-                            {'unit':datainfo.y_unit})
-
-        
-        # Sample info
-        sample = doc.createElement("SASsample")
-        if datainfo.sample.name is not None:
-            sample.setAttribute("name", str(datainfo.sample.name))
-        entry_node.appendChild(sample)
-        write_node(doc, sample, "ID", str(datainfo.sample.ID))
-        write_node(doc, sample, "thickness", datainfo.sample.thickness,
-                   {"unit":datainfo.sample.thickness_unit})
-        write_node(doc, sample, "transmission", datainfo.sample.transmission)
-        write_node(doc, sample, "temperature", datainfo.sample.temperature,
-                   {"unit":datainfo.sample.temperature_unit})
-        
-        for item in datainfo.sample.details:
-            write_node(doc, sample, "details", item)
-        
-        pos = doc.createElement("position")
-        written = write_node(doc, pos, "x", datainfo.sample.position.x,
-                             {"unit":datainfo.sample.position_unit})
-        written = written | write_node(doc, pos, "y",
-                                       datainfo.sample.position.y,
-                                       {"unit":datainfo.sample.position_unit})
-        written = written | write_node(doc, pos, "z",
-                                       datainfo.sample.position.z,
-                                       {"unit":datainfo.sample.position_unit})
-        if written == True:
-            sample.appendChild(pos)
-        
-        ori = doc.createElement("orientation")
-        written = write_node(doc, ori, "roll",
-                             datainfo.sample.orientation.x,
-                             {"unit":datainfo.sample.orientation_unit})
-        written = written | write_node(doc, ori, "pitch",
-                                       datainfo.sample.orientation.y,
-                                    {"unit":datainfo.sample.orientation_unit})
-        written = written | write_node(doc, ori, "yaw",
-                                       datainfo.sample.orientation.z,
-                                    {"unit":datainfo.sample.orientation_unit})
-        if written == True:
-            sample.appendChild(ori)
-        
-        # Instrument info
-        instr = doc.createElement("SASinstrument")
-        entry_node.appendChild(instr)
-        
-        write_node(doc, instr, "name", datainfo.instrument)
-        
-        #   Source
-        source = doc.createElement("SASsource")
-        if datainfo.source.name is not None:
-            source.setAttribute("name", str(datainfo.source.name))
-        instr.appendChild(source)
-        
-        write_node(doc, source, "radiation", datainfo.source.radiation)
-        write_node(doc, source, "beam_shape", datainfo.source.beam_shape)
-        size = doc.createElement("beam_size")
-        if datainfo.source.beam_size_name is not None:
-            size.setAttribute("name", str(datainfo.source.beam_size_name))
-        written = write_node(doc, size, "x", datainfo.source.beam_size.x,
-                             {"unit":datainfo.source.beam_size_unit})
-        written = written | write_node(doc, size, "y",
-                                       datainfo.source.beam_size.y,
-                                       {"unit":datainfo.source.beam_size_unit})
-        written = written | write_node(doc, size, "z",
-                                       datainfo.source.beam_size.z,
-                                       {"unit":datainfo.source.beam_size_unit})
-        if written == True:
-            source.appendChild(size)
-            
-        write_node(doc, source, "wavelength",
-                   datainfo.source.wavelength,
-                   {"unit":datainfo.source.wavelength_unit})
-        write_node(doc, source, "wavelength_min",
-                   datainfo.source.wavelength_min,
-                   {"unit":datainfo.source.wavelength_min_unit})
-        write_node(doc, source, "wavelength_max",
-                   datainfo.source.wavelength_max,
-                   {"unit":datainfo.source.wavelength_max_unit})
-        write_node(doc, source, "wavelength_spread",
-                   datainfo.source.wavelength_spread,
-                   {"unit":datainfo.source.wavelength_spread_unit})
-        
-        #   Collimation
-        for item in datainfo.collimation:
-            coll = doc.createElement("SAScollimation")
-            if item.name is not None:
-                coll.setAttribute("name", str(item.name))
-            instr.appendChild(coll)
-            
-            write_node(doc, coll, "length", item.length,
-                       {"unit":item.length_unit})
-            
-            for apert in item.aperture:
-                ap = doc.createElement("aperture")
-                if apert.name is not None:
-                    ap.setAttribute("name", str(apert.name))
-                if apert.type is not None:
-                    ap.setAttribute("type", str(apert.type))
-                coll.appendChild(ap)
-                
-                write_node(doc, ap, "distance", apert.distance,
-                           {"unit":apert.distance_unit})
-                
-                size = doc.createElement("size")
-                if apert.size_name is not None:
-                    size.setAttribute("name", str(apert.size_name))
-                written = write_node(doc, size, "x", apert.size.x,
-                                     {"unit":apert.size_unit})
-                written = written | write_node(doc, size, "y", apert.size.y,
-                                               {"unit":apert.size_unit})
-                written = written | write_node(doc, size, "z", apert.size.z,
-                                               {"unit":apert.size_unit})
-                if written == True:
-                    ap.appendChild(size)
-
-        #   Detectors
-        for item in datainfo.detector:
-            det = doc.createElement("SASdetector")
-            written = write_node(doc, det, "name", item.name)
-            written = written | write_node(doc, det, "SDD", item.distance,
-                                           {"unit":item.distance_unit})
-            written = written | write_node(doc, det, "slit_length",
-                                           item.slit_length,
-                                           {"unit":item.slit_length_unit})
-            if written == True:
-                instr.appendChild(det)
-            
-            off = doc.createElement("offset")
-            written = write_node(doc, off, "x", item.offset.x,
-                                 {"unit":item.offset_unit})
-            written = written | write_node(doc, off, "y", item.offset.y,
-                                           {"unit":item.offset_unit})
-            written = written | write_node(doc, off, "z", item.offset.z,
-                                           {"unit":item.offset_unit})
-            if written == True:
-                det.appendChild(off)
-            
-            center = doc.createElement("beam_center")
-            written = write_node(doc, center, "x", item.beam_center.x,
-                                 {"unit":item.beam_center_unit})
-            written = written | write_node(doc, center, "y",
-                                           item.beam_center.y,
-                                           {"unit":item.beam_center_unit})
-            written = written | write_node(doc, center, "z",
-                                           item.beam_center.z,
-                                           {"unit":item.beam_center_unit})
-            if written == True:
-                det.appendChild(center)
-                
-            pix = doc.createElement("pixel_size")
-            written = write_node(doc, pix, "x", item.pixel_size.x,
-                                 {"unit":item.pixel_size_unit})
-            written = written | write_node(doc, pix, "y", item.pixel_size.y,
-                                           {"unit":item.pixel_size_unit})
-            written = written | write_node(doc, pix, "z", item.pixel_size.z,
-                                           {"unit":item.pixel_size_unit})
-            if written == True:
-                det.appendChild(pix)
-                
-            ori = doc.createElement("orientation")
-            written = write_node(doc, ori, "roll",  item.orientation.x,
-                                 {"unit":item.orientation_unit})
-            written = written | write_node(doc, ori, "pitch",
-                                           item.orientation.y,
-                                           {"unit":item.orientation_unit})
-            written = written | write_node(doc, ori, "yaw",
-                                           item.orientation.z,
-                                           {"unit":item.orientation_unit})
-            if written == True:
-                det.appendChild(ori)
-                
-        
-        # Processes info
-        for item in datainfo.process:
-            node = doc.createElement("SASprocess")
-            entry_node.appendChild(node)
-
-            write_node(doc, node, "name", item.name)
-            write_node(doc, node, "date", item.date)
-            write_node(doc, node, "description", item.description)
-            for term in item.term:
-                value = term['value']
-                del term['value']
-                write_node(doc, node, "term", value, term)
-            for note in item.notes:
-                write_node(doc, node, "SASprocessnote", note)
-        
-        # Return the document, and the SASentry node associated with
-        # the data we just wrote
-        return doc, entry_node
-            
-    def write(self, filename, datainfo):
-        """
-        Write the content of a Data1D as a CanSAS XML file
-        
-        :param filename: name of the file to write
-        :param datainfo: Data1D object
-        """
-        # Create XML document
-        doc, sasentry = self._to_xml_doc(datainfo)
-        # Write the file
-        fd = open(filename, 'w')
-        fd.write(doc.toprettyxml())
-        fd.close()
-        
-    def _store_float(self, location, node, variable, storage, optional=True):
-        """
-        Get the content of a xpath location and store
-        the result. Check that the units are compatible
-        with the destination. The value is expected to
-        be a float.
-        
-        The xpath location might or might not exist.
-        If it does not exist, nothing is done
-        
-        :param location: xpath location to fetch
-        :param node: node to read the data from
-        :param variable: name of the data member to store it in [string]
-        :param storage: data object that has the 'variable' data member
-        :param optional: if True, no exception will be raised 
-            if unit conversion can't be done
-
-        :raise ValueError: raised when the units are not recognized
-        """
-        entry = get_content(location, node)
-        try:
-            value = float(entry.text)
-        except:
-            value = None
-            
-        if value is not None:
-            # If the entry has units, check to see that they are
-            # compatible with what we currently have in the data object
-            units = entry.get('unit')
-            if units is not None:
-                toks = variable.split('.')
-                exec "local_unit = storage.%s_unit" % toks[0]
-                if units.lower()!=local_unit.lower():
-                    if has_converter==True:
-                        try:
-                            conv = Converter(units)
-                            exec "storage.%s = %g" % (variable,
-                                            conv(value, units=local_unit))
-                        except:
-                            err_mess = "CanSAS reader: could not convert"
-                            err_mess += " %s unit [%s]; expecting [%s]\n  %s" \
-                                % (variable, units, local_unit, sys.exc_value)
-                            self.errors.append(err_mess)
-                            if optional:
-                                logging.info(err_mess)
-                            else:
-                                raise ValueError, err_mess 
-                    else:
-                        err_mess = "CanSAS reader: unrecognized %s unit [%s];"
-                        err_mess += " expecting [%s]" % (variable, 
-                                                         units, local_unit)
-                        self.errors.append(err_mess)
-                        if optional:
-                            logging.info(err_mess)
-                        else:
-                            raise ValueError, err_mess
-                else:
-                    exec "storage.%s = value" % variable
-            else:
-                exec "storage.%s = value" % variable
-                
-    def _store_content(self, location, node, variable, storage):
-        """
-        Get the content of a xpath location and store
-        the result. The value is treated as a string.
-        
-        The xpath location might or might not exist.
-        If it does not exist, nothing is done
-        
-        :param location: xpath location to fetch
-        :param node: node to read the data from
-        :param variable: name of the data member to store it in [string]
-        :param storage: data object that has the 'variable' data member
-        
-        :return: return a list of errors
-        """
-        entry = get_content(location, node)
-        if entry is not None and entry.text is not None:
-            exec "storage.%s = entry.text.strip()" % variable
-
-            
-            
-if __name__ == "__main__": 
-    logging.basicConfig(level=logging.ERROR,
-                        format='%(asctime)s %(levelname)s %(message)s',
-                        filename='cansas_reader.log',
-                        filemode='w')
-    reader = Reader()
-    print reader.read("../test/cansas1d.xml")
-    #print reader.read("../test/latex_smeared.xml")
-    
-    
-                        
Index: nsdataloader/readers/danse_reader.py
===================================================================
--- sansdataloader/readers/danse_reader.py	(revision aab4e1501beed9965c9e6c08d09fcd8e34a20adb)
+++ 	(revision )
@@ -1,292 +1,0 @@
-
-
-############################################################################
-#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
-#############################################################################
-
-"""
-    DANSE/SANS file reader
-"""
-
-import math
-import os
-#import copy
-import numpy
-import logging
-from DataLoader.data_info import Data2D, Detector
-from DataLoader.manipulations import reader2D_converter
-
-# Look for unit converter
-has_converter = True
-try:
-    from data_util.nxsunit import Converter
-except:
-    has_converter = False
-
-class Reader:
-    """
-    Example data manipulation
-    """
-    ## File type
-    type_name = "DANSE"   
-    ## Wildcards
-    type = ["DANSE files (*.sans)|*.sans"]
-    ## Extension
-    ext  = ['.sans', '.SANS']    
-        
-    def read(self, filename=None):
-        """
-        Open and read the data in a file
-        @param file: path of the file
-        """
-        
-        read_it = False
-        for item in self.ext:
-            if filename.lower().find(item) >= 0:
-                read_it = True
-                
-        if read_it:
-            try:
-                datafile = open(filename, 'r')
-            except :
-                raise  RuntimeError,"danse_reader cannot open %s" % (filename)
-        
-            # defaults
-            # wavelength in Angstrom
-            wavelength = 10.0
-            # Distance in meter
-            distance   = 11.0
-            # Pixel number of center in x
-            center_x   = 65
-            # Pixel number of center in y
-            center_y   = 65
-            # Pixel size [mm]
-            pixel      = 5.0
-            # Size in x, in pixels
-            size_x     = 128
-            # Size in y, in pixels
-            size_y     = 128
-            # Format version
-            fversion   = 1.0
-            
-            output = Data2D()
-            output.filename = os.path.basename(filename)
-            detector = Detector()
-            output.detector.append(detector)
-            
-            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)            
-        
-            read_on = True
-            while read_on:
-                line = datafile.readline()
-                if line.find("DATA:") >= 0:
-                    read_on = False
-                    break
-                toks = line.split(':')
-                if toks[0] == "FORMATVERSION":
-                    fversion = float(toks[1])
-                if toks[0] == "WAVELENGTH":    
-                    wavelength = float(toks[1])                
-                elif toks[0] == "DISTANCE":
-                    distance = float(toks[1])
-                elif toks[0] == "CENTER_X":
-                    center_x = float(toks[1])
-                elif toks[0] == "CENTER_Y":
-                    center_y = float(toks[1])
-                elif toks[0] == "PIXELSIZE":
-                    pixel = float(toks[1])
-                elif toks[0] == "SIZE_X":
-                    size_x = int(toks[1])
-                elif toks[0] == "SIZE_Y":
-                    size_y = int(toks[1])
-            
-            # Read the data
-            data = []
-            error = []
-            if fversion == 1.0:
-                data_str = datafile.readline()
-                data = data_str.split(' ')
-            else:
-                read_on = True
-                while read_on:
-                    data_str = datafile.readline()
-                    if len(data_str) == 0:
-                        read_on = False
-                    else:
-                        toks = data_str.split()
-                        try:
-                            val = float(toks[0])
-                            err = float(toks[1])
-                            if data_conv_i is not None:
-                                val = data_conv_i(val, units=output.y_unit)
-                                err = data_conv_i(err, units=output.y_unit)
-                            data.append(val)
-                            error.append(err)
-                        except:
-                            logging.info("Skipping line:%s,%s" %( data_str,
-                                                                sys.exc_value))
-            
-            # Initialize 
-            x_vals = []
-            y_vals = [] 
-            ymin = None
-            ymax = None
-            xmin = None
-            xmax = None
-            
-            # Qx and Qy vectors
-            theta = pixel / distance / 100.0
-            stepq = 4.0 * math.pi/wavelength * math.sin(theta/2.0) 
-            for i_x in range(size_x):
-                theta = (i_x - center_x + 1) * pixel / 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)
-                
-                x_vals.append(qx)
-                if xmin == None or qx < xmin:
-                    xmin = qx
-                if xmax == None or qx > xmax:
-                    xmax = qx
-            
-            ymin = None
-            ymax = None
-            for i_y in range(size_y):
-                theta = (i_y - center_y + 1) * pixel / 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)
-                
-                y_vals.append(qy)
-                if ymin == None or qy < ymin:
-                    ymin = qy
-                if ymax == None or qy > ymax:
-                    ymax = qy
-            
-            # Store the data in the 2D array
-            itot = 0
-            i_x  = 0
-            i_y  = -1
-            
-            for i_pt in range(len(data)):
-                try:
-                    value = float(data[i_pt])
-                except:
-                    # For version 1.0, the data were still
-                    # stored as strings at this point.
-                    msg = "Skipping entry (v1.0):%s,%s" %(str(data[i_pt]),
-                                                           sys.exc_value)
-                    logging.info(msg)
-                
-                # Get bin number
-                if math.fmod(i_pt, size_x) == 0:
-                    i_x = 0
-                    i_y += 1
-                else:
-                    i_x += 1
-                    
-                output.data[i_y][i_x] = value       
-                #output.data[size_y-1-i_y][i_x] = value
-                if fversion>1.0:
-                    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 
-            # 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 pixel size
-            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 - stepq / 2.0
-            xmax = xmax + stepq / 2.0
-            ymin = ymin - stepq  /2.0
-            ymax = ymax + stepq / 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_vals
-            output.y_bins     = y_vals
-           
-            # Units
-            if data_conv_q is not None:
-                output.xaxis("\\rm{Q_{x}}", output.Q_unit)
-                output.yaxis("\\rm{Q_{y}}", output.Q_unit)
-            else:
-                output.xaxis("\\rm{Q_{x}}", 'A^{-1}')
-                output.yaxis("\\rm{Q_{y}}", 'A^{-1}')
-                
-            if data_conv_i is not None:
-                output.zaxis("\\rm{Intensity}", output.I_unit)
-            else:
-                output.zaxis("\\rm{Intensity}","cm^{-1}")
-           
-            if not fversion >= 1.0:
-                msg = "Danse_reader can't read this file %s" % filename
-                raise ValueError, msg
-            else:
-                logging.info("Danse_reader Reading %s \n" % filename)
-            
-            # Store loading process information
-            output.meta_data['loader'] = self.type_name    
-            output = reader2D_converter(output)
-            return output
-        
-        return None
-
-if __name__ == "__main__": 
-    reader = Reader()
-    print reader.read("../test/MP_New.sans")
-    
Index: nsdataloader/readers/defaults.xml
===================================================================
--- sansdataloader/readers/defaults.xml	(revision aab4e1501beed9965c9e6c08d09fcd8e34a20adb)
+++ 	(revision )
@@ -1,15 +1,0 @@
-<?xml version="1.0"?>
-<SansLoader version="1.0"
-    xmlns="sansloader/1.0"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    >
-	
-	<FileType extension='.xml' reader='cansas_reader'/>
-	<FileType extension='.asc' reader='IgorReader'/>
-	<FileType extension='.dat' reader='red2d_reader'/>
-	<FileType extension='.tif' reader='tiff_reader'/>
-	<FileType extension='.tiff' reader='tiff_reader'/>
-	<FileType extension='.sans' reader='danse_reader'/>
-    
-</SansLoader>
-
Index: nsdataloader/readers/hfir1d_reader.py
===================================================================
--- sansdataloader/readers/hfir1d_reader.py	(revision aab4e1501beed9965c9e6c08d09fcd8e34a20adb)
+++ 	(revision )
@@ -1,136 +1,0 @@
-
-#####################################################################
-#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. 
-#See the license text in license.txt
-#copyright 2008, University of Tennessee
-######################################################################
-
-import numpy
-import os
-from DataLoader.data_info import Data1D
-
-# Check whether we have a converter available
-has_converter = True
-try:
-    from data_util.nxsunit import Converter
-except:
-    has_converter = False
-
-class Reader(object):
-    """
-    Class to load HFIR 1D 4-column files
-    """
-    ## File type
-    type_name = "HFIR 1D"   
-    ## Wildcards
-    type = ["HFIR 1D files (*.d1d)|*.d1d"]
-    ## List of allowed extensions
-    ext = ['.d1d']  
-    
-    def read(self, path):
-        """ 
-        Load data file
-        
-        :param path: file path
-        
-        :return: Data1D object, or None
-        
-        :raise RuntimeError: when the file can't be opened
-        :raise ValueError: when the length of the data vectors are inconsistent
-        """
-        if os.path.isfile(path):
-            basename  = os.path.basename(path)
-            root, extension = os.path.splitext(basename)
-            if extension.lower() in self.ext:
-                try:
-                    input_f =  open(path,'r')
-                except :
-                    raise  RuntimeError, "hfir1d_reader: cannot open %s" % path
-                buff = input_f.read()
-                lines = buff.split('\n')
-                x  = numpy.zeros(0)
-                y  = numpy.zeros(0)
-                dx = numpy.zeros(0)
-                dy = numpy.zeros(0)
-                output = Data1D(x, y, dx=dx, dy=dy)
-                self.filename = output.filename = basename
-           
-                data_conv_q = None
-                data_conv_i = None
-                
-                if has_converter == True and output.x_unit != '1/A':
-                    data_conv_q = Converter('1/A')
-                    # Test it
-                    data_conv_q(1.0, output.x_unit)
-                    
-                if has_converter == True and output.y_unit != '1/cm':
-                    data_conv_i = Converter('1/cm')
-                    # Test it
-                    data_conv_i(1.0, output.y_unit)
-                           
-                for line in lines:
-                    toks = line.split()
-                    try:
-                        _x = float(toks[0])
-                        _y = float(toks[1])
-                        _dx = float(toks[3])
-                        _dy = float(toks[2])
-                        
-                        if data_conv_q is not None:
-                            _x = data_conv_q(_x, units=output.x_unit)
-                            _dx = data_conv_q(_dx, units=output.x_unit)
-                            
-                        if data_conv_i is not None:
-                            _y = data_conv_i(_y, units=output.y_unit)                        
-                            _dy = data_conv_i(_dy, units=output.y_unit)                        
-                                                    
-                        x   = numpy.append(x, _x) 
-                        y   = numpy.append(y, _y)
-                        dx  = numpy.append(dx, _dx)
-                        dy  = numpy.append(dy, _dy)                        
-                    except:
-                        # Couldn't parse this line, skip it 
-                        pass
-                         
-                     
-                # Sanity check
-                if not len(y) == len(dy):
-                    msg = "hfir1d_reader: y and dy have different length"
-                    raise RuntimeError, msg
-                if not len(x) == len(dx):
-                    msg = "hfir1d_reader: x and dx have different length"
-                    raise RuntimeError, msg
-
-                # If the data length is zero, consider this as
-                # though we were not able to read the file.
-                if len(x) == 0:
-                    raise RuntimeError, "hfir1d_reader: could not load file"
-               
-                output.x = x
-                output.y = y
-                output.dy = dy
-                output.dx = dx
-                if data_conv_q is not None:
-                    output.xaxis("\\rm{Q}", output.x_unit)
-                else:
-                    output.xaxis("\\rm{Q}", 'A^{-1}')
-                if data_conv_i is not None:
-                    output.yaxis("\\rm{Intensity}", output.y_unit)
-                else:
-                    output.yaxis("\\rm{Intensity}","cm^{-1}")
-                
-                # Store loading process information
-                output.meta_data['loader'] = self.type_name   
-                return output
-        else:
-            raise RuntimeError, "%s is not a file" % path
-        return None
-    
-if __name__ == "__main__": 
-    reader = Reader()
-    print reader.read("../test/S2-30dq.d1d")
-    
-    
-                        
Index: nsdataloader/readers/red2d_reader.py
===================================================================
--- sansdataloader/readers/red2d_reader.py	(revision aab4e1501beed9965c9e6c08d09fcd8e34a20adb)
+++ 	(revision )
@@ -1,379 +1,0 @@
-
-#####################################################################
-#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. 
-#See the license text in license.txt
-#copyright 2008, University of Tennessee
-######################################################################
-
-"""
-    TXT/IGOR 2D Q Map file reader
-"""
-
-
-import os
-#import sys
-import numpy
-import math
-#import 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
-    
-def check_point(x_point):
-    """
-    check point validity
-    """
-    # set zero for non_floats
-    try:
-        return float(x_point)
-    except:
-        return 0
-        
-class Reader:
-    """ Simple data reader for Igor data files """
-    ## File type
-    type_name = "IGOR/DAT 2D Q_map"   
-    ## Wildcards
-    type = ["IGOR/DAT 2D file in Q_map (*.dat)|*.DAT"]
-    ## Extension
-    ext=['.DAT', '.dat']
-    
-    def write(self, filename, data):
-        """
-        Write to .dat
-        
-        :param filename: file name to write
-        :param data: data2D 
-        """
-        import time
-        st = time.time()
-        # Write the file
-        fd = open(filename, 'w')
-        t = time.localtime()
-        time_str = time.strftime("%H:%M on %b %d %y", t)
-        
-        header_str = "Data columns are Qx - Qy - I(Qx,Qy)\n\nASCII data"
-        header_str += " created at %s \n\n" % time_str
-        # simple 2D header
-        fd.write(header_str)
-        # write qx qy I values
-        for i in range(len(data.data)):
-            fd.write("%g  %g  %g\n" % (data.qx_data[i], 
-                                        data.qy_data[i],
-                                       data.data[i]))
-        # close
-        fd.close()                 
-
-    def read(self,filename=None):
-        """ Read file """
-        if not os.path.isfile(filename):
-            raise ValueError, \
-            "Specified file %s is not a regular file" % filename
-
-        # Read file
-        f = open(filename,'r')
-        buf = f.read()
-        f.close()     
-        # 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)
-                
-        # Get content
-        dataStarted = False
-        
-        ## Defaults      
-        lines = buf.split('\n')
-        itot = 0
-        x = []
-        y = []
-        
-        ncounts = 0
-        
-        wavelength   = None
-        distance     = None
-        transmission = None
-        
-        pixel_x = None
-        pixel_y = None
-        
-        i_x    = 0
-        i_y    = -1
-        pixels = 0
-        
-        isInfo   = False
-        isCenter = False
-
-        data_conv_q = None
-        data_conv_i = None
-        
-        # Set units: This is the unit assumed for Q and I in the data file.
-        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)            
-        
-              
-        # Remove the last lines before the for loop if the lines are empty
-        # to calculate the exact number of data points
-        count = 0
-        while (len(lines[len(lines)-(count+1)].lstrip().rstrip()) < 1):
-            del lines[len(lines)-(count+1)]
-            count = count + 1
-
-        #Read Header and find the dimensions of 2D data
-        line_num = 0
-        # Old version NIST files: 0
-        ver = 0
-        for line in lines:      
-            line_num += 1
-            ## Reading the header applies only to IGOR/NIST 2D q_map data files
-            # Find setup info line
-            if isInfo:
-                isInfo = False
-                line_toks = line.split()
-                # Wavelength in Angstrom
-                try:
-                    wavelength = float(line_toks[1])
-                    # Units
-                    if has_converter == True and \
-                    output.source.wavelength_unit != 'A':
-                        conv = Converter('A')
-                        wavelength = conv(wavelength,
-                                          units=output.source.wavelength_unit)
-                except:
-                    #Not required
-                    pass
-                # Distance in mm
-                try:
-                    distance = float(line_toks[3])
-                    # Units
-                    if has_converter == True and detector.distance_unit != 'm':
-                        conv = Converter('m')
-                        distance = conv(distance, units=detector.distance_unit)
-                except:
-                    #Not required
-                    pass
-                
-                # Distance in meters
-                try:
-                    transmission = float(line_toks[4])
-                except:
-                    #Not required
-                    pass
-                                            
-            if line.count("LAMBDA") > 0:
-                isInfo = True
-                
-            # Find center info line
-            if isCenter:
-                isCenter = False                
-                line_toks = line.split()
-                # Center in bin number
-                center_x = float(line_toks[0])
-                center_y = float(line_toks[1])
-
-            if line.count("BCENT") > 0:
-                isCenter = True
-            # Check version
-            if line.count("Data columns") > 0:
-                if line.count("err(I)") > 0:
-                    ver = 1
-            # Find data start
-            if line.count("ASCII data") > 0:
-                dataStarted = True
-                continue
-
-            ## Read and get data.   
-            if dataStarted == True:
-                line_toks = line.split()              
-                if len(line_toks) == 0:
-                    #empty line
-                    continue
-                # the number of columns must be stayed same 
-                col_num = len(line_toks)
-                break
-        # Make numpy array to remove header lines using index
-        lines_array = numpy.array(lines)
-
-        # index for lines_array
-        lines_index = numpy.arange(len(lines))
-        
-        # get the data lines
-        data_lines = lines_array[lines_index >= (line_num - 1)]
-        # Now we get the total number of rows (i.e., # of data points)
-        row_num = len(data_lines)
-        # make it as list again to control the separators
-        data_list = " ".join(data_lines.tolist())
-        # split all data to one big list w/" "separator
-        data_list = data_list.split()
- 
-        # Check if the size is consistent with data, otherwise 
-        #try the tab(\t) separator
-        # (this may be removed once get the confidence 
-        #the former working all cases).
-        if len(data_list) != (len(data_lines)) * col_num:
-            data_list = "\t".join(data_lines.tolist())
-            data_list = data_list.split()
-
-        # Change it(string) into float
-        #data_list = map(float,data_list)
-        data_list1 = map(check_point,data_list)
-
-        # numpy array form
-        data_array = numpy.array(data_list1)
-        # Redimesion based on the row_num and col_num, 
-        #otherwise raise an error.
-        try:
-            data_point = data_array.reshape(row_num, col_num).transpose()
-        except:
-            msg = "red2d_reader: Can't read this file: Not a proper file format"
-            raise ValueError, msg
-        ## Get the all data: Let's HARDcoding; Todo find better way
-        # Defaults
-        dqx_data = numpy.zeros(0)
-        dqy_data = numpy.zeros(0)
-        err_data = numpy.ones(row_num)
-        qz_data = numpy.zeros(row_num)
-        mask = numpy.ones(row_num,dtype=bool)
-        # Get from the array
-        qx_data = data_point[0]
-        qy_data = data_point[1]
-        data = data_point[2]
-        if ver == 1:
-            if col_num > (2 + ver): err_data = data_point[(2 + ver)]
-        if col_num > (3 + ver): qz_data = data_point[(3 + ver)]
-        if col_num > (4 + ver): dqx_data = data_point[(4 + ver)]
-        if col_num > (5 + ver): dqy_data = data_point[(5 + ver)]
-        #if col_num > (6 + ver): mask[data_point[(6 + ver)] < 1] = False
-        q_data = numpy.sqrt(qx_data*qx_data+qy_data*qy_data+qz_data*qz_data)
-           
-        # Extra protection(it is needed for some data files): 
-        # If all mask elements are False, put all True
-        if not mask.any(): mask[mask==False] = True   
-  
-        # Store limits of the image in q space
-        xmin    = numpy.min(qx_data)
-        xmax    = numpy.max(qx_data)
-        ymin    = numpy.min(qy_data)
-        ymax    = numpy.max(qy_data)
-
-        # units
-        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)
-            
-        ## calculate the range of the qx and qy_data
-        x_size = math.fabs(xmax - xmin)
-        y_size = math.fabs(ymax - ymin)
-        
-        # calculate the number of pixels in the each axes
-        npix_y = math.floor(math.sqrt(len(data)))
-        npix_x = math.floor(len(data)/npix_y)
-        
-        # calculate the size of bins      
-        xstep = x_size/(npix_x-1)
-        ystep = y_size/(npix_y-1)
-        
-        # store x and y axis bin centers in q space
-        x_bins  = numpy.arange(xmin,xmax+xstep,xstep)
-        y_bins  = numpy.arange(ymin,ymax+ystep,ystep)
-       
-        # get the limits of q values
-        xmin = xmin - xstep/2
-        xmax = xmax + xstep/2
-        ymin = ymin - ystep/2
-        ymax = ymax + ystep/2
-        
-        #Store data in outputs  
-        #TODO: Check the lengths 
-        output.data     = data
-        if (err_data == 1).all():
-            output.err_data = numpy.sqrt(numpy.abs(data))
-            output.err_data[output.err_data == 0.0] = 1.0
-        else:
-            output.err_data = err_data
-            
-        output.qx_data  = qx_data
-        output.qy_data  = qy_data             
-        output.q_data   = q_data
-        output.mask     = mask 
-        
-        output.x_bins = x_bins
-        output.y_bins = y_bins
-               
-        output.xmin = xmin
-        output.xmax = xmax
-        output.ymin = ymin
-        output.ymax = ymax
-        
-        output.source.wavelength = wavelength
-        
-        # Store pixel size in mm
-        detector.pixel_size.x = pixel_x
-        detector.pixel_size.y = pixel_y
-        
-        # Store the sample to detector distance
-        detector.distance = distance
-        
-        # optional data: if all of dq data == 0, do not pass to output
-        if len(dqx_data) == len(qx_data) and dqx_data.any()!=0: 
-            # if no dqx_data, do not pass dqy_data.
-            #(1 axis dq is not supported yet).
-            if len(dqy_data) == len(qy_data) and dqy_data.any()!=0:
-                # Currently we do not support dq parr, perp.
-                # tranfer the comp. to cartesian coord. for newer version.
-                if ver != 1:
-                    diag = numpy.sqrt(qx_data * qx_data + qy_data * qy_data)
-                    cos_th = qx_data / diag
-                    sin_th = qy_data / diag
-                    output.dqx_data = numpy.sqrt((dqx_data * cos_th) * \
-                                                 (dqx_data * cos_th) \
-                                                 + ( dqy_data * sin_th) * \
-                                                  ( dqy_data * sin_th))
-                    output.dqy_data = numpy.sqrt((dqx_data * sin_th) * \
-                                                 (dqx_data * sin_th) \
-                                                 + ( dqy_data * cos_th) * \
-                                                  ( dqy_data * cos_th))
-                else:
-                    output.dqx_data = dqx_data
-                    output.dqy_data = dqy_data
-
-        # Units of axes
-        if data_conv_q is not None:
-            output.xaxis("\\rm{Q_{x}}", output.Q_unit)
-            output.yaxis("\\rm{Q_{y}}", output.Q_unit)
-        else:
-            output.xaxis("\\rm{Q_{x}}", 'A^{-1}')
-            output.yaxis("\\rm{Q_{y}}", 'A^{-1}')            
-        if data_conv_i is not None:
-            output.zaxis("\\rm{Intensity}", output.I_unit)
-        else:
-            output.zaxis("\\rm{Intensity}","cm^{-1}")
-    
-        # Store loading process information
-        output.meta_data['loader'] = self.type_name
-
-        return output
-    
-if __name__ == "__main__": 
-    reader = Reader()
-    print reader.read("../test/exp18_14_igor_2dqxqy.dat") 
-        
-
Index: nsdataloader/readers/tiff_reader.py
===================================================================
--- sansdataloader/readers/tiff_reader.py	(revision aab4e1501beed9965c9e6c08d09fcd8e34a20adb)
+++ 	(revision )
@@ -1,109 +1,0 @@
-
-
-#####################################################################
-#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. 
-#See the license text in license.txt
-#copyright 2008, University of Tennessee
-######################################################################
-"""
-    Image reader. Untested. 
-"""
-
-
-#TODO: load and check data and orientation of the image (needs rendering)
-
-import math, logging, os
-import numpy
-from DataLoader.data_info import Data2D
-    
-class Reader:
-    """
-    Example data manipulation
-    """
-    ## File type
-    type_name = "TIF"   
-    ## Wildcards
-    type = ["TIF files (*.tif)|*.tif",
-            "TIFF files (*.tiff)|*.tiff",
-            ]
-    ## Extension
-    ext  = ['.tif', '.tiff']    
-        
-    def read(self, filename=None):
-        """
-        Open and read the data in a file
-        
-        :param file: path of the file
-        """
-        try:
-            import Image
-        except:
-            msg = "tiff_reader: could not load file. Missing Image module."
-            raise RuntimeError, msg
-        
-        # Instantiate data object
-        output = Data2D()
-        output.filename = os.path.basename(filename)
-            
-        # Read in the image
-        try:
-            im = Image.open(filename)
-        except :
-            raise  RuntimeError,"cannot open %s"%(filename)
-        data = im.getdata()
-
-        # Initiazed the output data object
-        output.data = numpy.zeros([im.size[0],im.size[1]])
-        output.err_data = numpy.zeros([im.size[0],im.size[1]])
-        
-        # Initialize 
-        x_vals = []
-        y_vals = [] 
-
-        # x and y vectors
-        for i_x in range(im.size[0]):
-            x_vals.append(i_x)
-            
-        itot = 0
-        for i_y in range(im.size[1]):
-            y_vals.append(i_y)
-
-        for val in data:
-            try:
-                value = float(val)
-            except:
-                logging.error("tiff_reader: had to skip a non-float point")
-                continue
-            
-            # Get bin number
-            if math.fmod(itot, im.size[0])==0:
-                i_x = 0
-                i_y += 1
-            else:
-                i_x += 1
-                
-            output.data[im.size[1]-1-i_y][i_x] = value
-            
-            itot += 1
-                
-        output.xbins      = im.size[0]
-        output.ybins      = im.size[1]
-        output.x_bins     = x_vals
-        output.y_bins     = y_vals
-        output.xmin       = 0
-        output.xmax       = im.size[0]-1
-        output.ymin       = 0
-        output.ymax       = im.size[0]-1
-        
-        # Store loading process information
-        output.meta_data['loader'] = self.type_name 
-        return output
-        
-
-if __name__ == "__main__": 
-    reader = Reader()
-    print reader.read("../test/MP_New.sans")
-    
-
Index: sansdataloader/src/sans/dataloader/readers/IgorReader.py
===================================================================
--- sansdataloader/src/sans/dataloader/readers/IgorReader.py	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
+++ sansdataloader/src/sans/dataloader/readers/IgorReader.py	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
@@ -0,0 +1,314 @@
+
+############################################################################
+#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
+#############################################################################
+
+"""
+    IGOR 2D reduced file reader
+"""
+
+import os
+#import sys
+import numpy
+import math
+#import logging
+from DataLoader.data_info import Data2D
+from DataLoader.data_info import Detector
+from DataLoader.manipulations import reader2D_converter
+
+# 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 """
+    ## File type
+    type_name = "IGOR 2D"   
+    ## Wildcards
+    type = ["IGOR 2D files (*.ASC)|*.ASC"]
+    ## Extension
+    ext=['.ASC', '.asc']
+
+    def read(self,filename=None):
+        """ Read file """
+        if not os.path.isfile(filename):
+            raise ValueError, \
+            "Specified file %s is not a regular file" % filename
+        
+        # Read file
+        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)
+                
+        # Get content
+        dataStarted = False
+        
+        
+        lines = buf.split('\n')
+        itot = 0
+        x = []
+        y = []
+        
+        ncounts = 0
+        
+        xmin = None
+        xmax = None
+        ymin = None
+        ymax = None
+        
+        i_x = 0
+        i_y = -1
+        i_tot_row = 0
+        
+        isInfo = False
+        isCenter = False
+       
+        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)            
+         
+        for line in lines:
+            
+            # Find setup info line
+            if isInfo:
+                isInfo = False
+                line_toks = line.split()
+                # Wavelength in Angstrom
+                try:
+                    wavelength = float(line_toks[1])
+                except:
+                    msg = "IgorReader: can't read this file, missing wavelength"
+                    raise ValueError, msg
+                
+            #Find # of bins in a row assuming the detector is square.
+            if dataStarted == True:
+                try:
+                    value = float(line)
+                except:
+                    # Found a non-float entry, skip it
+                    continue
+                
+                # Get total bin number
+                
+            i_tot_row += 1
+        i_tot_row=math.ceil(math.sqrt(i_tot_row))-1 
+        #print "i_tot", i_tot_row
+        size_x = i_tot_row#192#128
+        size_y = i_tot_row#192#128
+        output.data = numpy.zeros([size_x,size_y])
+        output.err_data = numpy.zeros([size_x,size_y])
+     
+        #Read Header and 2D data
+        for line in lines:
+            # Find setup info line
+            if isInfo:
+                isInfo = False
+                line_toks = line.split()
+                # Wavelength in Angstrom
+                try:
+                    wavelength = float(line_toks[1])
+                except:
+                    msg = "IgorReader: can't read this file, missing wavelength"
+                    raise ValueError, msg
+                # Distance in meters
+                try:
+                    distance = float(line_toks[3])
+                except:
+                    msg = "IgorReader: can't read this file, missing distance"
+                    raise ValueError, msg
+                
+                # Distance in meters
+                try:
+                    transmission = float(line_toks[4])
+                except:
+                    msg = "IgorReader: can't read this file, "
+                    msg += "missing transmission"
+                    raise ValueError, msg
+                                            
+            if line.count("LAMBDA")>0:
+                isInfo = True
+                
+            # Find center info line
+            if isCenter:
+                isCenter = False                
+                line_toks = line.split()
+                
+                # Center in bin number: Must substrate 1 because 
+                #the index starts from 1
+                center_x = float(line_toks[0])-1
+                center_y = float(line_toks[1])-1
+
+            if line.count("BCENT")>0:
+                isCenter = True
+                
+        
+            # Find data start
+            if line.count("***")>0:
+                dataStarted = True
+                
+                # Check that we have all the info
+                if wavelength == None \
+                    or distance == None \
+                    or center_x == None \
+                    or center_y == None:
+                    msg = "IgorReader:Missing information in data file"
+                    raise ValueError, msg
+                
+            if dataStarted == True:
+                try:
+                    value = float(line)
+                except:
+                    # Found a non-float entry, skip it
+                    continue
+                
+                # Get bin number
+                if math.fmod(itot, i_tot_row)==0:
+                    i_x = 0
+                    i_y += 1
+                else:
+                    i_x += 1
+                    
+                output.data[i_y][i_x] = value
+                ncounts += 1 
+                
+                # Det 640 x 640 mm
+                # Q = 4pi/lambda sin(theta/2)
+                # Bin size is 0.5 cm 
+                #REmoved +1 from theta = (i_x-center_x+1)*0.5 / distance 
+                # / 100.0 and 
+                #REmoved +1 from theta = (i_y-center_y+1)*0.5 /
+                # distance / 100.0
+                #ToDo: Need  complete check if the following
+                # covert process is consistent with fitting.py.
+                theta = (i_x-center_x)*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
+                if xmax==None or qx>xmax:
+                    xmax = qx
+                
+                theta = (i_y-center_y)*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
+                if ymax==None or qy>ymax:
+                    ymax = qy
+                
+                if not qx in x:
+                    x.append(qx)
+                if not qy in y:
+                    y.append(qy)
+                
+                itot += 1
+                  
+                  
+        theta = 0.25 / distance / 100.0
+        xstep = 4.0*math.pi/wavelength * math.sin(theta/2.0)
+        
+        theta = 0.25 / distance / 100.0
+        ystep = 4.0*math.pi/wavelength * math.sin(theta/2.0)
+        
+        # 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_{x}}", output.Q_unit)
+            output.yaxis("\\rm{Q_{y}}", output.Q_unit)
+        else:
+            output.xaxis("\\rm{Q_{x}}", 'A^{-1}')
+            output.yaxis("\\rm{Q_{y}}", 'A^{-1}')
+            
+        if data_conv_i is not None:
+            output.zaxis("\\rm{Intensity}", output.I_unit)
+        else:
+            output.zaxis("\\rm{Intensity}","cm^{-1}")
+    
+        # Store loading process information
+        output.meta_data['loader'] = self.type_name
+        output = reader2D_converter(output)
+
+        return output
+    
+if __name__ == "__main__": 
+    reader = Reader()
+    print reader.read("../test/MAR07232_rest.ASC") 
+    
Index: sansdataloader/src/sans/dataloader/readers/__init__.py
===================================================================
--- sansdataloader/src/sans/dataloader/readers/__init__.py	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
+++ sansdataloader/src/sans/dataloader/readers/__init__.py	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
@@ -0,0 +1,13 @@
+# Backward compatibility with the previous implementation of the default readers
+from associations import register_readers
+
+# Method to associate extensions to default readers 
+from associations import read_associations
+
+# Method to return the location of the XML settings file
+def get_data_path():
+    """
+        Return the location of the settings file for the data readers.
+    """
+    import os
+    return os.path.dirname(__file__)
Index: sansdataloader/src/sans/dataloader/readers/abs_reader.py
===================================================================
--- sansdataloader/src/sans/dataloader/readers/abs_reader.py	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
+++ sansdataloader/src/sans/dataloader/readers/abs_reader.py	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
@@ -0,0 +1,263 @@
+"""
+"""
+#####################################################################
+#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. 
+#See the license text in license.txt
+#copyright 2008, University of Tennessee
+######################################################################
+
+import numpy
+import os
+from DataLoader.data_info import Data1D
+from DataLoader.data_info import Detector
+
+has_converter = True
+try:
+    from data_util.nxsunit import Converter
+except:
+    has_converter = False
+    
+class Reader:
+    """
+    Class to load IGOR reduced .ABS files
+    """
+    ## File type
+    type_name = "IGOR 1D"   
+    ## Wildcards
+    type = ["IGOR 1D files (*.abs)|*.abs"]
+    ## List of allowed extensions
+    ext = ['.abs', '.ABS']  
+    
+    def read(self, path):
+        """ 
+        Load data file.
+        
+        :param path: file path
+        
+        :return: Data1D object, or None
+        
+        :raise RuntimeError: when the file can't be opened
+        :raise ValueError: when the length of the data vectors are inconsistent
+        """
+        if os.path.isfile(path):
+            basename  = os.path.basename(path)
+            root, extension = os.path.splitext(basename)
+            if extension.lower() in self.ext:
+                try:
+                    input_f =  open(path,'r')
+                except :
+                    raise  RuntimeError, "abs_reader: cannot open %s" % path
+                buff = input_f.read()
+                lines = buff.split('\n')
+                x  = numpy.zeros(0)
+                y  = numpy.zeros(0)
+                dy = numpy.zeros(0)
+                dx = numpy.zeros(0)
+                output = Data1D(x, y, dy=dy, dx=dx)
+                detector = Detector()
+                output.detector.append(detector)
+                output.filename = basename
+                
+                is_info = False
+                is_center = False
+                is_data_started = False
+                
+                data_conv_q = None
+                data_conv_i = None
+                
+                if has_converter == True and output.x_unit != '1/A':
+                    data_conv_q = Converter('1/A')
+                    # Test it
+                    data_conv_q(1.0, output.x_unit)
+                    
+                if has_converter == True and output.y_unit != '1/cm':
+                    data_conv_i = Converter('1/cm')
+                    # Test it
+                    data_conv_i(1.0, output.y_unit)
+                
+                for line in lines:
+                    
+                    # Information line 1
+                    if is_info == True:
+                        is_info = False
+                        line_toks = line.split()
+                        
+                        # Wavelength in Angstrom
+                        try:
+                            value = float(line_toks[1])
+                            if has_converter == True and \
+                                output.source.wavelength_unit != 'A':
+                                conv = Converter('A')
+                                output.source.wavelength = conv(value, 
+                                        units=output.source.wavelength_unit)
+                            else:
+                                output.source.wavelength = value
+                        except:
+                            #goes to ASC reader
+                            msg = "abs_reader: cannot open %s" % path
+                            raise  RuntimeError, msg
+                            #raise ValueError,"IgorReader: can't read this file,
+                            # missing wavelength"
+                        
+                        # Distance in meters
+                        try:
+                            value = float(line_toks[3])
+                            if has_converter == True and \
+                                detector.distance_unit != 'm':
+                                conv = Converter('m')
+                                detector.distance = conv(value, 
+                                                units=detector.distance_unit)
+                            else:
+                                detector.distance = value
+                        except:
+                            #goes to ASC reader
+                            msg = "abs_reader: cannot open %s" % path
+                            raise  RuntimeError, msg
+                        # Transmission 
+                        try:
+                            output.sample.transmission = float(line_toks[4])
+                        except:
+                            # Transmission is not a mandatory entry
+                            pass
+                    
+                        # Thickness in mm
+                        try:
+                            value = float(line_toks[5])
+                            if has_converter == True and \
+                                output.sample.thickness_unit != 'cm':
+                                conv = Converter('cm')
+                                output.sample.thickness = conv(value, 
+                                            units=output.sample.thickness_unit)
+                            else:
+                                output.sample.thickness = value
+                        except:
+                            # Thickness is not a mandatory entry
+                            pass
+                    
+                    #MON CNT   LAMBDA   DET ANG   DET DIST   TRANS   THICK 
+                    #  AVE   STEP
+                    if line.count("LAMBDA") > 0:
+                        is_info = True
+                        
+                    # Find center info line
+                    if is_center == True:
+                        is_center = False                
+                        line_toks = line.split()
+                        # Center in bin number
+                        center_x = float(line_toks[0])
+                        center_y = float(line_toks[1])
+                        
+                        # Bin size
+                        if has_converter == True and \
+                            detector.pixel_size_unit != 'mm':
+                            conv = Converter('mm')
+                            detector.pixel_size.x = conv(5.0, 
+                                                units=detector.pixel_size_unit)
+                            detector.pixel_size.y = conv(5.0,
+                                                units=detector.pixel_size_unit)
+                        else:
+                            detector.pixel_size.x = 5.0
+                            detector.pixel_size.y = 5.0
+                        
+                        # Store beam center in distance units
+                        # Det 640 x 640 mm
+                        if has_converter==True and \
+                            detector.beam_center_unit != 'mm':
+                            conv = Converter('mm')
+                            detector.beam_center.x = conv(center_x * 5.0,
+                                             units=detector.beam_center_unit)
+                            detector.beam_center.y = conv(center_y * 5.0, 
+                                            units=detector.beam_center_unit)
+                        else:
+                            detector.beam_center.x = center_x * 5.0
+                            detector.beam_center.y = center_y * 5.0
+                        
+                        # Detector type
+                        try:
+                            detector.name = line_toks[7]
+                        except:
+                            # Detector name is not a mandatory entry
+                            pass
+                    
+                    #BCENT(X,Y)   A1(mm)   A2(mm)   A1A2DIST(m)   DL/L 
+                    #  BSTOP(mm)   DET_TYP 
+                    if line.count("BCENT") > 0:
+                        is_center = True
+                        
+                    # Parse the data
+                    if is_data_started == True:
+                        toks = line.split()
+
+                        try:  
+                            _x  = float(toks[0])
+                            _y  = float(toks[1]) 
+                            _dy = float(toks[2])
+                            _dx = float(toks[3])
+                            
+                            if data_conv_q is not None:
+                                _x = data_conv_q(_x, units=output.x_unit)
+                                _dx = data_conv_i(_dx, units=output.x_unit)
+                                
+                            if data_conv_i is not None:
+                                _y = data_conv_i(_y, units=output.y_unit)
+                                _dy = data_conv_i(_dy, units=output.y_unit)
+                           
+                            x  = numpy.append(x,   _x) 
+                            y  = numpy.append(y,   _y)
+                            dy = numpy.append(dy, _dy)
+                            dx  = numpy.append(dx, _dx)
+                            
+                        except:
+                            # Could not read this data line. If we are here
+                            # it is because we are in the data section. Just
+                            # skip it.
+                            pass
+                            
+                    #The 6 columns are | Q (1/A) | I(Q) (1/cm) | std. dev.
+                    # I(Q) (1/cm) | sigmaQ | meanQ | ShadowFactor|
+                    if line.count("The 6 columns")>0:
+                        is_data_started = True
+            
+                # Sanity check
+                if not len(y) == len(dy):
+                    msg = "abs_reader: y and dy have different length"
+                    raise ValueError, msg
+                # If the data length is zero, consider this as
+                # though we were not able to read the file.
+                if len(x) == 0:
+                    raise ValueError, "ascii_reader: could not load file"
+                
+                # Zeros in dx, dy 
+                if not numpy.all(dx==0):
+                    dx[dx==0] = _ZERO
+                if not numpy.all(dy==0):
+                    dy[dy==0] = _ZERO
+
+                output.x = x[x!=0]
+                output.y = y[x!=0]
+                output.dy = dy[x!=0]
+                output.dx = dx[x!=0]
+                if data_conv_q is not None:
+                    output.xaxis("\\rm{Q}", output.x_unit)
+                else:
+                    output.xaxis("\\rm{Q}", 'A^{-1}')
+                if data_conv_i is not None:
+                    output.yaxis("\\rm{Intensity}", output.y_unit)
+                else:
+                    output.yaxis("\\rm{Intensity}","cm^{-1}")
+                    
+                # Store loading process information
+                output.meta_data['loader'] = self.type_name                       
+                return output
+        else:
+            raise RuntimeError, "%s is not a file" % path
+        return None
+    
+if __name__ == "__main__": 
+    reader = Reader()
+    print reader.read("../test/jan08002.ABS")
+    
+    
+            
Index: sansdataloader/src/sans/dataloader/readers/ascii_reader.py
===================================================================
--- sansdataloader/src/sans/dataloader/readers/ascii_reader.py	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
+++ sansdataloader/src/sans/dataloader/readers/ascii_reader.py	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
@@ -0,0 +1,361 @@
+
+
+############################################################################
+#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 numpy
+import os
+from DataLoader.data_info import Data1D
+
+# Check whether we have a converter available
+has_converter = True
+try:
+    from data_util.nxsunit import Converter
+except:
+    has_converter = False
+_ZERO = 1e-16
+
+class Reader:
+    """
+    Class to load ascii files (2, 3 or 4 columns).
+    """
+    ## File type
+    type_name = "ASCII"
+    
+    ## Wildcards
+    type = ["ASCII files (*.txt)|*.txt",
+            "ASCII files (*.dat)|*.dat",
+            "ASCII files (*.abs)|*.abs"]
+    ## List of allowed extensions
+    ext = ['.txt', '.TXT', '.dat', '.DAT', '.abs', '.ABS']  
+    
+    ## Flag to bypass extension check
+    allow_all = True
+    
+    def read(self, path):
+        """ 
+        Load data file
+        
+        :param path: file path
+        
+        :return: Data1D object, or None
+        
+        :raise RuntimeError: when the file can't be opened
+        :raise ValueError: when the length of the data vectors are inconsistent
+        """
+        if os.path.isfile(path):
+            basename  = os.path.basename(path)
+            _, extension = os.path.splitext(basename)
+            if self.allow_all or extension.lower() in self.ext:
+                try:
+                    input_f =  open(path,'r')
+                except :
+                    raise  RuntimeError, "ascii_reader: cannot open %s" % path
+                buff = input_f.read()
+                lines = buff.split('\n')
+                
+                #Jae could not find python universal line spliter: 
+                #keep the below for now
+                # some ascii data has \r line separator,
+                # try it when the data is on only one long line
+                if len(lines) < 2 : 
+                    lines = buff.split('\r')
+                 
+                x  = numpy.zeros(0)
+                y  = numpy.zeros(0)
+                dy = numpy.zeros(0)
+                dx = numpy.zeros(0)
+                
+               #temp. space to sort data
+                tx  = numpy.zeros(0)
+                ty  = numpy.zeros(0)
+                tdy = numpy.zeros(0)
+                tdx = numpy.zeros(0)
+                
+                output = Data1D(x, y, dy=dy, dx=dx)
+                self.filename = output.filename = basename
+           
+                data_conv_q = None
+                data_conv_i = None
+                
+                if has_converter == True and output.x_unit != '1/A':
+                    data_conv_q = Converter('1/A')
+                    # Test it
+                    data_conv_q(1.0, output.x_unit)
+                    
+                if has_converter == True and output.y_unit != '1/cm':
+                    data_conv_i = Converter('1/cm')
+                    # Test it
+                    data_conv_i(1.0, output.y_unit)
+           
+                
+                # The first good line of data will define whether
+                # we have 2-column or 3-column ascii
+                has_error_dx = None
+                has_error_dy = None
+                
+                #Initialize counters for data lines and header lines.
+                is_data = False #Has more than 5 lines
+                # More than "5" lines of data is considered as actual
+                # data unless that is the only data
+                mum_data_lines = 5 
+                # To count # of current data candidate lines
+                i = -1  
+                # To count total # of previous data candidate lines          
+                i1 = -1 
+                # To count # of header lines          
+                j = -1
+                # Helps to count # of header lines            
+                j1 = -1
+                #minimum required number of columns of data; ( <= 4).           
+                lentoks = 2     
+                for line in lines:
+                    toks = line.split()
+                    try:
+                        #Make sure that all columns are numbers.
+                        for colnum in range(len(toks)):
+                            float(toks[colnum])
+                            
+                        _x = float(toks[0])
+                        _y = float(toks[1])
+                        
+                        #Reset the header line counters
+                        if j == j1:
+                            j = 0
+                            j1 = 0
+                            
+                        if i > 1:
+                            is_data = True
+                        
+                        if data_conv_q is not None:
+                            _x = data_conv_q(_x, units=output.x_unit)
+                            
+                        if data_conv_i is not None:
+                            _y = data_conv_i(_y, units=output.y_unit)                        
+                        
+                        # If we have an extra token, check
+                        # whether it can be interpreted as a
+                        # third column.
+                        _dy = None
+                        if len(toks) > 2:
+                            try:
+                                _dy = float(toks[2])
+                                
+                                if data_conv_i is not None:
+                                    _dy = data_conv_i(_dy, units=output.y_unit)
+                                
+                            except:
+                                # The third column is not a float, skip it.
+                                pass
+                            
+                        # If we haven't set the 3rd column
+                        # flag, set it now.
+                        if has_error_dy == None:
+                            has_error_dy = False if _dy == None else True
+                            
+                        #Check for dx
+                        _dx = None
+                        if len(toks) > 3:
+                            try:
+                                _dx = float(toks[3])
+                                
+                                if data_conv_i is not None:
+                                    _dx = data_conv_i(_dx, units=output.x_unit)
+                                
+                            except:
+                                # The 4th column is not a float, skip it.
+                                pass
+                            
+                        # If we haven't set the 3rd column
+                        # flag, set it now.
+                        if has_error_dx == None:
+                            has_error_dx = False if _dx == None else True
+                        
+                        #After talked with PB, we decided to take care of only 
+                        # 4 columns of data for now.
+                        #number of columns in the current line
+                        #To remember the # of columns in the current 
+                        #line of data
+                        new_lentoks = len(toks)
+                        
+                        #If the previous columns not equal to the current, 
+                        #mark the previous as non-data and reset the dependents.  
+                        if lentoks != new_lentoks :
+                            if is_data == True:
+                                break
+                            else:
+                                i = -1
+                                i1 = 0
+                                j = -1
+                                j1 = -1
+                            
+                            
+                        #Delete the previously stored lines of data candidates
+                        # if is not data.
+                        if i < 0 and -1 < i1 < mum_data_lines and \
+                            is_data == False:
+                            try:
+                                x = numpy.zeros(0)
+                                y = numpy.zeros(0)
+                            except:
+                                pass
+                            
+                        x  = numpy.append(x,   _x) 
+                        y  = numpy.append(y,   _y)
+                        
+                        if has_error_dy == True:
+                            #Delete the previously stored lines of
+                            # data candidates if is not data.
+                            if i < 0 and -1 < i1 < mum_data_lines and \
+                                is_data == False:
+                                try:
+                                    dy = numpy.zeros(0)  
+                                except:
+                                    pass                                                               
+                            dy = numpy.append(dy, _dy)
+                            
+                        if has_error_dx == True:
+                            #Delete the previously stored lines of
+                            # data candidates if is not data.
+                            if i < 0 and -1 < i1 < mum_data_lines and \
+                                is_data == False:
+                                try:
+                                    dx = numpy.zeros(0)                            
+                                except:
+                                    pass                                                               
+                            dx = numpy.append(dx, _dx)
+                            
+                        #Same for temp.
+                        #Delete the previously stored lines of data candidates
+                        # if is not data.
+                        if i < 0 and -1 < i1 < mum_data_lines and\
+                            is_data == False:
+                            try:
+                                tx = numpy.zeros(0)
+                                ty = numpy.zeros(0)
+                            except:
+                                pass                                                           
+
+                        tx  = numpy.append(tx,   _x) 
+                        ty  = numpy.append(ty,   _y)
+                        
+                        if has_error_dy == True:
+                            #Delete the previously stored lines of
+                            # data candidates if is not data.
+                            if i < 0 and -1 < i1 < mum_data_lines and \
+                                is_data == False:
+                                try:
+                                    tdy = numpy.zeros(0)
+                                except:
+                                    pass                                                                                                                
+                            tdy = numpy.append(tdy, _dy)
+                        if has_error_dx == True:
+                            #Delete the previously stored lines of
+                            # data candidates if is not data.
+                            if i < 0 and -1 < i1 < mum_data_lines and \
+                                is_data == False:
+                                try:
+                                    tdx = numpy.zeros(0)
+                                except:
+                                    pass                                                                                                          
+                            tdx = numpy.append(tdx, _dx)
+
+                        #reset i1 and flag lentoks for the next
+                        if lentoks < new_lentoks:
+                            if is_data == False:
+                                i1 = -1                            
+                        #To remember the # of columns on the current line
+                        # for the next line of data
+                        lentoks = len(toks)
+                        
+                        #Reset # of header lines and counts # 
+                        # of data candidate lines    
+                        if j == 0 and j1 == 0:
+                            i1 = i + 1                            
+                        i += 1
+                    except:
+
+                        # It is data and meet non - number, then stop reading
+                        if is_data == True:
+                            break    
+                        lentoks = 2
+                        #Counting # of header lines                    
+                        j += 1
+                        if j == j1 + 1:
+                            j1 = j                            
+                        else:                            
+                            j = -1
+                        #Reset # of lines of data candidates
+                        i = -1
+                        
+                        # Couldn't parse this line, skip it 
+                        pass
+                    
+                input_f.close()     
+                # Sanity check
+                if has_error_dy == True and not len(y) == len(dy):
+                    msg = "ascii_reader: y and dy have different length"
+                    raise RuntimeError, msg
+                if has_error_dx == True and not len(x) == len(dx):
+                    msg = "ascii_reader: y and dy have different length"
+                    raise RuntimeError, msg
+                # If the data length is zero, consider this as
+                # though we were not able to read the file.
+                if len(x) == 0:
+                    raise RuntimeError, "ascii_reader: could not load file"
+                
+                #Let's re-order the data to make cal.
+                # curve look better some cases
+                ind = numpy.lexsort((ty, tx))
+                for i in ind:
+                    x[i] = tx[ind[i]]
+                    y[i] = ty[ind[i]]
+                    if has_error_dy == True:
+                        dy[i] = tdy[ind[i]]
+                    if has_error_dx == True:
+                        dx[i] = tdx[ind[i]]
+                # Zeros in dx, dy 
+                if has_error_dx:
+                    dx[dx==0] = _ZERO
+                if has_error_dy:
+                    dy[dy==0] = _ZERO
+                #Data    
+                output.x = x[x!=0]
+                output.y = y[x!=0]
+                output.dy = dy[x!=0] if has_error_dy == True else numpy.zeros(len(output.y))
+                output.dx = dx[x!=0] if has_error_dx == True else numpy.zeros(len(output.x))
+                                
+                if data_conv_q is not None:
+                    output.xaxis("\\rm{Q}", output.x_unit)
+                else:
+                    output.xaxis("\\rm{Q}", 'A^{-1}')
+                if data_conv_i is not None:
+                    output.yaxis("\\rm{Intensity}", output.y_unit)
+                else:
+                    output.yaxis("\\rm{Intensity}","cm^{-1}")
+                    
+                # Store loading process information
+                output.meta_data['loader'] = self.type_name    
+                    
+                return output
+            
+        else:
+            raise RuntimeError, "%s is not a file" % path
+        return None
+    
+if __name__ == "__main__": 
+    reader = Reader()
+    #print reader.read("../test/test_3_columns.txt")
+    print reader.read("../test/empty.txt")
+    
+    
+                        
Index: sansdataloader/src/sans/dataloader/readers/associations.py
===================================================================
--- sansdataloader/src/sans/dataloader/readers/associations.py	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
+++ sansdataloader/src/sans/dataloader/readers/associations.py	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
@@ -0,0 +1,125 @@
+
+
+############################################################################
+#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 2009, University of Tennessee
+#############################################################################
+
+
+"""
+Module to associate default readers to file extensions.
+The module reads an xml file to get the readers for each file extension.
+The readers are tried in order they appear when reading a file.
+"""
+
+import os
+import sys
+import logging
+from lxml import etree 
+# Py2exe compatibility: import _elementpath to ensure that py2exe finds it
+from lxml import _elementpath  
+
+## Format version for the XML settings file
+VERSION = 'sansloader/1.0'
+
+def read_associations(loader, settings='defaults.xml'):
+    """
+    Read the specified settings file to associate
+    default readers to file extension.
+    
+    :param loader: Loader object
+    :param settings: path to the XML settings file [string]
+    """
+    reader_dir = os.path.dirname(__file__)
+    path = os.path.join(reader_dir, settings)
+    
+    # If we can't find the file in the installation
+    # directory, look into the execution directory.
+    if not os.path.isfile(path):
+        path = os.path.join(os.getcwd(), settings)
+    if not os.path.isfile(path):
+        path = os.path.join(os.path.dirname(os.path.sys.path[0]), settings)
+    if os.path.isfile(path):
+        tree = etree.parse(path, parser=etree.ETCompatXMLParser())
+        
+        # Check the format version number
+        # Specifying the namespace will take care of the file format version 
+        root = tree.getroot()
+        
+        # Read in the file extension associations
+        entry_list = root.xpath('/ns:SansLoader/ns:FileType',
+                                 namespaces={'ns': VERSION})
+
+        # For each FileType entry, get the associated reader and extension
+        for entry in entry_list:
+            reader = entry.get('reader')
+            ext    = entry.get('extension')
+            
+            if reader is not None and ext is not None:
+                # Associate the extension with a particular reader
+                # TODO: Modify the Register code to be case-insensitive 
+                # and remove the extra line below.
+                try:
+                    exec "import %s" % reader
+                    exec "loader.associate_file_type('%s', %s)" % (ext.lower(),
+                                                                    reader)
+                    exec "loader.associate_file_type('%s', %s)" % (ext.upper(),
+                                                                    reader)
+                except:
+                    msg = "read_associations: skipping association"
+                    msg += " for %s\n  %s" % (attr['extension'], sys.exc_value)
+                    logging.error(msg)
+         
+         
+def register_readers(registry_function):
+    """
+    Function called by the registry/loader object to register
+    all default readers using a call back function.
+    
+    :WARNING: this method is now obsolete
+
+    :param registry_function: function to be called to register each reader
+    """
+    logging.info("register_readers is now obsolete: use read_associations()")
+    import abs_reader
+    import cansas_reader
+    import ascii_reader
+    import cansas_reader
+    import danse_reader
+    import hfir1d_reader
+    import IgorReader
+    import red2d_reader
+    import tiff_reader
+
+    registry_function(abs_reader)
+    registry_function(cansas_reader)
+    registry_function(ascii_reader)
+    registry_function(cansas_reader)
+    registry_function(danse_reader)
+    registry_function(hfir1d_reader)
+    registry_function(IgorReader)
+    registry_function(red2d_reader)
+    registry_function(tiff_reader)
+    
+    return True            
+
+
+if __name__ == "__main__": 
+    logging.basicConfig(level=logging.INFO,
+                        format='%(asctime)s %(levelname)s %(message)s',
+                        filename='logger.log',
+                        filemode='w')
+    from DataLoader.loader import Loader
+    l = Loader()
+    read_associations(l)
+    
+    
+    print l.get_wildcards()
+    
+    
Index: sansdataloader/src/sans/dataloader/readers/cansas_reader.py
===================================================================
--- sansdataloader/src/sans/dataloader/readers/cansas_reader.py	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
+++ sansdataloader/src/sans/dataloader/readers/cansas_reader.py	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
@@ -0,0 +1,947 @@
+
+
+############################################################################
+#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,2009 University of Tennessee
+#############################################################################
+
+# Known issue: reader not compatible with multiple SASdata entries
+# within a single SASentry. Will raise a runtime error.
+
+#TODO: check that all vectors are written only if they have at 
+#    least one non-empty value
+#TODO: Writing only allows one SASentry per file.
+#     Would be best to allow multiple entries.
+#TODO: Store error list
+#TODO: Allow for additional meta data for each section
+#TODO: Notes need to be implemented. They can be any XML 
+#    structure in version 1.0
+#      Process notes have the same problem.
+#TODO: Unit conversion is not complete (temperature units are missing)
+
+
+import logging
+import numpy
+import os
+import sys
+from DataLoader.data_info import Data1D
+from DataLoader.data_info import Collimation
+from DataLoader.data_info import Detector
+from DataLoader.data_info import Process
+from DataLoader.data_info import Aperture
+from lxml import etree
+import xml.dom.minidom
+_ZERO = 1e-16
+has_converter = True
+try:
+    from data_util.nxsunit import Converter
+except:
+    has_converter = False
+
+CANSAS_NS = "cansas1d/1.0"
+
+def write_node(doc, parent, name, value, attr={}):
+    """
+    :param doc: document DOM
+    :param parent: parent node
+    :param name: tag of the element
+    :param value: value of the child text node
+    :param attr: attribute dictionary
+    
+    :return: True if something was appended, otherwise False
+    """
+    if value is not None:
+        node = doc.createElement(name)
+        node.appendChild(doc.createTextNode(str(value)))
+        for item in attr:
+            node.setAttribute(item, attr[item])
+        parent.appendChild(node)
+        return True
+    return False
+
+def get_content(location, node):
+    """
+    Get the first instance of the content of a xpath location.
+    
+    :param location: xpath location
+    :param node: node to start at
+    
+    :return: Element, or None
+    """
+    nodes = node.xpath(location, namespaces={'ns': CANSAS_NS})
+    
+    if len(nodes)>0:
+        return nodes[0]
+    else:
+        return None
+
+def get_float(location, node):
+    """
+    Get the content of a node as a float 
+    
+    :param location: xpath location
+    :param node: node to start at
+    """
+    nodes = node.xpath(location, namespaces={'ns': CANSAS_NS})
+    
+    value = None
+    attr = {}
+    if len(nodes) > 0:
+        try:
+            value = float(nodes[0].text)   
+        except:
+            # Could not pass, skip and return None
+            msg = "cansas_reader.get_float: could not "
+            msg += " convert '%s' to float" % nodes[0].text
+            logging.error(msg)
+        if nodes[0].get('unit') is not None:
+            attr['unit'] = nodes[0].get('unit')
+    return value, attr
+
+            
+class Reader:
+    """
+    Class to load cansas 1D XML files
+    
+    :Dependencies:
+        The CanSas reader requires PyXML 0.8.4 or later.
+    """
+    ## CanSAS version
+    version = '1.0'
+    ## File type
+    type_name = "CanSAS 1D"
+    ## Wildcards
+    type = ["CanSAS 1D files (*.xml)|*.xml",
+                        "CanSAS 1D AVE files (*.AVEx)|*.AVEx",
+                         "CanSAS 1D AVE files (*.ABSx)|*.ABSx"]
+
+    ## List of allowed extensions
+    ext = ['.xml', '.XML','.avex', '.AVEx', '.absx', 'ABSx']  
+    
+    def __init__(self):
+        ## List of errors
+        self.errors = []
+    
+    def read(self, path):
+        """ 
+        Load data file
+        
+        :param path: file path
+        
+        :return: Data1D object if a single SASentry was found, 
+                    or a list of Data1D objects if multiple entries were found,
+                    or None of nothing was found
+                    
+        :raise RuntimeError: when the file can't be opened
+        :raise ValueError: when the length of the data vectors are inconsistent
+        """
+        output = []
+        if os.path.isfile(path):
+            basename  = os.path.basename(path)
+            root, extension = os.path.splitext(basename)
+            if extension.lower() in self.ext:
+                
+                tree = etree.parse(path, parser=etree.ETCompatXMLParser())
+                # Check the format version number
+                # Specifying the namespace will take care of the file
+                # format version 
+                root = tree.getroot()
+                
+                entry_list = root.xpath('/ns:SASroot/ns:SASentry',
+                                         namespaces={'ns': CANSAS_NS})
+                
+                for entry in entry_list:
+                    self.errors = []
+                    sas_entry = self._parse_entry(entry)
+                    sas_entry.filename = basename
+                    
+                    # Store loading process information
+                    sas_entry.errors = self.errors
+                    sas_entry.meta_data['loader'] = self.type_name
+                    output.append(sas_entry)
+                
+        else:
+            raise RuntimeError, "%s is not a file" % path
+        # Return output consistent with the loader's api
+        if len(output) == 0:
+            #cannot return none when it cannot read 
+            #return None
+            raise RuntimeError, "%s cannot be read \n" % path
+        elif len(output) == 1:
+            return output[0]
+        else:
+            return output                
+                
+    def _parse_entry(self, dom):
+        """
+        Parse a SASentry
+        
+        :param node: SASentry node
+        
+        :return: Data1D object
+        """
+        x = numpy.zeros(0)
+        y = numpy.zeros(0)
+        
+        data_info = Data1D(x, y)
+        
+        # Look up title      
+        self._store_content('ns:Title', dom, 'title', data_info)
+        
+        # Look up run number   
+        nodes = dom.xpath('ns:Run', namespaces={'ns': CANSAS_NS})
+        for item in nodes:    
+            if item.text is not None:
+                value = item.text.strip()
+                if len(value) > 0:
+                    data_info.run.append(value)
+                    if item.get('name') is not None:
+                        data_info.run_name[value] = item.get('name')
+                           
+        # Look up instrument name              
+        self._store_content('ns:SASinstrument/ns:name', dom, 'instrument',
+                             data_info)
+
+        # Notes
+        note_list = dom.xpath('ns:SASnote', namespaces={'ns': CANSAS_NS})
+        for note in note_list:
+            try:
+                if note.text is not None:
+                    note_value = note.text.strip()
+                    if len(note_value) > 0:
+                        data_info.notes.append(note_value)
+            except:
+                err_mess = "cansas_reader.read: error processing"
+                err_mess += " entry notes\n  %s" % sys.exc_value
+                self.errors.append(err_mess)
+                logging.error(err_mess)
+        
+        # Sample info ###################
+        entry = get_content('ns:SASsample', dom)
+        if entry is not None:
+            data_info.sample.name = entry.get('name')
+            
+        self._store_content('ns:SASsample/ns:ID', 
+                     dom, 'ID', data_info.sample)                    
+        self._store_float('ns:SASsample/ns:thickness', 
+                     dom, 'thickness', data_info.sample)
+        self._store_float('ns:SASsample/ns:transmission', 
+                     dom, 'transmission', data_info.sample)
+        self._store_float('ns:SASsample/ns:temperature', 
+                     dom, 'temperature', data_info.sample)
+        
+        nodes = dom.xpath('ns:SASsample/ns:details', 
+                          namespaces={'ns': CANSAS_NS})
+        for item in nodes:
+            try:
+                if item.text is not None:
+                    detail_value = item.text.strip()
+                    if len(detail_value) > 0:
+                        data_info.sample.details.append(detail_value)
+            except:
+                err_mess = "cansas_reader.read: error processing "
+                err_mess += " sample details\n  %s" % sys.exc_value
+                self.errors.append(err_mess)
+                logging.error(err_mess)
+        
+        # Position (as a vector)
+        self._store_float('ns:SASsample/ns:position/ns:x', 
+                     dom, 'position.x', data_info.sample)          
+        self._store_float('ns:SASsample/ns:position/ns:y', 
+                     dom, 'position.y', data_info.sample)          
+        self._store_float('ns:SASsample/ns:position/ns:z', 
+                     dom, 'position.z', data_info.sample)          
+        
+        # Orientation (as a vector)
+        self._store_float('ns:SASsample/ns:orientation/ns:roll', 
+                     dom, 'orientation.x', data_info.sample)          
+        self._store_float('ns:SASsample/ns:orientation/ns:pitch', 
+                     dom, 'orientation.y', data_info.sample)          
+        self._store_float('ns:SASsample/ns:orientation/ns:yaw', 
+                     dom, 'orientation.z', data_info.sample)          
+       
+        # Source info ###################
+        entry = get_content('ns:SASinstrument/ns:SASsource', dom)
+        if entry is not None:
+            data_info.source.name = entry.get('name')
+        
+        self._store_content('ns:SASinstrument/ns:SASsource/ns:radiation', 
+                     dom, 'radiation', data_info.source)                    
+        self._store_content('ns:SASinstrument/ns:SASsource/ns:beam_shape', 
+                     dom, 'beam_shape', data_info.source)                    
+        self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength', 
+                     dom, 'wavelength', data_info.source)          
+        self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_min', 
+                     dom, 'wavelength_min', data_info.source)          
+        self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_max', 
+                     dom, 'wavelength_max', data_info.source)          
+        self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_spread', 
+                     dom, 'wavelength_spread', data_info.source)    
+        
+        # Beam size (as a vector)   
+        entry = get_content('ns:SASinstrument/ns:SASsource/ns:beam_size', dom)
+        if entry is not None:
+            data_info.source.beam_size_name = entry.get('name')
+            
+        self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:x', 
+                     dom, 'beam_size.x', data_info.source)    
+        self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:y', 
+                     dom, 'beam_size.y', data_info.source)    
+        self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:z', 
+                     dom, 'beam_size.z', data_info.source)    
+        
+        # Collimation info ###################
+        nodes = dom.xpath('ns:SASinstrument/ns:SAScollimation', 
+                          namespaces={'ns': CANSAS_NS})
+        for item in nodes:
+            collim = Collimation()
+            if item.get('name') is not None:
+                collim.name = item.get('name')
+            self._store_float('ns:length', item, 'length', collim)  
+            
+            # Look for apertures
+            apert_list = item.xpath('ns:aperture', namespaces={'ns': CANSAS_NS})
+            for apert in apert_list:
+                aperture =  Aperture()
+                
+                # Get the name and type of the aperture
+                aperture.name = apert.get('name')
+                aperture.type = apert.get('type')
+                    
+                self._store_float('ns:distance', apert, 'distance', aperture)    
+                
+                entry = get_content('ns:size', apert)
+                if entry is not None:
+                    aperture.size_name = entry.get('name')
+                
+                self._store_float('ns:size/ns:x', apert, 'size.x', aperture)    
+                self._store_float('ns:size/ns:y', apert, 'size.y', aperture)    
+                self._store_float('ns:size/ns:z', apert, 'size.z', aperture)
+                
+                collim.aperture.append(aperture)
+                
+            data_info.collimation.append(collim)
+        
+        # Detector info ######################
+        nodes = dom.xpath('ns:SASinstrument/ns:SASdetector',
+                           namespaces={'ns': CANSAS_NS})
+        for item in nodes:
+            
+            detector = Detector()
+            
+            self._store_content('ns:name', item, 'name', detector)
+            self._store_float('ns:SDD', item, 'distance', detector)    
+            
+            # Detector offset (as a vector)
+            self._store_float('ns:offset/ns:x', item, 'offset.x', detector)    
+            self._store_float('ns:offset/ns:y', item, 'offset.y', detector)    
+            self._store_float('ns:offset/ns:z', item, 'offset.z', detector)    
+            
+            # Detector orientation (as a vector)
+            self._store_float('ns:orientation/ns:roll',  item, 'orientation.x',
+                               detector)    
+            self._store_float('ns:orientation/ns:pitch', item, 'orientation.y',
+                               detector)    
+            self._store_float('ns:orientation/ns:yaw',   item, 'orientation.z',
+                               detector)    
+            
+            # Beam center (as a vector)
+            self._store_float('ns:beam_center/ns:x', item, 'beam_center.x',
+                               detector)    
+            self._store_float('ns:beam_center/ns:y', item, 'beam_center.y', 
+                              detector)    
+            self._store_float('ns:beam_center/ns:z', item, 'beam_center.z',
+                               detector)    
+            
+            # Pixel size (as a vector)
+            self._store_float('ns:pixel_size/ns:x', item, 'pixel_size.x',
+                               detector)    
+            self._store_float('ns:pixel_size/ns:y', item, 'pixel_size.y',
+                               detector)    
+            self._store_float('ns:pixel_size/ns:z', item, 'pixel_size.z',
+                               detector)    
+            
+            self._store_float('ns:slit_length', item, 'slit_length', detector)
+            
+            data_info.detector.append(detector)    
+
+        # Processes info ######################
+        nodes = dom.xpath('ns:SASprocess', namespaces={'ns': CANSAS_NS})
+        for item in nodes:
+            process = Process()
+            self._store_content('ns:name', item, 'name', process)
+            self._store_content('ns:date', item, 'date', process)
+            self._store_content('ns:description', item, 'description', process)
+            
+            term_list = item.xpath('ns:term', namespaces={'ns': CANSAS_NS})
+            for term in term_list:
+                try:
+                    term_attr = {}
+                    for attr in term.keys():
+                        term_attr[attr] = term.get(attr).strip()
+                    if term.text is not None:
+                        term_attr['value'] = term.text.strip()
+                        process.term.append(term_attr)
+                except:
+                    err_mess = "cansas_reader.read: error processing "
+                    err_mess += " process term\n  %s" % sys.exc_value
+                    self.errors.append(err_mess)
+                    logging.error(err_mess)
+            
+            note_list = item.xpath('ns:SASprocessnote', 
+                                   namespaces={'ns': CANSAS_NS})
+            for note in note_list:
+                if note.text is not None:
+                    process.notes.append(note.text.strip())
+            
+            data_info.process.append(process)
+            
+            
+        # Data info ######################
+        nodes = dom.xpath('ns:SASdata', namespaces={'ns': CANSAS_NS})
+        if len(nodes) > 1:
+            msg = "CanSAS reader is not compatible with multiple"
+            msg += " SASdata entries"
+            raise RuntimeError, msg
+        
+        nodes = dom.xpath('ns:SASdata/ns:Idata', namespaces={'ns': CANSAS_NS})
+
+        x  = numpy.zeros(0)
+        y  = numpy.zeros(0)
+        dx = numpy.zeros(0)
+        dy = numpy.zeros(0)
+        dxw = numpy.zeros(0)
+        dxl = numpy.zeros(0)
+        
+        for item in nodes:
+            _x, attr = get_float('ns:Q', item)
+            _dx, attr_d = get_float('ns:Qdev', item)
+            _dxl, attr_l = get_float('ns:dQl', item)
+            _dxw, attr_w = get_float('ns:dQw', item)
+            if _dx == None:
+                _dx = 0.0
+            if _dxl == None:
+                _dxl = 0.0
+            if _dxw == None:
+                _dxw = 0.0
+                
+            if attr.has_key('unit') and \
+                attr['unit'].lower() != data_info.x_unit.lower():
+                if has_converter==True:
+                    try:
+                        data_conv_q = Converter(attr['unit'])
+                        _x = data_conv_q(_x, units=data_info.x_unit)
+                    except:
+                        msg =  "CanSAS reader: could not convert "
+                        msg += "Q unit [%s]; " 
+                        msg += "expecting [%s]\n  %s" % (attr['unit'], 
+                                  data_info.x_unit, sys.exc_value)
+                        raise ValueError, msg
+                        
+                else:
+                    msg = "CanSAS reader: unrecognized Q unit [%s]; "
+                    msg += "expecting [%s]" % (attr['unit'], data_info.x_unit)
+                    raise ValueError, msg
+                        
+            # Error in Q
+            if attr_d.has_key('unit') and \
+                attr_d['unit'].lower() != data_info.x_unit.lower():
+                if has_converter==True:
+                    try:
+                        data_conv_q = Converter(attr_d['unit'])
+                        _dx = data_conv_q(_dx, units=data_info.x_unit)
+                    except:
+                        msg = "CanSAS reader: could not convert dQ unit [%s];"
+                        msg += " expecting " 
+                        msg += "[%s]\n  %s" % (attr['unit'],
+                                                data_info.x_unit, sys.exc_value)
+                        raise ValueError, msg
+                        
+                else:
+                    msg = "CanSAS reader: unrecognized dQ unit [%s]; "
+                    msg += "expecting [%s]" % (attr['unit'], data_info.x_unit)
+                    raise ValueError,  msg
+                        
+            # Slit length
+            if attr_l.has_key('unit') and \
+                attr_l['unit'].lower() != data_info.x_unit.lower():
+                if has_converter == True:
+                    try:
+                        data_conv_q = Converter(attr_l['unit'])
+                        _dxl = data_conv_q(_dxl, units=data_info.x_unit)
+                    except:
+                        msg = "CanSAS reader: could not convert dQl unit [%s];"
+                        msg += " expecting [%s]\n  %s" % (attr['unit'],
+                                             data_info.x_unit, sys.exc_value)
+                        raise ValueError, msg
+                        
+                else:
+                    msg = "CanSAS reader: unrecognized dQl unit [%s];"
+                    msg += " expecting [%s]" % (attr['unit'], data_info.x_unit)
+                    raise ValueError, msg
+                        
+            # Slit width
+            if attr_w.has_key('unit') and \
+            attr_w['unit'].lower() != data_info.x_unit.lower():
+                if has_converter == True:
+                    try:
+                        data_conv_q = Converter(attr_w['unit'])
+                        _dxw = data_conv_q(_dxw, units=data_info.x_unit)
+                    except:
+                        msg = "CanSAS reader: could not convert dQw unit [%s];"
+                        msg += " expecting [%s]\n  %s" % (attr['unit'], 
+                                                data_info.x_unit, sys.exc_value)
+                        raise ValueError, msg
+                        
+                else:
+                    msg = "CanSAS reader: unrecognized dQw unit [%s];"
+                    msg += " expecting [%s]" % (attr['unit'], data_info.x_unit)
+                    raise ValueError, msg   
+            _y, attr = get_float('ns:I', item)
+            _dy, attr_d = get_float('ns:Idev', item)
+            if _dy == None:
+                _dy = 0.0
+            if attr.has_key('unit') and \
+            attr['unit'].lower() != data_info.y_unit.lower():
+                if has_converter==True:
+                    try:
+                        data_conv_i = Converter(attr['unit'])
+                        _y = data_conv_i(_y, units=data_info.y_unit)
+                    except:
+                        if attr['unit'].lower() == 'count':
+                            pass
+                        else:
+                            msg = "CanSAS reader: could not"
+                            msg += " convert I(q) unit [%s];" % str(attr['unit'])
+                            msg += " expecting [%s]\n" % str(data_info.y_unit)
+                            msg += "  %s" % str(sys.exc_value)
+                            raise ValueError, msg
+                else:
+                    msg = "CanSAS reader: unrecognized I(q) unit [%s];"
+                    msg += " expecting [%s]" % (attr['unit'], data_info.y_unit)
+                    raise ValueError, msg 
+                        
+            if attr_d.has_key('unit') and \
+            attr_d['unit'].lower() != data_info.y_unit.lower():
+                if has_converter==True:
+                    try:
+                        data_conv_i = Converter(attr_d['unit'])
+                        _dy = data_conv_i(_dy, units=data_info.y_unit)
+                    except:
+                        if attr_d['unit'].lower() == 'count':
+                            pass 
+                        else:
+                            msg = "CanSAS reader: could not convert dI(q) unit "
+                            msg += "[%s]; expecting [%s]\n  %s"  % (attr_d['unit'],
+                                                 data_info.y_unit, sys.exc_value)
+                            raise ValueError, msg
+                else:
+                    msg = "CanSAS reader: unrecognized dI(q) unit [%s]; "
+                    msg += "expecting [%s]" % (attr_d['unit'], data_info.y_unit)
+                    raise ValueError, msg
+                
+            if _x is not None and _y is not None:
+                x  = numpy.append(x, _x)
+                y  = numpy.append(y, _y)
+                dx = numpy.append(dx, _dx)
+                dy = numpy.append(dy, _dy)
+                dxl = numpy.append(dxl, _dxl)
+                dxw = numpy.append(dxw, _dxw)
+        # Zeros in dx, dy 
+        if not numpy.all(dx==0):
+            dx[dx==0] = _ZERO
+        if not numpy.all(dy==0):
+            dy[dy==0] = _ZERO
+       
+        data_info.x = x[x!=0]
+        data_info.y = y[x!=0]
+        data_info.dx = dx[x!=0]
+        
+        data_info.dy = dy[x!=0]
+        data_info.dxl = dxl[x!=0]
+        data_info.dxw = dxw[x!=0]
+        
+        data_conv_q = None
+        data_conv_i = None
+        
+        if has_converter == True and data_info.x_unit != '1/A':
+            data_conv_q = Converter('1/A')
+            # Test it
+            data_conv_q(1.0, output.Q_unit)
+            
+        if has_converter == True and data_info.y_unit != '1/cm':
+            data_conv_i = Converter('1/cm')
+            # Test it
+            data_conv_i(1.0, output.I_unit)                    
+                
+        if data_conv_q is not None:
+            data_info.xaxis("\\rm{Q}", data_info.x_unit)
+        else:
+            data_info.xaxis("\\rm{Q}", 'A^{-1}')
+        if data_conv_i is not None:
+            data_info.yaxis("\\rm{Intensity}", data_info.y_unit)
+        else:
+            data_info.yaxis("\\rm{Intensity}","cm^{-1}")
+
+        return data_info
+
+    def _to_xml_doc(self, datainfo):
+        """
+        Create an XML document to contain the content of a Data1D
+        
+        :param datainfo: Data1D object
+        """
+        
+        if not issubclass(datainfo.__class__, Data1D):
+            raise RuntimeError, "The cansas writer expects a Data1D instance"
+        
+        doc = xml.dom.minidom.Document()
+        main_node = doc.createElement("SASroot")
+        main_node.setAttribute("version", self.version)
+        main_node.setAttribute("xmlns", "cansas1d/%s" % self.version)
+        main_node.setAttribute("xmlns:xsi",
+                               "http://www.w3.org/2001/XMLSchema-instance")
+        main_node.setAttribute("xsi:schemaLocation",
+                               "cansas1d/%s http://svn.smallangles.net/svn/canSAS/1dwg/trunk/cansas1d.xsd" % self.version)
+        
+        doc.appendChild(main_node)
+        
+        entry_node = doc.createElement("SASentry")
+        main_node.appendChild(entry_node)
+        
+        write_node(doc, entry_node, "Title", datainfo.title)
+        for item in datainfo.run:
+            runname = {}
+            if datainfo.run_name.has_key(item) and \
+            len(str(datainfo.run_name[item]))>1:
+                runname = {'name': datainfo.run_name[item] }
+            write_node(doc, entry_node, "Run", item, runname)
+        
+        # Data info
+        node = doc.createElement("SASdata")
+        entry_node.appendChild(node)
+        
+        for i in range(len(datainfo.x)):
+            pt = doc.createElement("Idata")
+            node.appendChild(pt)
+            write_node(doc, pt, "Q", datainfo.x[i], {'unit':datainfo.x_unit})
+            if len(datainfo.y)>=i:
+                write_node(doc, pt, "I", datainfo.y[i],
+                            {'unit':datainfo.y_unit})
+            if datainfo.dx != None and len(datainfo.dx) >= i:
+                write_node(doc, pt, "Qdev", datainfo.dx[i],
+                            {'unit':datainfo.x_unit})
+            if datainfo.dxl != None and len(datainfo.dxl) >= i:
+                write_node(doc, pt, "dQl", datainfo.dxl[i],
+                            {'unit':datainfo.x_unit})    
+            if datainfo.dxw != None and len(datainfo.dxw) >= i:
+                write_node(doc, pt, "dQw", datainfo.dxw[i],
+                            {'unit':datainfo.x_unit})              
+            if datainfo.dy != None and len(datainfo.dy) >= i:
+                write_node(doc, pt, "Idev", datainfo.dy[i],
+                            {'unit':datainfo.y_unit})
+
+        
+        # Sample info
+        sample = doc.createElement("SASsample")
+        if datainfo.sample.name is not None:
+            sample.setAttribute("name", str(datainfo.sample.name))
+        entry_node.appendChild(sample)
+        write_node(doc, sample, "ID", str(datainfo.sample.ID))
+        write_node(doc, sample, "thickness", datainfo.sample.thickness,
+                   {"unit":datainfo.sample.thickness_unit})
+        write_node(doc, sample, "transmission", datainfo.sample.transmission)
+        write_node(doc, sample, "temperature", datainfo.sample.temperature,
+                   {"unit":datainfo.sample.temperature_unit})
+        
+        for item in datainfo.sample.details:
+            write_node(doc, sample, "details", item)
+        
+        pos = doc.createElement("position")
+        written = write_node(doc, pos, "x", datainfo.sample.position.x,
+                             {"unit":datainfo.sample.position_unit})
+        written = written | write_node(doc, pos, "y",
+                                       datainfo.sample.position.y,
+                                       {"unit":datainfo.sample.position_unit})
+        written = written | write_node(doc, pos, "z",
+                                       datainfo.sample.position.z,
+                                       {"unit":datainfo.sample.position_unit})
+        if written == True:
+            sample.appendChild(pos)
+        
+        ori = doc.createElement("orientation")
+        written = write_node(doc, ori, "roll",
+                             datainfo.sample.orientation.x,
+                             {"unit":datainfo.sample.orientation_unit})
+        written = written | write_node(doc, ori, "pitch",
+                                       datainfo.sample.orientation.y,
+                                    {"unit":datainfo.sample.orientation_unit})
+        written = written | write_node(doc, ori, "yaw",
+                                       datainfo.sample.orientation.z,
+                                    {"unit":datainfo.sample.orientation_unit})
+        if written == True:
+            sample.appendChild(ori)
+        
+        # Instrument info
+        instr = doc.createElement("SASinstrument")
+        entry_node.appendChild(instr)
+        
+        write_node(doc, instr, "name", datainfo.instrument)
+        
+        #   Source
+        source = doc.createElement("SASsource")
+        if datainfo.source.name is not None:
+            source.setAttribute("name", str(datainfo.source.name))
+        instr.appendChild(source)
+        
+        write_node(doc, source, "radiation", datainfo.source.radiation)
+        write_node(doc, source, "beam_shape", datainfo.source.beam_shape)
+        size = doc.createElement("beam_size")
+        if datainfo.source.beam_size_name is not None:
+            size.setAttribute("name", str(datainfo.source.beam_size_name))
+        written = write_node(doc, size, "x", datainfo.source.beam_size.x,
+                             {"unit":datainfo.source.beam_size_unit})
+        written = written | write_node(doc, size, "y",
+                                       datainfo.source.beam_size.y,
+                                       {"unit":datainfo.source.beam_size_unit})
+        written = written | write_node(doc, size, "z",
+                                       datainfo.source.beam_size.z,
+                                       {"unit":datainfo.source.beam_size_unit})
+        if written == True:
+            source.appendChild(size)
+            
+        write_node(doc, source, "wavelength",
+                   datainfo.source.wavelength,
+                   {"unit":datainfo.source.wavelength_unit})
+        write_node(doc, source, "wavelength_min",
+                   datainfo.source.wavelength_min,
+                   {"unit":datainfo.source.wavelength_min_unit})
+        write_node(doc, source, "wavelength_max",
+                   datainfo.source.wavelength_max,
+                   {"unit":datainfo.source.wavelength_max_unit})
+        write_node(doc, source, "wavelength_spread",
+                   datainfo.source.wavelength_spread,
+                   {"unit":datainfo.source.wavelength_spread_unit})
+        
+        #   Collimation
+        for item in datainfo.collimation:
+            coll = doc.createElement("SAScollimation")
+            if item.name is not None:
+                coll.setAttribute("name", str(item.name))
+            instr.appendChild(coll)
+            
+            write_node(doc, coll, "length", item.length,
+                       {"unit":item.length_unit})
+            
+            for apert in item.aperture:
+                ap = doc.createElement("aperture")
+                if apert.name is not None:
+                    ap.setAttribute("name", str(apert.name))
+                if apert.type is not None:
+                    ap.setAttribute("type", str(apert.type))
+                coll.appendChild(ap)
+                
+                write_node(doc, ap, "distance", apert.distance,
+                           {"unit":apert.distance_unit})
+                
+                size = doc.createElement("size")
+                if apert.size_name is not None:
+                    size.setAttribute("name", str(apert.size_name))
+                written = write_node(doc, size, "x", apert.size.x,
+                                     {"unit":apert.size_unit})
+                written = written | write_node(doc, size, "y", apert.size.y,
+                                               {"unit":apert.size_unit})
+                written = written | write_node(doc, size, "z", apert.size.z,
+                                               {"unit":apert.size_unit})
+                if written == True:
+                    ap.appendChild(size)
+
+        #   Detectors
+        for item in datainfo.detector:
+            det = doc.createElement("SASdetector")
+            written = write_node(doc, det, "name", item.name)
+            written = written | write_node(doc, det, "SDD", item.distance,
+                                           {"unit":item.distance_unit})
+            written = written | write_node(doc, det, "slit_length",
+                                           item.slit_length,
+                                           {"unit":item.slit_length_unit})
+            if written == True:
+                instr.appendChild(det)
+            
+            off = doc.createElement("offset")
+            written = write_node(doc, off, "x", item.offset.x,
+                                 {"unit":item.offset_unit})
+            written = written | write_node(doc, off, "y", item.offset.y,
+                                           {"unit":item.offset_unit})
+            written = written | write_node(doc, off, "z", item.offset.z,
+                                           {"unit":item.offset_unit})
+            if written == True:
+                det.appendChild(off)
+            
+            center = doc.createElement("beam_center")
+            written = write_node(doc, center, "x", item.beam_center.x,
+                                 {"unit":item.beam_center_unit})
+            written = written | write_node(doc, center, "y",
+                                           item.beam_center.y,
+                                           {"unit":item.beam_center_unit})
+            written = written | write_node(doc, center, "z",
+                                           item.beam_center.z,
+                                           {"unit":item.beam_center_unit})
+            if written == True:
+                det.appendChild(center)
+                
+            pix = doc.createElement("pixel_size")
+            written = write_node(doc, pix, "x", item.pixel_size.x,
+                                 {"unit":item.pixel_size_unit})
+            written = written | write_node(doc, pix, "y", item.pixel_size.y,
+                                           {"unit":item.pixel_size_unit})
+            written = written | write_node(doc, pix, "z", item.pixel_size.z,
+                                           {"unit":item.pixel_size_unit})
+            if written == True:
+                det.appendChild(pix)
+                
+            ori = doc.createElement("orientation")
+            written = write_node(doc, ori, "roll",  item.orientation.x,
+                                 {"unit":item.orientation_unit})
+            written = written | write_node(doc, ori, "pitch",
+                                           item.orientation.y,
+                                           {"unit":item.orientation_unit})
+            written = written | write_node(doc, ori, "yaw",
+                                           item.orientation.z,
+                                           {"unit":item.orientation_unit})
+            if written == True:
+                det.appendChild(ori)
+                
+        
+        # Processes info
+        for item in datainfo.process:
+            node = doc.createElement("SASprocess")
+            entry_node.appendChild(node)
+
+            write_node(doc, node, "name", item.name)
+            write_node(doc, node, "date", item.date)
+            write_node(doc, node, "description", item.description)
+            for term in item.term:
+                value = term['value']
+                del term['value']
+                write_node(doc, node, "term", value, term)
+            for note in item.notes:
+                write_node(doc, node, "SASprocessnote", note)
+        
+        # Return the document, and the SASentry node associated with
+        # the data we just wrote
+        return doc, entry_node
+            
+    def write(self, filename, datainfo):
+        """
+        Write the content of a Data1D as a CanSAS XML file
+        
+        :param filename: name of the file to write
+        :param datainfo: Data1D object
+        """
+        # Create XML document
+        doc, sasentry = self._to_xml_doc(datainfo)
+        # Write the file
+        fd = open(filename, 'w')
+        fd.write(doc.toprettyxml())
+        fd.close()
+        
+    def _store_float(self, location, node, variable, storage, optional=True):
+        """
+        Get the content of a xpath location and store
+        the result. Check that the units are compatible
+        with the destination. The value is expected to
+        be a float.
+        
+        The xpath location might or might not exist.
+        If it does not exist, nothing is done
+        
+        :param location: xpath location to fetch
+        :param node: node to read the data from
+        :param variable: name of the data member to store it in [string]
+        :param storage: data object that has the 'variable' data member
+        :param optional: if True, no exception will be raised 
+            if unit conversion can't be done
+
+        :raise ValueError: raised when the units are not recognized
+        """
+        entry = get_content(location, node)
+        try:
+            value = float(entry.text)
+        except:
+            value = None
+            
+        if value is not None:
+            # If the entry has units, check to see that they are
+            # compatible with what we currently have in the data object
+            units = entry.get('unit')
+            if units is not None:
+                toks = variable.split('.')
+                exec "local_unit = storage.%s_unit" % toks[0]
+                if units.lower()!=local_unit.lower():
+                    if has_converter==True:
+                        try:
+                            conv = Converter(units)
+                            exec "storage.%s = %g" % (variable,
+                                            conv(value, units=local_unit))
+                        except:
+                            err_mess = "CanSAS reader: could not convert"
+                            err_mess += " %s unit [%s]; expecting [%s]\n  %s" \
+                                % (variable, units, local_unit, sys.exc_value)
+                            self.errors.append(err_mess)
+                            if optional:
+                                logging.info(err_mess)
+                            else:
+                                raise ValueError, err_mess 
+                    else:
+                        err_mess = "CanSAS reader: unrecognized %s unit [%s];"
+                        err_mess += " expecting [%s]" % (variable, 
+                                                         units, local_unit)
+                        self.errors.append(err_mess)
+                        if optional:
+                            logging.info(err_mess)
+                        else:
+                            raise ValueError, err_mess
+                else:
+                    exec "storage.%s = value" % variable
+            else:
+                exec "storage.%s = value" % variable
+                
+    def _store_content(self, location, node, variable, storage):
+        """
+        Get the content of a xpath location and store
+        the result. The value is treated as a string.
+        
+        The xpath location might or might not exist.
+        If it does not exist, nothing is done
+        
+        :param location: xpath location to fetch
+        :param node: node to read the data from
+        :param variable: name of the data member to store it in [string]
+        :param storage: data object that has the 'variable' data member
+        
+        :return: return a list of errors
+        """
+        entry = get_content(location, node)
+        if entry is not None and entry.text is not None:
+            exec "storage.%s = entry.text.strip()" % variable
+
+            
+            
+if __name__ == "__main__": 
+    logging.basicConfig(level=logging.ERROR,
+                        format='%(asctime)s %(levelname)s %(message)s',
+                        filename='cansas_reader.log',
+                        filemode='w')
+    reader = Reader()
+    print reader.read("../test/cansas1d.xml")
+    #print reader.read("../test/latex_smeared.xml")
+    
+    
+                        
Index: sansdataloader/src/sans/dataloader/readers/danse_reader.py
===================================================================
--- sansdataloader/src/sans/dataloader/readers/danse_reader.py	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
+++ sansdataloader/src/sans/dataloader/readers/danse_reader.py	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
@@ -0,0 +1,292 @@
+
+
+############################################################################
+#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
+#############################################################################
+
+"""
+    DANSE/SANS file reader
+"""
+
+import math
+import os
+#import copy
+import numpy
+import logging
+from DataLoader.data_info import Data2D, Detector
+from DataLoader.manipulations import reader2D_converter
+
+# Look for unit converter
+has_converter = True
+try:
+    from data_util.nxsunit import Converter
+except:
+    has_converter = False
+
+class Reader:
+    """
+    Example data manipulation
+    """
+    ## File type
+    type_name = "DANSE"   
+    ## Wildcards
+    type = ["DANSE files (*.sans)|*.sans"]
+    ## Extension
+    ext  = ['.sans', '.SANS']    
+        
+    def read(self, filename=None):
+        """
+        Open and read the data in a file
+        @param file: path of the file
+        """
+        
+        read_it = False
+        for item in self.ext:
+            if filename.lower().find(item) >= 0:
+                read_it = True
+                
+        if read_it:
+            try:
+                datafile = open(filename, 'r')
+            except :
+                raise  RuntimeError,"danse_reader cannot open %s" % (filename)
+        
+            # defaults
+            # wavelength in Angstrom
+            wavelength = 10.0
+            # Distance in meter
+            distance   = 11.0
+            # Pixel number of center in x
+            center_x   = 65
+            # Pixel number of center in y
+            center_y   = 65
+            # Pixel size [mm]
+            pixel      = 5.0
+            # Size in x, in pixels
+            size_x     = 128
+            # Size in y, in pixels
+            size_y     = 128
+            # Format version
+            fversion   = 1.0
+            
+            output = Data2D()
+            output.filename = os.path.basename(filename)
+            detector = Detector()
+            output.detector.append(detector)
+            
+            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)            
+        
+            read_on = True
+            while read_on:
+                line = datafile.readline()
+                if line.find("DATA:") >= 0:
+                    read_on = False
+                    break
+                toks = line.split(':')
+                if toks[0] == "FORMATVERSION":
+                    fversion = float(toks[1])
+                if toks[0] == "WAVELENGTH":    
+                    wavelength = float(toks[1])                
+                elif toks[0] == "DISTANCE":
+                    distance = float(toks[1])
+                elif toks[0] == "CENTER_X":
+                    center_x = float(toks[1])
+                elif toks[0] == "CENTER_Y":
+                    center_y = float(toks[1])
+                elif toks[0] == "PIXELSIZE":
+                    pixel = float(toks[1])
+                elif toks[0] == "SIZE_X":
+                    size_x = int(toks[1])
+                elif toks[0] == "SIZE_Y":
+                    size_y = int(toks[1])
+            
+            # Read the data
+            data = []
+            error = []
+            if fversion == 1.0:
+                data_str = datafile.readline()
+                data = data_str.split(' ')
+            else:
+                read_on = True
+                while read_on:
+                    data_str = datafile.readline()
+                    if len(data_str) == 0:
+                        read_on = False
+                    else:
+                        toks = data_str.split()
+                        try:
+                            val = float(toks[0])
+                            err = float(toks[1])
+                            if data_conv_i is not None:
+                                val = data_conv_i(val, units=output.y_unit)
+                                err = data_conv_i(err, units=output.y_unit)
+                            data.append(val)
+                            error.append(err)
+                        except:
+                            logging.info("Skipping line:%s,%s" %( data_str,
+                                                                sys.exc_value))
+            
+            # Initialize 
+            x_vals = []
+            y_vals = [] 
+            ymin = None
+            ymax = None
+            xmin = None
+            xmax = None
+            
+            # Qx and Qy vectors
+            theta = pixel / distance / 100.0
+            stepq = 4.0 * math.pi/wavelength * math.sin(theta/2.0) 
+            for i_x in range(size_x):
+                theta = (i_x - center_x + 1) * pixel / 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)
+                
+                x_vals.append(qx)
+                if xmin == None or qx < xmin:
+                    xmin = qx
+                if xmax == None or qx > xmax:
+                    xmax = qx
+            
+            ymin = None
+            ymax = None
+            for i_y in range(size_y):
+                theta = (i_y - center_y + 1) * pixel / 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)
+                
+                y_vals.append(qy)
+                if ymin == None or qy < ymin:
+                    ymin = qy
+                if ymax == None or qy > ymax:
+                    ymax = qy
+            
+            # Store the data in the 2D array
+            itot = 0
+            i_x  = 0
+            i_y  = -1
+            
+            for i_pt in range(len(data)):
+                try:
+                    value = float(data[i_pt])
+                except:
+                    # For version 1.0, the data were still
+                    # stored as strings at this point.
+                    msg = "Skipping entry (v1.0):%s,%s" %(str(data[i_pt]),
+                                                           sys.exc_value)
+                    logging.info(msg)
+                
+                # Get bin number
+                if math.fmod(i_pt, size_x) == 0:
+                    i_x = 0
+                    i_y += 1
+                else:
+                    i_x += 1
+                    
+                output.data[i_y][i_x] = value       
+                #output.data[size_y-1-i_y][i_x] = value
+                if fversion>1.0:
+                    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 
+            # 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 pixel size
+            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 - stepq / 2.0
+            xmax = xmax + stepq / 2.0
+            ymin = ymin - stepq  /2.0
+            ymax = ymax + stepq / 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_vals
+            output.y_bins     = y_vals
+           
+            # Units
+            if data_conv_q is not None:
+                output.xaxis("\\rm{Q_{x}}", output.Q_unit)
+                output.yaxis("\\rm{Q_{y}}", output.Q_unit)
+            else:
+                output.xaxis("\\rm{Q_{x}}", 'A^{-1}')
+                output.yaxis("\\rm{Q_{y}}", 'A^{-1}')
+                
+            if data_conv_i is not None:
+                output.zaxis("\\rm{Intensity}", output.I_unit)
+            else:
+                output.zaxis("\\rm{Intensity}","cm^{-1}")
+           
+            if not fversion >= 1.0:
+                msg = "Danse_reader can't read this file %s" % filename
+                raise ValueError, msg
+            else:
+                logging.info("Danse_reader Reading %s \n" % filename)
+            
+            # Store loading process information
+            output.meta_data['loader'] = self.type_name    
+            output = reader2D_converter(output)
+            return output
+        
+        return None
+
+if __name__ == "__main__": 
+    reader = Reader()
+    print reader.read("../test/MP_New.sans")
+    
Index: sansdataloader/src/sans/dataloader/readers/defaults.xml
===================================================================
--- sansdataloader/src/sans/dataloader/readers/defaults.xml	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
+++ sansdataloader/src/sans/dataloader/readers/defaults.xml	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<SansLoader version="1.0"
+    xmlns="sansloader/1.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    >
+	
+	<FileType extension='.xml' reader='cansas_reader'/>
+	<FileType extension='.asc' reader='IgorReader'/>
+	<FileType extension='.dat' reader='red2d_reader'/>
+	<FileType extension='.tif' reader='tiff_reader'/>
+	<FileType extension='.tiff' reader='tiff_reader'/>
+	<FileType extension='.sans' reader='danse_reader'/>
+    
+</SansLoader>
+
Index: sansdataloader/src/sans/dataloader/readers/hfir1d_reader.py
===================================================================
--- sansdataloader/src/sans/dataloader/readers/hfir1d_reader.py	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
+++ sansdataloader/src/sans/dataloader/readers/hfir1d_reader.py	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
@@ -0,0 +1,136 @@
+
+#####################################################################
+#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. 
+#See the license text in license.txt
+#copyright 2008, University of Tennessee
+######################################################################
+
+import numpy
+import os
+from DataLoader.data_info import Data1D
+
+# Check whether we have a converter available
+has_converter = True
+try:
+    from data_util.nxsunit import Converter
+except:
+    has_converter = False
+
+class Reader(object):
+    """
+    Class to load HFIR 1D 4-column files
+    """
+    ## File type
+    type_name = "HFIR 1D"   
+    ## Wildcards
+    type = ["HFIR 1D files (*.d1d)|*.d1d"]
+    ## List of allowed extensions
+    ext = ['.d1d']  
+    
+    def read(self, path):
+        """ 
+        Load data file
+        
+        :param path: file path
+        
+        :return: Data1D object, or None
+        
+        :raise RuntimeError: when the file can't be opened
+        :raise ValueError: when the length of the data vectors are inconsistent
+        """
+        if os.path.isfile(path):
+            basename  = os.path.basename(path)
+            root, extension = os.path.splitext(basename)
+            if extension.lower() in self.ext:
+                try:
+                    input_f =  open(path,'r')
+                except :
+                    raise  RuntimeError, "hfir1d_reader: cannot open %s" % path
+                buff = input_f.read()
+                lines = buff.split('\n')
+                x  = numpy.zeros(0)
+                y  = numpy.zeros(0)
+                dx = numpy.zeros(0)
+                dy = numpy.zeros(0)
+                output = Data1D(x, y, dx=dx, dy=dy)
+                self.filename = output.filename = basename
+           
+                data_conv_q = None
+                data_conv_i = None
+                
+                if has_converter == True and output.x_unit != '1/A':
+                    data_conv_q = Converter('1/A')
+                    # Test it
+                    data_conv_q(1.0, output.x_unit)
+                    
+                if has_converter == True and output.y_unit != '1/cm':
+                    data_conv_i = Converter('1/cm')
+                    # Test it
+                    data_conv_i(1.0, output.y_unit)
+                           
+                for line in lines:
+                    toks = line.split()
+                    try:
+                        _x = float(toks[0])
+                        _y = float(toks[1])
+                        _dx = float(toks[3])
+                        _dy = float(toks[2])
+                        
+                        if data_conv_q is not None:
+                            _x = data_conv_q(_x, units=output.x_unit)
+                            _dx = data_conv_q(_dx, units=output.x_unit)
+                            
+                        if data_conv_i is not None:
+                            _y = data_conv_i(_y, units=output.y_unit)                        
+                            _dy = data_conv_i(_dy, units=output.y_unit)                        
+                                                    
+                        x   = numpy.append(x, _x) 
+                        y   = numpy.append(y, _y)
+                        dx  = numpy.append(dx, _dx)
+                        dy  = numpy.append(dy, _dy)                        
+                    except:
+                        # Couldn't parse this line, skip it 
+                        pass
+                         
+                     
+                # Sanity check
+                if not len(y) == len(dy):
+                    msg = "hfir1d_reader: y and dy have different length"
+                    raise RuntimeError, msg
+                if not len(x) == len(dx):
+                    msg = "hfir1d_reader: x and dx have different length"
+                    raise RuntimeError, msg
+
+                # If the data length is zero, consider this as
+                # though we were not able to read the file.
+                if len(x) == 0:
+                    raise RuntimeError, "hfir1d_reader: could not load file"
+               
+                output.x = x
+                output.y = y
+                output.dy = dy
+                output.dx = dx
+                if data_conv_q is not None:
+                    output.xaxis("\\rm{Q}", output.x_unit)
+                else:
+                    output.xaxis("\\rm{Q}", 'A^{-1}')
+                if data_conv_i is not None:
+                    output.yaxis("\\rm{Intensity}", output.y_unit)
+                else:
+                    output.yaxis("\\rm{Intensity}","cm^{-1}")
+                
+                # Store loading process information
+                output.meta_data['loader'] = self.type_name   
+                return output
+        else:
+            raise RuntimeError, "%s is not a file" % path
+        return None
+    
+if __name__ == "__main__": 
+    reader = Reader()
+    print reader.read("../test/S2-30dq.d1d")
+    
+    
+                        
Index: sansdataloader/src/sans/dataloader/readers/red2d_reader.py
===================================================================
--- sansdataloader/src/sans/dataloader/readers/red2d_reader.py	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
+++ sansdataloader/src/sans/dataloader/readers/red2d_reader.py	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
@@ -0,0 +1,379 @@
+
+#####################################################################
+#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. 
+#See the license text in license.txt
+#copyright 2008, University of Tennessee
+######################################################################
+
+"""
+    TXT/IGOR 2D Q Map file reader
+"""
+
+
+import os
+#import sys
+import numpy
+import math
+#import 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
+    
+def check_point(x_point):
+    """
+    check point validity
+    """
+    # set zero for non_floats
+    try:
+        return float(x_point)
+    except:
+        return 0
+        
+class Reader:
+    """ Simple data reader for Igor data files """
+    ## File type
+    type_name = "IGOR/DAT 2D Q_map"   
+    ## Wildcards
+    type = ["IGOR/DAT 2D file in Q_map (*.dat)|*.DAT"]
+    ## Extension
+    ext=['.DAT', '.dat']
+    
+    def write(self, filename, data):
+        """
+        Write to .dat
+        
+        :param filename: file name to write
+        :param data: data2D 
+        """
+        import time
+        st = time.time()
+        # Write the file
+        fd = open(filename, 'w')
+        t = time.localtime()
+        time_str = time.strftime("%H:%M on %b %d %y", t)
+        
+        header_str = "Data columns are Qx - Qy - I(Qx,Qy)\n\nASCII data"
+        header_str += " created at %s \n\n" % time_str
+        # simple 2D header
+        fd.write(header_str)
+        # write qx qy I values
+        for i in range(len(data.data)):
+            fd.write("%g  %g  %g\n" % (data.qx_data[i], 
+                                        data.qy_data[i],
+                                       data.data[i]))
+        # close
+        fd.close()                 
+
+    def read(self,filename=None):
+        """ Read file """
+        if not os.path.isfile(filename):
+            raise ValueError, \
+            "Specified file %s is not a regular file" % filename
+
+        # Read file
+        f = open(filename,'r')
+        buf = f.read()
+        f.close()     
+        # 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)
+                
+        # Get content
+        dataStarted = False
+        
+        ## Defaults      
+        lines = buf.split('\n')
+        itot = 0
+        x = []
+        y = []
+        
+        ncounts = 0
+        
+        wavelength   = None
+        distance     = None
+        transmission = None
+        
+        pixel_x = None
+        pixel_y = None
+        
+        i_x    = 0
+        i_y    = -1
+        pixels = 0
+        
+        isInfo   = False
+        isCenter = False
+
+        data_conv_q = None
+        data_conv_i = None
+        
+        # Set units: This is the unit assumed for Q and I in the data file.
+        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)            
+        
+              
+        # Remove the last lines before the for loop if the lines are empty
+        # to calculate the exact number of data points
+        count = 0
+        while (len(lines[len(lines)-(count+1)].lstrip().rstrip()) < 1):
+            del lines[len(lines)-(count+1)]
+            count = count + 1
+
+        #Read Header and find the dimensions of 2D data
+        line_num = 0
+        # Old version NIST files: 0
+        ver = 0
+        for line in lines:      
+            line_num += 1
+            ## Reading the header applies only to IGOR/NIST 2D q_map data files
+            # Find setup info line
+            if isInfo:
+                isInfo = False
+                line_toks = line.split()
+                # Wavelength in Angstrom
+                try:
+                    wavelength = float(line_toks[1])
+                    # Units
+                    if has_converter == True and \
+                    output.source.wavelength_unit != 'A':
+                        conv = Converter('A')
+                        wavelength = conv(wavelength,
+                                          units=output.source.wavelength_unit)
+                except:
+                    #Not required
+                    pass
+                # Distance in mm
+                try:
+                    distance = float(line_toks[3])
+                    # Units
+                    if has_converter == True and detector.distance_unit != 'm':
+                        conv = Converter('m')
+                        distance = conv(distance, units=detector.distance_unit)
+                except:
+                    #Not required
+                    pass
+                
+                # Distance in meters
+                try:
+                    transmission = float(line_toks[4])
+                except:
+                    #Not required
+                    pass
+                                            
+            if line.count("LAMBDA") > 0:
+                isInfo = True
+                
+            # Find center info line
+            if isCenter:
+                isCenter = False                
+                line_toks = line.split()
+                # Center in bin number
+                center_x = float(line_toks[0])
+                center_y = float(line_toks[1])
+
+            if line.count("BCENT") > 0:
+                isCenter = True
+            # Check version
+            if line.count("Data columns") > 0:
+                if line.count("err(I)") > 0:
+                    ver = 1
+            # Find data start
+            if line.count("ASCII data") > 0:
+                dataStarted = True
+                continue
+
+            ## Read and get data.   
+            if dataStarted == True:
+                line_toks = line.split()              
+                if len(line_toks) == 0:
+                    #empty line
+                    continue
+                # the number of columns must be stayed same 
+                col_num = len(line_toks)
+                break
+        # Make numpy array to remove header lines using index
+        lines_array = numpy.array(lines)
+
+        # index for lines_array
+        lines_index = numpy.arange(len(lines))
+        
+        # get the data lines
+        data_lines = lines_array[lines_index >= (line_num - 1)]
+        # Now we get the total number of rows (i.e., # of data points)
+        row_num = len(data_lines)
+        # make it as list again to control the separators
+        data_list = " ".join(data_lines.tolist())
+        # split all data to one big list w/" "separator
+        data_list = data_list.split()
+ 
+        # Check if the size is consistent with data, otherwise 
+        #try the tab(\t) separator
+        # (this may be removed once get the confidence 
+        #the former working all cases).
+        if len(data_list) != (len(data_lines)) * col_num:
+            data_list = "\t".join(data_lines.tolist())
+            data_list = data_list.split()
+
+        # Change it(string) into float
+        #data_list = map(float,data_list)
+        data_list1 = map(check_point,data_list)
+
+        # numpy array form
+        data_array = numpy.array(data_list1)
+        # Redimesion based on the row_num and col_num, 
+        #otherwise raise an error.
+        try:
+            data_point = data_array.reshape(row_num, col_num).transpose()
+        except:
+            msg = "red2d_reader: Can't read this file: Not a proper file format"
+            raise ValueError, msg
+        ## Get the all data: Let's HARDcoding; Todo find better way
+        # Defaults
+        dqx_data = numpy.zeros(0)
+        dqy_data = numpy.zeros(0)
+        err_data = numpy.ones(row_num)
+        qz_data = numpy.zeros(row_num)
+        mask = numpy.ones(row_num,dtype=bool)
+        # Get from the array
+        qx_data = data_point[0]
+        qy_data = data_point[1]
+        data = data_point[2]
+        if ver == 1:
+            if col_num > (2 + ver): err_data = data_point[(2 + ver)]
+        if col_num > (3 + ver): qz_data = data_point[(3 + ver)]
+        if col_num > (4 + ver): dqx_data = data_point[(4 + ver)]
+        if col_num > (5 + ver): dqy_data = data_point[(5 + ver)]
+        #if col_num > (6 + ver): mask[data_point[(6 + ver)] < 1] = False
+        q_data = numpy.sqrt(qx_data*qx_data+qy_data*qy_data+qz_data*qz_data)
+           
+        # Extra protection(it is needed for some data files): 
+        # If all mask elements are False, put all True
+        if not mask.any(): mask[mask==False] = True   
+  
+        # Store limits of the image in q space
+        xmin    = numpy.min(qx_data)
+        xmax    = numpy.max(qx_data)
+        ymin    = numpy.min(qy_data)
+        ymax    = numpy.max(qy_data)
+
+        # units
+        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)
+            
+        ## calculate the range of the qx and qy_data
+        x_size = math.fabs(xmax - xmin)
+        y_size = math.fabs(ymax - ymin)
+        
+        # calculate the number of pixels in the each axes
+        npix_y = math.floor(math.sqrt(len(data)))
+        npix_x = math.floor(len(data)/npix_y)
+        
+        # calculate the size of bins      
+        xstep = x_size/(npix_x-1)
+        ystep = y_size/(npix_y-1)
+        
+        # store x and y axis bin centers in q space
+        x_bins  = numpy.arange(xmin,xmax+xstep,xstep)
+        y_bins  = numpy.arange(ymin,ymax+ystep,ystep)
+       
+        # get the limits of q values
+        xmin = xmin - xstep/2
+        xmax = xmax + xstep/2
+        ymin = ymin - ystep/2
+        ymax = ymax + ystep/2
+        
+        #Store data in outputs  
+        #TODO: Check the lengths 
+        output.data     = data
+        if (err_data == 1).all():
+            output.err_data = numpy.sqrt(numpy.abs(data))
+            output.err_data[output.err_data == 0.0] = 1.0
+        else:
+            output.err_data = err_data
+            
+        output.qx_data  = qx_data
+        output.qy_data  = qy_data             
+        output.q_data   = q_data
+        output.mask     = mask 
+        
+        output.x_bins = x_bins
+        output.y_bins = y_bins
+               
+        output.xmin = xmin
+        output.xmax = xmax
+        output.ymin = ymin
+        output.ymax = ymax
+        
+        output.source.wavelength = wavelength
+        
+        # Store pixel size in mm
+        detector.pixel_size.x = pixel_x
+        detector.pixel_size.y = pixel_y
+        
+        # Store the sample to detector distance
+        detector.distance = distance
+        
+        # optional data: if all of dq data == 0, do not pass to output
+        if len(dqx_data) == len(qx_data) and dqx_data.any()!=0: 
+            # if no dqx_data, do not pass dqy_data.
+            #(1 axis dq is not supported yet).
+            if len(dqy_data) == len(qy_data) and dqy_data.any()!=0:
+                # Currently we do not support dq parr, perp.
+                # tranfer the comp. to cartesian coord. for newer version.
+                if ver != 1:
+                    diag = numpy.sqrt(qx_data * qx_data + qy_data * qy_data)
+                    cos_th = qx_data / diag
+                    sin_th = qy_data / diag
+                    output.dqx_data = numpy.sqrt((dqx_data * cos_th) * \
+                                                 (dqx_data * cos_th) \
+                                                 + ( dqy_data * sin_th) * \
+                                                  ( dqy_data * sin_th))
+                    output.dqy_data = numpy.sqrt((dqx_data * sin_th) * \
+                                                 (dqx_data * sin_th) \
+                                                 + ( dqy_data * cos_th) * \
+                                                  ( dqy_data * cos_th))
+                else:
+                    output.dqx_data = dqx_data
+                    output.dqy_data = dqy_data
+
+        # Units of axes
+        if data_conv_q is not None:
+            output.xaxis("\\rm{Q_{x}}", output.Q_unit)
+            output.yaxis("\\rm{Q_{y}}", output.Q_unit)
+        else:
+            output.xaxis("\\rm{Q_{x}}", 'A^{-1}')
+            output.yaxis("\\rm{Q_{y}}", 'A^{-1}')            
+        if data_conv_i is not None:
+            output.zaxis("\\rm{Intensity}", output.I_unit)
+        else:
+            output.zaxis("\\rm{Intensity}","cm^{-1}")
+    
+        # Store loading process information
+        output.meta_data['loader'] = self.type_name
+
+        return output
+    
+if __name__ == "__main__": 
+    reader = Reader()
+    print reader.read("../test/exp18_14_igor_2dqxqy.dat") 
+        
+
Index: sansdataloader/src/sans/dataloader/readers/tiff_reader.py
===================================================================
--- sansdataloader/src/sans/dataloader/readers/tiff_reader.py	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
+++ sansdataloader/src/sans/dataloader/readers/tiff_reader.py	(revision 8e165f9eb8bcd342bc7f84242bf0240ffadc1bad)
@@ -0,0 +1,109 @@
+
+
+#####################################################################
+#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. 
+#See the license text in license.txt
+#copyright 2008, University of Tennessee
+######################################################################
+"""
+    Image reader. Untested. 
+"""
+
+
+#TODO: load and check data and orientation of the image (needs rendering)
+
+import math, logging, os
+import numpy
+from DataLoader.data_info import Data2D
+    
+class Reader:
+    """
+    Example data manipulation
+    """
+    ## File type
+    type_name = "TIF"   
+    ## Wildcards
+    type = ["TIF files (*.tif)|*.tif",
+            "TIFF files (*.tiff)|*.tiff",
+            ]
+    ## Extension
+    ext  = ['.tif', '.tiff']    
+        
+    def read(self, filename=None):
+        """
+        Open and read the data in a file
+        
+        :param file: path of the file
+        """
+        try:
+            import Image
+        except:
+            msg = "tiff_reader: could not load file. Missing Image module."
+            raise RuntimeError, msg
+        
+        # Instantiate data object
+        output = Data2D()
+        output.filename = os.path.basename(filename)
+            
+        # Read in the image
+        try:
+            im = Image.open(filename)
+        except :
+            raise  RuntimeError,"cannot open %s"%(filename)
+        data = im.getdata()
+
+        # Initiazed the output data object
+        output.data = numpy.zeros([im.size[0],im.size[1]])
+        output.err_data = numpy.zeros([im.size[0],im.size[1]])
+        
+        # Initialize 
+        x_vals = []
+        y_vals = [] 
+
+        # x and y vectors
+        for i_x in range(im.size[0]):
+            x_vals.append(i_x)
+            
+        itot = 0
+        for i_y in range(im.size[1]):
+            y_vals.append(i_y)
+
+        for val in data:
+            try:
+                value = float(val)
+            except:
+                logging.error("tiff_reader: had to skip a non-float point")
+                continue
+            
+            # Get bin number
+            if math.fmod(itot, im.size[0])==0:
+                i_x = 0
+                i_y += 1
+            else:
+                i_x += 1
+                
+            output.data[im.size[1]-1-i_y][i_x] = value
+            
+            itot += 1
+                
+        output.xbins      = im.size[0]
+        output.ybins      = im.size[1]
+        output.x_bins     = x_vals
+        output.y_bins     = y_vals
+        output.xmin       = 0
+        output.xmax       = im.size[0]-1
+        output.ymin       = 0
+        output.ymax       = im.size[0]-1
+        
+        # Store loading process information
+        output.meta_data['loader'] = self.type_name 
+        return output
+        
+
+if __name__ == "__main__": 
+    reader = Reader()
+    print reader.read("../test/MP_New.sans")
+    
+
