Index: DataLoader/data_info.py
===================================================================
--- DataLoader/data_info.py	(revision a3084adadd2dd25fa3b12dc2dff6c6aee06d4a82)
+++ DataLoader/data_info.py	(revision 8780e9a7e98f59c06b1819f1e068b7e84f496efc)
@@ -21,4 +21,14 @@
 from sans.guitools.plottables import Data1D as plottable_1D
 
+class Data2D:
+    """
+        Data2D is a place holder for 2D plottables, which are 
+        not yet implemented.
+    """
+    xmin = None
+    xmax = None
+    ymin = None
+    ymax = None
+    image = None
   
 class Vector:
@@ -58,14 +68,37 @@
     ## Sample to detector distance [float] [mm]
     distance = None
+    distance_unit = 'm'
     ## Offset of this detector position in X, Y, (and Z if necessary) [Vector] [mm] 
     offset = Vector()
+    offset_unit = 'mm'
     ## Orientation (rotation) of this detector in roll, pitch, and yaw [Vector] [degrees]
     orientation = Vector()
+    orientation_unit = 'degree'
     ## Center of the beam on the detector in X and Y (and Z if necessary) [Vector] [pixel]
     beam_center = Vector()
+    beam_center_unit = 'mm'
     ## Pixel size in X, Y, (and Z if necessary) [Vector] [mm]
     pixel_size = Vector()
+    pixel_size_unit = 'mm'
     ## Slit length of the instrument for this detector.[float] [mm]
     slit_length = None
+    slit_length_unit = 'mm'
+    
+    def __str__(self):
+        _str  = "Detector:\n"
+        _str += "   Name:         %s\n" % self.name
+        _str += "   Distance:     %s [%s]\n" % \
+            (str(self.distance), str(self.distance_unit))
+        _str += "   Offset:       %s [%s]\n" % \
+            (str(self.offset), str(self.offset_unit))
+        _str += "   Orientation:  %s [%s]\n" % \
+            (str(self.orientation), str(self.orientation_unit))
+        _str += "   Beam center:  %s [%s]\n" % \
+            (str(self.beam_center), str(self.beam_center_unit))
+        _str += "   Pixel size:   %s [%s]\n" % \
+            (str(self.pixel_size), str(self.pixel_size_unit))
+        _str += "   Slit length:  %s [%s]\n" % \
+            (str(self.slit_length), str(self.slit_length_unit))
+        return _str
 
 class Collimation:
@@ -73,10 +106,28 @@
         Class to hold collimation information
     """
+    class Aperture:
+        # Aperture size [Vector]
+        size = Vector()
+        size_unit = 'mm'
+        # Aperture distance [float]
+        distance = None
+        distance_unit = 'mm'
+    
     ## Length [float] [mm]
     length = None
-    ## Aperture size [Vector] [mm]
-    aperture_size = Vector()
-    ## Aperture distance [float] [m]
-    aperture_distance = None
+    length_unit = 'mm'
+    ## Aperture
+    aperture = []
+    
+    def __str__(self):
+        _str = "Collimation:\n"
+        _str += "   Length:       %s [%s]\n" % \
+            (str(self.length), str(self.length_unit))
+        for item in self.aperture:
+            _str += "   Aperture size:%s [%s]\n" % \
+                (str(item.size), str(item.size_unit))
+            _str += "   Aperture_dist:%s [%s]\n" % \
+                (str(item.distance), str(item.distance_unit))
+        return _str
 
 class Source:
@@ -88,14 +139,36 @@
     ## Beam size [Vector] [mm]
     beam_size = Vector()
+    beam_size_unit = 'mm'
     ## Beam shape [string]
     beam_shape = ''
     ## Wavelength [float] [Angstrom]
     wavelength = None
+    wavelength_unit = 'A'
     ## Minimum wavelength [float] [Angstrom]
     wavelength_min = None
+    wavelength_min_unit = 'nm'
     ## Maximum wavelength [float] [Angstrom]
     wavelength_max = None
+    wavelength_max_unit = 'nm'
     ## Wavelength spread [float] [Angstrom]
     wavelength_spread = None
+    wavelength_spread_unit = 'percent'
+    
+    def __str__(self):
+        _str  = "Source:\n"
+        _str += "   Radiation:    %s\n" % str(self.radiation)
+        _str += "   Shape:        %s\n" % str(self.beam_shape)
+        _str += "   Wavelength:   %s [%s]\n" % \
+            (str(self.wavelength), str(self.wavelength_unit))
+        _str += "   Waveln_min:   %s [%s]\n" % \
+            (str(self.wavelength_min), str(self.wavelength_min_unit))
+        _str += "   Waveln_max:   %s [%s]\n" % \
+            (str(self.wavelength_max), str(self.wavelength_max_unit))
+        _str += "   Waveln_spread:%s [%s]\n" % \
+            (str(self.wavelength_spread), str(self.wavelength_spread_unit))
+        _str += "   Beam_size:    %s [%s]\n" % \
+            (str(self.beam_size), str(self.beam_size_unit))
+        return _str
+    
     
 """ 
@@ -115,14 +188,59 @@
     ## Thickness [float] [mm]
     thickness = None
-    ## Transmission [float] [%]
+    thickness_unit = 'mm'
+    ## Transmission [float] [fraction]
     transmission = None
     ## Temperature [float] [C]
     temperature = None
+    temperature_unit = 'C'
     ## Position [Vector] [mm]
     position = Vector()
+    position_unit = 'mm'
     ## Orientation [Vector] [degrees]
     orientation = Vector()
+    orientation_unit = 'degree'
     ## Details
-    details = ''
+    details = []
+    
+    def __str__(self):
+        _str  = "Sample:\n"
+        _str += "   ID:           %s\n" % str(self.ID)
+        _str += "   Transmission: %s\n" % str(self.transmission)
+        _str += "   Thickness:    %s [%s]\n" % \
+            (str(self.thickness), str(self.thickness_unit))
+        _str += "   Temperature:  %s [%s]\n" % \
+            (str(self.temperature), str(self.temperature_unit))
+        _str += "   Position:     %s [%s]\n" % \
+            (str(self.position), str(self.position_unit))
+        _str += "   Orientation:  %s [%s]\n" % \
+            (str(self.orientation), str(self.orientation_unit))
+        
+        _str += "   Details:\n"
+        for item in self.details:
+            _str += "      %s\n" % item
+            
+        return _str
+  
+class Process:
+    """
+        Class that holds information about the processes
+        performed on the data.
+    """
+    name = ''
+    date = ''
+    description= ''
+    term = []
+    notes = []
+    
+    def __str__(self):
+        _str  = "Process:\n"
+        _str += "   Name:         %s\n" % self.name
+        _str += "   Date:         %s\n" % self.date
+        _str += "   Description:  %s\n" % self.description
+        for item in self.term:
+            _str += "   Term:         %s\n" % item
+        for item in self.notes:
+            _str += "   Note:         %s\n" % item
+        return _str
     
   
@@ -134,4 +252,6 @@
         the data itself and any other meta data.
     """
+    ## Title 
+    title      = ''
     ## Run number
     run        = None
@@ -139,15 +259,21 @@
     filename   = ''
     ## Notes
-    notes      = ''
+    notes      = []
     ## Processes (Action on the data)
     process    = []
+    ## Instrument name
+    instrument = ''
     ## Detector information
-    detector   = Detector()
+    detector   = []
     ## Sample information
     sample     = Sample()
     ## Source information
     source     = Source()
+    ## Collimation information
+    collimation = []
     ## Additional meta-data
     meta_data  = {}
+    ## Loading errors
+    errors = []
     
     def __add__(self, data):
@@ -191,4 +317,7 @@
         1D data class
     """
+    x_unit = '1/A'
+    y_unit = '1/cm'
+    
     def __init__(self, x, y, dx=None, dy=None):
         plottable_1D.__init__(self, x, y, dx, dy)
@@ -198,17 +327,19 @@
             Nice printout
         """
-        _str = "File: %s\n" % self.filename
-        
-        _str += "Sample:\n"
-        _str += "   Transmission: %s\n" % str(self.sample.transmission)
-        _str += "   Thickness:    %s\n" % str(self.sample.thickness)
-        
-        _str += "Source:\n"
-        _str += "   Wavelength:   %s [A]\n" % str(self.source.wavelength)
-
-        _str += "Detector:\n"
-        _str += "   Name:         %s\n" % self.detector.name
-        _str += "   Distance:     %s [mm]\n" % str(self.detector.distance)
-        _str += "   Beam_center:  %s [pixel]\n" % str(self.detector.beam_center)
+        _str =  "File:            %s\n" % self.filename
+        _str += "Title:           %s\n" % self.title
+        _str += "Run:             %s\n" % str(self.run)
+        _str += "Instrument:      %s\n" % str(self.instrument)
+        _str += "%s\n" % str(self.sample)
+        _str += "%s\n" % str(self.source)
+        for item in self.detector:
+            _str += "%s\n" % str(item)
+        for item in self.collimation:
+            _str += "%s\n" % str(item)
+        for item in self.process:
+            _str += "%s\n" % str(item)
+        for item in self.notes:
+            _str += "%s\n" % str(item)
+        
         
         _str += "Data:\n"
Index: DataLoader/readers/abs_reader.py
===================================================================
--- DataLoader/readers/abs_reader.py	(revision 8bd8ea439767ebb5cd5480a4da37e8e080d4f3df)
+++ DataLoader/readers/abs_reader.py	(revision 8780e9a7e98f59c06b1819f1e068b7e84f496efc)
@@ -17,4 +17,6 @@
         Class to load IGOR reduced .ABS files
     """
+    ## File type
+    type = ["IGOR 1D files (*.abs)|*.abs"]
     ## List of allowed extensions
     ext=['.abs', '.ABS']  
Index: DataLoader/readers/ascii_reader.py
===================================================================
--- DataLoader/readers/ascii_reader.py	(revision 8bd8ea439767ebb5cd5480a4da37e8e080d4f3df)
+++ DataLoader/readers/ascii_reader.py	(revision 8780e9a7e98f59c06b1819f1e068b7e84f496efc)
@@ -17,4 +17,7 @@
         Class to load ascii files (2 or 3 columns)
     """
+    ## File type
+    type = ["ASCII files (*.txt)|*.txt",
+            "ASCII files (*.dat)|*.dat"]
     ## List of allowed extensions
     ext=['.txt', '.TXT', '.dat', '.DAT']  
Index: DataLoader/readers/cansas_reader.py
===================================================================
--- DataLoader/readers/cansas_reader.py	(revision 8780e9a7e98f59c06b1819f1e068b7e84f496efc)
+++ DataLoader/readers/cansas_reader.py	(revision 8780e9a7e98f59c06b1819f1e068b7e84f496efc)
@@ -0,0 +1,426 @@
+"""
+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
+"""
+
+#TODO: Unit conversion
+#TODO: Store error list
+#TODO: convert from pixel to mm for beam center...
+#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.
+
+
+import logging
+import numpy
+import os, sys
+from DataLoader.data_info import Data1D, Collimation, Detector, Process
+from xml import xpath
+
+def get_node_text(node):
+    """
+        Get the text context of a node
+        
+        @param node: node to read from
+        @return: content, attribute list
+    """
+    content = None
+    attr    = {}
+    for item in node.childNodes:
+        if item.nodeName.find('text')>=0 \
+            and len(item.nodeValue.strip())>0:
+            content = item.nodeValue.strip()
+            break
+        
+    if node.hasAttributes():
+        for i in range(node.attributes.length):
+            attr[node.attributes.item(i).nodeName] \
+                = node.attributes.item(i).nodeValue
+
+    return content, attr
+
+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
+    """
+    value = None
+    attr  = {}
+    nodes = xpath.Evaluate(location, node)
+    if len(nodes)>0:
+        try:
+            # Skip comments and empty lines 
+            for item in nodes[0].childNodes:
+                if item.nodeName.find('text')>=0 \
+                    and len(item.nodeValue.strip())>0:
+                    value = item.nodeValue.strip()
+                    break
+                
+                if nodes[0].hasAttributes():
+                    for i in range(nodes[0].attributes.length):
+                        attr[nodes[0].attributes.item(i).nodeName] \
+                            = nodes[0].attributes.item(i).nodeValue
+        except:
+            # problem reading the node. Skip it and return that
+            # nothing was found
+            logging.error("cansas_reader.get_content: %s\n  %s" % (location, sys.exc_value))
+        
+    return value, attr
+
+def get_float(location, node):
+    """
+        Get the content of a node as a float
+        
+        @param location: xpath location
+        @param node: node to start at
+    """
+    value = None
+    attr = {}
+    content, attr = get_content(location, node)
+    if content is not None:
+        try:
+            value = float(content)        
+        except:
+            # Could not pass, skip and return None
+            logging.error("cansas_reader.get_float: could not convert '%s' to float" % content)
+        
+    return value, attr
+
+def _store_float(location, node, variable, storage):
+    """
+        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
+        
+        @raise ValueError: raised when the units are not recognized
+    """
+    value, attr = get_float(location, node)
+    if value is not None:
+        exec "storage.%s = value" % variable
+        
+        # If the entry has units, check to see that they are
+        # compatible with what we currently have in the data object
+        if attr.has_key('unit'):
+            toks = variable.split('.')
+            exec "local_unit = storage.%s_unit.lower()" % toks[0]
+            if attr['unit'].lower()!=local_unit:
+                raise ValueError, "CanSAS reader: unrecognized %s unit [%s]; expecting [%s]" \
+                    % (variable, attr['unit'], local_unit)
+
+def _store_content(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
+    """
+    value, attr = get_content(location, node)
+    if value is not None:
+        exec "storage.%s = value" % variable
+
+
+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 = ["CanSAS 1D files (*.xml)|*.xml"]
+    ## List of allowed extensions
+    ext=['.xml', '.XML']  
+    
+    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
+        """
+        from xml.dom.minidom import parse
+        
+        output = []
+        
+        if os.path.isfile(path):
+            basename  = os.path.basename(path)
+            root, extension = os.path.splitext(basename)
+            if extension.lower() in self.ext:
+                
+                dom = parse(path)
+                
+                # Check the format version number
+                nodes = xpath.Evaluate('SASroot', dom)
+                if nodes[0].hasAttributes():
+                    for i in range(nodes[0].attributes.length):
+                        if nodes[0].attributes.item(i).nodeName=='version':
+                            if nodes[0].attributes.item(i).nodeValue != self.version:
+                                raise ValueError, "cansas_reader: unrecognized version number %s" % \
+                                    nodes[0].attributes.item(i).nodeValue
+                
+                entry_list = xpath.Evaluate('SASroot/SASentry', dom)
+                for entry in entry_list:
+                    sas_entry = self._parse_entry(entry)
+                    sas_entry.filename = basename
+                    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:
+            return None
+        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
+        _store_content('Title', dom, 'title', data_info)
+        # Look up run number                    
+        _store_content('Run', dom, 'run', data_info)                    
+        # Look up instrument name              
+        value, attr = get_content('SASinstrument', dom)
+        if attr.has_key('name'):
+            data_info.instrument = attr['name']
+
+        note_list = xpath.Evaluate('SASnote', dom)
+        for note in note_list:
+            try:
+                note_value, note_attr = get_node_text(note)
+                if note_value is not None:
+                    data_info.notes.append(note_value)
+            except:
+                logging.error("cansas_reader.read: error processing entry notes\n  %s" % sys.exc_value)
+
+        
+        # Sample info ###################
+        _store_content('SASsample/ID', 
+                     dom, 'ID', data_info.sample)                    
+        _store_float('SASsample/thickness', 
+                     dom, 'thickness', data_info.sample)
+        _store_float('SASsample/transmission', 
+                     dom, 'transmission', data_info.sample)
+        _store_float('SASsample/temperature', 
+                     dom, 'temperature', data_info.sample)
+        nodes = xpath.Evaluate('SASsample/details', dom)
+        for item in nodes:
+            try:
+                detail_value, detail_attr = get_node_text(item)
+                if detail_value is not None:
+                    data_info.sample.details.append(detail_value)
+            except:
+                logging.error("cansas_reader.read: error processing sample details\n  %s" % sys.exc_value)
+        
+        # Position (as a vector)
+        _store_float('SASsample/position/x', 
+                     dom, 'position.x', data_info.sample)          
+        _store_float('SASsample/position/y', 
+                     dom, 'position.y', data_info.sample)          
+        _store_float('SASsample/position/z', 
+                     dom, 'position.z', data_info.sample)          
+        
+        # Orientation (as a vector)
+        _store_float('SASsample/orientation/roll', 
+                     dom, 'orientation.x', data_info.sample)          
+        _store_float('SASsample/orientation/pitch', 
+                     dom, 'orientation.y', data_info.sample)          
+        _store_float('SASsample/orientation/yaw', 
+                     dom, 'orientation.z', data_info.sample)          
+       
+        # Source info ###################
+        _store_content('SASinstrument/SASsource/radiation', 
+                     dom, 'radiation', data_info.source)                    
+        _store_content('SASinstrument/SASsource/beam_shape', 
+                     dom, 'beam_shape', data_info.source)                    
+        _store_float('SASinstrument/SASsource/wavelength', 
+                     dom, 'wavelength', data_info.source)          
+        _store_float('SASinstrument/SASsource/wavelength_min', 
+                     dom, 'wavelength_min', data_info.source)          
+        _store_float('SASinstrument/SASsource/wavelength_max', 
+                     dom, 'wavelength_max', data_info.source)          
+        _store_float('SASinstrument/SASsource/wavelength_spread', 
+                     dom, 'wavelength_spread', data_info.source)    
+        
+        # Beam size (as a vector)      
+        _store_float('SASinstrument/SASsource/beam_size/x', 
+                     dom, 'beam_size.x', data_info.source)    
+        _store_float('SASinstrument/SASsource/beam_size/y', 
+                     dom, 'beam_size.y', data_info.source)    
+        _store_float('SASinstrument/SASsource/beam_size/z', 
+                     dom, 'beam_size.z', data_info.source)    
+        
+        # Collimation info ###################
+        nodes = xpath.Evaluate('SASinstrument/SAScollimation', dom)
+        for item in nodes:
+            collim = Collimation()
+            _store_float('length', item, 'length', collim)  
+            
+            # Look for apertures
+            apert_list = xpath.Evaluate('aperture', item)
+            for apert in apert_list:
+                aperture =  collim.Aperture()
+                
+                _store_float('distance', apert, 'distance', aperture)    
+                _store_float('size/x', apert, 'size.x', aperture)    
+                _store_float('size/y', apert, 'size.y', aperture)    
+                _store_float('size/z', apert, 'size.z', aperture)
+                
+                collim.aperture.append(aperture)
+                
+            data_info.collimation.append(collim)
+        
+        # Detector info ######################
+        nodes = xpath.Evaluate('SASinstrument/SASdetector', dom)
+        for item in nodes:
+            
+            detector = Detector()
+            
+            _store_content('name', item, 'name', detector)
+            _store_float('SDD', item, 'distance', detector)    
+            
+            # Detector offset (as a vector)
+            _store_float('offset/x', item, 'offset.x', detector)    
+            _store_float('offset/y', item, 'offset.y', detector)    
+            _store_float('offset/z', item, 'offset.z', detector)    
+            
+            # Detector orientation (as a vector)
+            _store_float('orientation/pitch', item, 'orientation.x', detector)    
+            _store_float('orientation/yaw',   item, 'orientation.y', detector)    
+            _store_float('orientation/roll',  item, 'orientation.z', detector)    
+            
+            # Beam center (as a vector)
+            _store_float('beam_center/x', item, 'beam_center.x', detector)    
+            _store_float('beam_center/y', item, 'beam_center.y', detector)    
+            _store_float('beam_center/z', item, 'beam_center.z', detector)    
+            
+            # Pixel size (as a vector)
+            _store_float('pixel_size/x', item, 'pixel_size.x', detector)    
+            _store_float('pixel_size/y', item, 'pixel_size.y', detector)    
+            _store_float('pixel_size/z', item, 'pixel_size.z', detector)    
+            
+            _store_float('slit_length', item, 'slit_length', detector)
+            
+            data_info.detector.append(detector)    
+
+        # Processes info ######################
+        nodes = xpath.Evaluate('SASprocess', dom)
+        for item in nodes:
+            process = Process()
+            _store_content('name', item, 'name', process)
+            _store_content('date', item, 'date', process)
+            _store_content('description', item, 'description', process)
+            
+            term_list = xpath.Evaluate('term', item)
+            for term in term_list:
+                try:
+                    term_value, term_attr = get_node_text(term)
+                    term_attr['value'] = term_value
+                    if term_value is not None:
+                        process.term.append(term_attr)
+                except:
+                    logging.error("cansas_reader.read: error processing process term\n  %s" % sys.exc_value)
+            
+            note_list = xpath.Evaluate('SASprocessnote', item)
+            for note in note_list:
+                try:
+                    note_value, note_attr = get_node_text(note)
+                    if note_value is not None:
+                        process.notes.append(note_value)
+                except:
+                    logging.error("cansas_reader.read: error processing process notes\n  %s" % sys.exc_value)
+            
+            
+            data_info.process.append(process)
+            
+            
+        # Data info ######################
+        nodes = xpath.Evaluate('SASdata/Idata', dom)
+        x  = numpy.zeros(0)
+        y  = numpy.zeros(0)
+        dx = numpy.zeros(0)
+        dy = numpy.zeros(0)
+        
+        for item in nodes:
+            _x, attr = get_float('Q', item)
+            _dx, attr = get_float('Qdev', item)
+            if _dx == None:
+                _dx = 0.0
+            if attr.has_key('unit') and attr['unit'].lower() != data_info.x_unit.lower():
+                raise ValueError, "CanSAS reader: unrecognized %s unit [%s]; expecting [%s]" \
+                    % (variable, attr['unit'], local_unit)
+                
+            _y, attr = get_float('I', item)
+            _dy, attr = get_float('Idev', item)
+            if _dy == None:
+                _dy = 0.0
+            if attr.has_key('unit') and attr['unit'].lower() != data_info.y_unit.lower():
+                raise ValueError, "CanSAS reader: unrecognized %s unit [%s]; expecting [%s]" \
+                    % (variable, attr['unit'], local_unit)
+                
+            if _x is not None and _y is not None:
+                x  = numpy.append(x, _x)
+                y  = numpy.append(x, _y)
+                dx = numpy.append(x, _dx)
+                dy = numpy.append(x, _dy)
+            
+        data_info.x = x
+        data_info.y = y
+        data_info.dx = dx
+        data_info.dy = dy
+        data_info.xaxis("\\rm{Q}", 'A^{-1}')
+        data_info.yaxis("\\rm{I(Q)}","cm^{-1}")
+
+        return data_info
+
+    
+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")
+    
+    
+                        
Index: DataLoader/test/cansas1d.xml
===================================================================
--- DataLoader/test/cansas1d.xml	(revision 8780e9a7e98f59c06b1819f1e068b7e84f496efc)
+++ DataLoader/test/cansas1d.xml	(revision 8780e9a7e98f59c06b1819f1e068b7e84f496efc)
@@ -0,0 +1,136 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="example.xsl" ?>
+<SASroot version="1.0"
+    xmlns="cansas1d/1.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="cansas1d/1.0 http://svn.smallangles.net/svn/canSAS/1dwg/trunk/cansas1d.xsd"
+    >
+	<SASentry>
+		<Title>Test title</Title>
+		<Run>1234</Run>
+		<SASdata>
+			<Idata>
+				<Q unit="1/A">0.02</Q>
+				<I unit="1/cm">1000</I>
+				<Idev unit="1/cm">3</Idev>
+				<Qdev unit="1/A">0.01</Qdev>
+				<Qmean unit="1/A"><!-- Qmean is optional --></Qmean>
+				<Shadowfactor><!-- Shadowfactor is optional --></Shadowfactor>
+			</Idata>
+			<Idata>
+				<Q unit="1/A">0.02</Q>
+				<I unit="1/cm">1000</I>
+				<Idev unit="1/cm">3</Idev>
+				<Qdev unit="1/A">0.01</Qdev>
+				<Qmean unit="1/A"><!-- Qmean is optional --></Qmean>
+				<Shadowfactor><!-- Shadowfactor is optional --></Shadowfactor>
+			</Idata>
+		</SASdata>
+		<SASsample>
+			<ID>SI600-new-long</ID>
+			<thickness unit="mm">1.03</thickness>
+			<transmission>0.327</transmission>
+			<temperature unit="C">0.0000</temperature>
+			<position>
+				<x unit="mm">10.00</x>
+				<y unit="mm">0.00</y>
+			</position>
+			<orientation>
+				<roll unit="degree">22.5<!-- was: sample_orientation --></roll>
+				<pitch unit="degree">0.020<!-- was: sample_offset_angle --></pitch>
+			</orientation>
+			<details>
+				<!-- was: sample_prep -->
+				http://chemtools.chem.soton.ac.uk/projects/blog/blogs.php/bit_id/2720
+			</details>
+			<details>
+				Some text here
+			</details>
+			
+		</SASsample>
+		<SASinstrument name="TEST instrument">
+			<name>canSAS instrument</name>
+			<SASsource>
+				<radiation>neutron</radiation>
+				<beam_size>
+					<x unit="mm">12.00</x>
+					<y unit="mm">12.00</y>
+				</beam_size>
+				<beam_shape>disc</beam_shape>
+				<wavelength unit="A">6.00</wavelength>
+				<wavelength_min unit="nm">0.22</wavelength_min>
+				<wavelength_max unit="nm">1.00</wavelength_max>
+				<wavelength_spread unit="percent">
+					14.3
+				</wavelength_spread>
+			</SASsource>
+			<SAScollimation>
+				<aperture name="source" type="radius">
+					<size>
+						<x unit="mm">50</x>
+					</size>
+					<distance unit="m">11.000<!-- was: distance_coll --></distance>
+				</aperture>
+				<aperture name="sample" type="radius">
+					<size>
+						<x unit="mm">1</x>
+					</size>
+				</aperture>
+			</SAScollimation>
+			<SASdetector>
+				<name>fictional hybrid</name>
+				<SDD unit="m">
+					<!-- sample-to-detector distance -->
+					4.150
+				</SDD>
+				<orientation>
+					<roll unit="degree">1.00</roll>
+					<pitch unit="degree">0.00</pitch>
+					<yaw unit="degree">0.00</yaw>
+				</orientation>
+				<beam_center>
+					<x unit="mm">322.64</x>
+					<y unit="mm">327.68</y>
+				</beam_center>
+				<pixel_size>
+					<x unit="mm">5.00</x>
+					<y unit="mm">5.00</y>
+				</pixel_size>
+			</SASdetector>
+		</SASinstrument>
+		<SASprocess>
+			<name>spol</name>
+			<date>04-Sep-2007 18:35:02</date>
+			<term name="radialstep" unit="mm">10.000</term>
+			<term name="sector_width" unit="degree">180.0</term>
+			<term name="sector_orient" unit="degree">0.0</term>
+			<term name="MASK_file">USER:MASK.COM</term>
+			<SASprocessnote>
+				AvA1 0.0000E+00 AsA2 1.0000E+00 XvA3 1.0526E+03 XsA4
+				5.2200E-02 XfA5 0.0000E+00
+			</SASprocessnote>
+			<SASprocessnote>
+				S... 13597 0 2.26E+02 2A 5mM 0%D2O Sbak 13594 0 1.13E+02
+				H2O Buffer
+			</SASprocessnote>
+			<SASprocessnote>V... 13552 3 1.00E+00 H2O5m</SASprocessnote>
+		</SASprocess>
+		<SASprocess>
+			<name>NCNR-IGOR</name>
+			<date>03-SEP-2006 11:42:47</date>
+			<description />
+			<term name="average_type">Circular</term>
+			<term name="SAM_file">SEP06064.SA3_AJJ_L205</term>
+			<term name="BKD_file">SEP06064.SA3_AJJ_L205</term>
+			<term name="EMP_file">SEP06064.SA3_AJJ_L205</term>
+			<term name="DIV_file">SEP06064.SA3_AJJ_L205</term>
+			<term name="MASK_file">SEP06064.SA3_AJJ_L205</term>
+			<term name="ABS:TSTAND">1</term>
+			<term name="ABS:DSTAND" unit="mm">1</term>
+			<term name="ABS:IZERO">230.09</term>
+			<term name="ABS:XSECT" unit="mm">1</term>
+			<SASprocessnote/>
+		</SASprocess>
+		<SASnote />
+	</SASentry>
+</SASroot>
Index: DataLoader/test/cansas_test.xml
===================================================================
--- DataLoader/test/cansas_test.xml	(revision 8780e9a7e98f59c06b1819f1e068b7e84f496efc)
+++ DataLoader/test/cansas_test.xml	(revision 8780e9a7e98f59c06b1819f1e068b7e84f496efc)
@@ -0,0 +1,106 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="example.xsl" ?>
+<SASroot version="1.0"
+    xmlns="cansas1d/1.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="cansas1d/1.0 http://svn.smallangles.net/svn/canSAS/1dwg/trunk/cansas1d.xsd"
+    >
+	<SASentry>
+		<Title>ILL-D11 example1: 2A 5mM 0%D2O</Title>
+		<Run>g013586.001</Run>
+		<SASdata>
+			<Idata><Q unit="1/A">  0.000E+00 </Q><I unit="1/cm">  0.0000E+00 </I><Idev unit="1/cm">  0.000E+00 </Idev><Qdev unit="1/A">  0.00E+00 </Qdev></Idata>
+			<Idata><Q unit="1/A">  1.047E-03 </Q><I unit="1/cm">  0.0000E+00 </I><Idev unit="1/cm">  0.000E+00 </Idev><Qdev unit="1/A">  9.14E-04 </Qdev></Idata>
+			<Idata><Q unit="1/A">  2.094E-03 </Q><I unit="1/cm">  0.0000E+00 </I><Idev unit="1/cm">  0.000E+00 </Idev><Qdev unit="1/A">  9.32E-04 </Qdev></Idata>
+			<Idata><Q unit="1/A">  3.142E-03 </Q><I unit="1/cm">  0.0000E+00 </I><Idev unit="1/cm">  0.000E+00 </Idev><Qdev unit="1/A">  9.61E-04 </Qdev></Idata>
+			<Idata><Q unit="1/A">  4.189E-03 </Q><I unit="1/cm">  0.0000E+00 </I><Idev unit="1/cm">  0.000E+00 </Idev><Qdev unit="1/A">  1.00E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  5.364E-03 </Q><I unit="1/cm">  5.4484E+00 </I><Idev unit="1/cm">  1.647E-01 </Idev><Qdev unit="1/A">  1.05E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  6.255E-03 </Q><I unit="1/cm">  4.9963E+00 </I><Idev unit="1/cm">  9.122E-02 </Idev><Qdev unit="1/A">  1.10E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  7.299E-03 </Q><I unit="1/cm">  4.6705E+00 </I><Idev unit="1/cm">  7.450E-02 </Idev><Qdev unit="1/A">  1.17E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  8.340E-03 </Q><I unit="1/cm">  4.2690E+00 </I><Idev unit="1/cm">  5.745E-02 </Idev><Qdev unit="1/A">  1.23E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  9.395E-03 </Q><I unit="1/cm">  4.0078E+00 </I><Idev unit="1/cm">  5.484E-02 </Idev><Qdev unit="1/A">  1.31E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  1.045E-02 </Q><I unit="1/cm">  3.8409E+00 </I><Idev unit="1/cm">  4.939E-02 </Idev><Qdev unit="1/A">  1.38E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  1.151E-02 </Q><I unit="1/cm">  3.6579E+00 </I><Idev unit="1/cm">  4.750E-02 </Idev><Qdev unit="1/A">  1.47E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  1.258E-02 </Q><I unit="1/cm">  3.4413E+00 </I><Idev unit="1/cm">  4.344E-02 </Idev><Qdev unit="1/A">  1.55E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  1.362E-02 </Q><I unit="1/cm">  3.2571E+00 </I><Idev unit="1/cm">  4.197E-02 </Idev><Qdev unit="1/A">  1.64E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  1.465E-02 </Q><I unit="1/cm">  3.0475E+00 </I><Idev unit="1/cm">  4.016E-02 </Idev><Qdev unit="1/A">  1.72E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  1.570E-02 </Q><I unit="1/cm">  2.9447E+00 </I><Idev unit="1/cm">  3.703E-02 </Idev><Qdev unit="1/A">  1.81E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  1.674E-02 </Q><I unit="1/cm">  2.8542E+00 </I><Idev unit="1/cm">  3.706E-02 </Idev><Qdev unit="1/A">  1.90E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  1.779E-02 </Q><I unit="1/cm">  2.6221E+00 </I><Idev unit="1/cm">  3.293E-02 </Idev><Qdev unit="1/A">  2.00E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  1.886E-02 </Q><I unit="1/cm">  2.5466E+00 </I><Idev unit="1/cm">  3.318E-02 </Idev><Qdev unit="1/A">  2.09E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  1.989E-02 </Q><I unit="1/cm">  2.4346E+00 </I><Idev unit="1/cm">  3.203E-02 </Idev><Qdev unit="1/A">  2.19E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  2.093E-02 </Q><I unit="1/cm">  2.2702E+00 </I><Idev unit="1/cm">  3.034E-02 </Idev><Qdev unit="1/A">  2.28E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  2.198E-02 </Q><I unit="1/cm">  2.2182E+00 </I><Idev unit="1/cm">  3.011E-02 </Idev><Qdev unit="1/A">  2.38E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  2.303E-02 </Q><I unit="1/cm">  2.0914E+00 </I><Idev unit="1/cm">  2.798E-02 </Idev><Qdev unit="1/A">  2.48E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  2.408E-02 </Q><I unit="1/cm">  2.0097E+00 </I><Idev unit="1/cm">  2.795E-02 </Idev><Qdev unit="1/A">  2.57E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  2.511E-02 </Q><I unit="1/cm">  1.9056E+00 </I><Idev unit="1/cm">  2.684E-02 </Idev><Qdev unit="1/A">  2.67E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  2.617E-02 </Q><I unit="1/cm">  1.8275E+00 </I><Idev unit="1/cm">  2.559E-02 </Idev><Qdev unit="1/A">  2.77E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  2.724E-02 </Q><I unit="1/cm">  1.7406E+00 </I><Idev unit="1/cm">  2.508E-02 </Idev><Qdev unit="1/A">  2.87E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  2.828E-02 </Q><I unit="1/cm">  1.6591E+00 </I><Idev unit="1/cm">  2.441E-02 </Idev><Qdev unit="1/A">  2.97E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  2.932E-02 </Q><I unit="1/cm">  1.5903E+00 </I><Idev unit="1/cm">  2.451E-02 </Idev><Qdev unit="1/A">  3.07E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  3.035E-02 </Q><I unit="1/cm">  1.4810E+00 </I><Idev unit="1/cm">  2.289E-02 </Idev><Qdev unit="1/A">  3.17E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  3.140E-02 </Q><I unit="1/cm">  1.4093E+00 </I><Idev unit="1/cm">  2.279E-02 </Idev><Qdev unit="1/A">  3.27E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  3.242E-02 </Q><I unit="1/cm">  1.3394E+00 </I><Idev unit="1/cm">  2.281E-02 </Idev><Qdev unit="1/A">  3.37E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  3.349E-02 </Q><I unit="1/cm">  1.2679E+00 </I><Idev unit="1/cm">  2.555E-02 </Idev><Qdev unit="1/A">  3.47E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  3.454E-02 </Q><I unit="1/cm">  1.2336E+00 </I><Idev unit="1/cm">  2.911E-02 </Idev><Qdev unit="1/A">  3.57E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  3.560E-02 </Q><I unit="1/cm">  1.1766E+00 </I><Idev unit="1/cm">  2.880E-02 </Idev><Qdev unit="1/A">  3.67E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  3.666E-02 </Q><I unit="1/cm">  1.0849E+00 </I><Idev unit="1/cm">  3.269E-02 </Idev><Qdev unit="1/A">  3.78E-03 </Qdev></Idata>
+			<Idata><Q unit="1/A">  3.750E-02 </Q><I unit="1/cm">  1.0130E+00 </I><Idev unit="1/cm">  5.246E-02 </Idev><Qdev unit="1/A">  3.86E-03 </Qdev></Idata>
+		</SASdata>
+		<SASsample>
+			<thickness unit="mm">0.0000</thickness>
+			<transmission>0.0000</transmission>
+			<temperature unit="C">32.0000</temperature>
+			<position>
+				<x unit="mm">10.00</x>
+				<y unit="mm">0.00</y>
+			</position>
+			<orientation>
+				<roll unit="degree">0.020<!-- was: sample_offset_angle_deg --></roll>
+			</orientation>
+		</SASsample>
+		<SASinstrument name="D11">
+			<SASsource>
+				<radiation>neutron</radiation>
+				<beam_size>
+					<x unit="mm">30.00</x>
+					<y unit="mm">0.00</y>
+				</beam_size>
+				<wavelength unit="A">6.00</wavelength>
+				<wavelength_spread unit="A">0.00</wavelength_spread>
+			</SASsource>
+			<SAScollimation>
+				<distance unit="m">10.000</distance>
+			</SAScollimation>
+			<SASdetector>
+				<name />
+				<SDD unit="m">10.000</SDD>
+				<orientation>
+					<roll unit="degree">0.00<!-- was: offset_angle_deg --></roll>
+				</orientation>
+				<beam_center>
+					<x unit="mm">311.00</x>
+					<y unit="mm">315.00</y>
+				</beam_center>
+				<pixel_size>
+					<x unit="mm">10.00</x>
+					<y unit="mm">10.00</y>
+				</pixel_size>
+			</SASdetector>
+		</SASinstrument>
+		<SASprocess name="spol" >
+			<name>spol</name>
+			<date>04-Sep-2007 18:12:27</date>
+			<term name="radialstep" unit="mm">10.000</term>
+			<term name="sector_width" unit="deg">180.0</term>
+			<term name="sector_orient" unit="deg">0.0</term>
+			<term name="Flux_monitor">1.00</term>
+			<term name="Count_time" unit="s">900.000</term>
+			<term name="Q_resolution">estimated</term>
+			<SASprocessnote name="01">  AvA1 0.0000E+00 AsA2 1.0000E+00 XvA3 1.1111E+01 XsA4 5.2200E-02 XfA5 0.0000E+00 </SASprocessnote>
+			<SASprocessnote name="02"> S... 13586  0  5.63E+01 2A 5mM 0%D2O    Sbak 13567  0  1.88E+01 H2O buffer       </SASprocessnote>
+			<SASprocessnote name="03"> Sbak 13533  0  7.49E+00 H2O buffer      V... 13552  1  1.00E+00 Normal 10m from  </SASprocessnote>
+			<SASprocessnote name="04" />
+</SASprocess>
+	</SASentry>
+</SASroot>
