Index: src/sas/sascalc/dataloader/file_reader_base_class.py
===================================================================
--- src/sas/sascalc/dataloader/file_reader_base_class.py	(revision da8bb53be7e5e725c5c588a677fbc7eb7238e129)
+++ src/sas/sascalc/dataloader/file_reader_base_class.py	(revision ad92c5a96ecb73ee7094bafca363a6a7a61a530d)
@@ -52,5 +52,4 @@
                 # Try to load the file, but raise an error if unable to.
                 try:
-                    self.load_unit_converter()
                     self.f_open = open(filepath, 'rb')
                     self.get_file_contents()
@@ -94,15 +93,4 @@
         self.output.append(data_obj)
 
-    def load_unit_converter(self):
-        """
-        Generic unit conversion import 
-        """
-        # Check whether we have a converter available
-        self.has_converter = True
-        try:
-            from sas.sascalc.data_util.nxsunit import Converter
-        except:
-            self.has_converter = False
-
     def sort_one_d_data(self):
         """
@@ -138,4 +126,27 @@
         self.output = []
 
+    def remove_empty_q_values(self, has_error_dx=False, has_error_dy=False):
+        """
+        Remove any point where Q == 0
+        """
+        x = self.current_dataset.x
+        self.current_dataset.x = self.current_dataset.x[x != 0]
+        self.current_dataset.y = self.current_dataset.y[x != 0]
+        self.current_dataset.dy = self.current_dataset.dy[x != 0] if \
+            has_error_dy else np.zeros(len(self.current_dataset.y))
+        self.current_dataset.dx = self.current_dataset.dx[x != 0] if \
+            has_error_dx else np.zeros(len(self.current_dataset.x))
+
+    def reset_data_list(self, no_lines=0):
+        """
+        Reset the plottable_1D object
+        """
+        # Initialize data sets with arrays the maximum possible size
+        x = np.zeros(no_lines)
+        y = np.zeros(no_lines)
+        dy = np.zeros(no_lines)
+        dx = np.zeros(no_lines)
+        self.current_dataset = plottable_1D(x, y, dx, dy)
+
     @staticmethod
     def splitline(line):
@@ -158,4 +169,5 @@
     def get_file_contents(self):
         """
+        Reader specific class to access the contents of the file
         All reader classes that inherit from FileReader must implement
         """
Index: src/sas/sascalc/dataloader/readers/abs_reader.py
===================================================================
--- src/sas/sascalc/dataloader/readers/abs_reader.py	(revision 959eb0181ad06828a748f04512f953aad5b31659)
+++ src/sas/sascalc/dataloader/readers/abs_reader.py	(revision ad92c5a96ecb73ee7094bafca363a6a7a61a530d)
@@ -1,249 +1,228 @@
 """
+    IGOR 1D data reader
 """
 #####################################################################
-#This software was developed by the University of Tennessee as part of the
-#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
-#project funded by the US National Science Foundation.
-#See the license text in license.txt
-#copyright 2008, University of Tennessee
+# 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 logging
 import numpy as np
-import os
-from sas.sascalc.dataloader.data_info import Data1D
-from sas.sascalc.dataloader.data_info import Detector
-
-has_converter = True
-try:
-    from sas.sascalc.data_util.nxsunit import Converter
-except:
-    has_converter = False
-    
-    
-class Reader:
+from sas.sascalc.dataloader.file_reader_base_class import FileReader
+from sas.sascalc.dataloader.data_info import DataInfo, plottable_1D, Data1D,\
+    Detector
+from sas.sascalc.dataloader.loader_exceptions import FileContentsException,\
+    DefaultReaderException
+
+logger = logging.getLogger(__name__)
+
+
+class Reader(FileReader):
     """
     Class to load IGOR reduced .ABS files
     """
-    ## File type
+    # File type
     type_name = "IGOR 1D"
-    ## Wildcards
+    # Wildcards
     type = ["IGOR 1D files (*.abs)|*.abs"]
-    ## List of allowed extensions
-    ext = ['.abs', '.ABS']
+    # List of allowed extensions
+    ext = ['.abs']
     
-    def read(self, path):
+    def get_file_contents(self):
         """ 
-        Load data file.
-        
-        :param path: file path
-        
-        :return: Data1D object, or None
+        Get the contents of the file
         
         :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')
+        buff = self.f_open.read()
+        filepath = self.f_open.name
+        lines = buff.splitlines()
+        self.has_converter = True
+        try:
+            from sas.sascalc.data_util.nxsunit import Converter
+        except:
+            self.has_converter = False
+        self.output = []
+        self.current_datainfo = DataInfo()
+        self.current_datainfo.filename = filepath
+        self.reset_data_list(len(lines))
+        detector = Detector()
+        data_line = 0
+        self.reset_data_list(len(lines))
+        self.current_datainfo.detector.append(detector)
+        self.current_datainfo.filename = filepath
+
+        is_info = False
+        is_center = False
+        is_data_started = False
+
+        base_q_unit = '1/A'
+        base_i_unit = '1/cm'
+        data_conv_q = Converter(base_q_unit)
+        data_conv_i = Converter(base_i_unit)
+
+        for line in lines:
+            # Information line 1
+            if is_info:
+                is_info = False
+                line_toks = line.split()
+
+                # Wavelength in Angstrom
+                try:
+                    value = float(line_toks[1])
+                    if self.has_converter and \
+                            self.current_datainfo.source.wavelength_unit != 'A':
+                        conv = Converter('A')
+                        self.current_datainfo.source.wavelength = conv(value,
+                            units=self.current_datainfo.source.wavelength_unit)
+                    else:
+                        self.current_datainfo.source.wavelength = value
+                except KeyError:
+                    msg = "ABSReader cannot read wavelength from %s" % filepath
+                    self.current_datainfo.errors.append(msg)
+
+                # Detector distance in meters
+                try:
+                    value = float(line_toks[3])
+                    if self.has_converter and detector.distance_unit != 'm':
+                        conv = Converter('m')
+                        detector.distance = conv(value,
+                                        units=detector.distance_unit)
+                    else:
+                        detector.distance = value
                 except:
-                    raise  RuntimeError, "abs_reader: cannot open %s" % path
-                buff = input_f.read()
-                lines = buff.split('\n')
-                x  = np.zeros(0)
-                y  = np.zeros(0)
-                dy = np.zeros(0)
-                dx = np.zeros(0)
-                output = Data1D(x, y, dy=dy, dx=dx)
-                detector = Detector()
-                output.detector.append(detector)
-                output.filename = basename
-                
-                is_info = False
+                    msg = "ABSReader cannot read SDD from %s" % filepath
+                    self.current_datainfo.errors.append(msg)
+
+                # Transmission
+                try:
+                    self.current_datainfo.sample.transmission = \
+                        float(line_toks[4])
+                except ValueError:
+                    # Transmission isn't always in the header
+                    pass
+
+                # Sample thickness in mm
+                try:
+                    value = float(line_toks[5])
+                    if self.has_converter and \
+                            self.current_datainfo.sample.thickness_unit != 'cm':
+                        conv = Converter('cm')
+                        self.current_datainfo.sample.thickness = conv(value,
+                            units=self.current_datainfo.sample.thickness_unit)
+                    else:
+                        self.current_datainfo.sample.thickness = value
+                except ValueError:
+                    # 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:
                 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
-                        
-                        # 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 = np.append(x, _x)
-                            y = np.append(y, _y)
-                            dy = np.append(dy, _dy)
-                            dx = np.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"
-                
-                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)
+                line_toks = line.split()
+                # Center in bin number
+                center_x = float(line_toks[0])
+                center_y = float(line_toks[1])
+
+                # Bin size
+                if self.has_converter and detector.pixel_size_unit != 'mm':
+                    conv = Converter('mm')
+                    detector.pixel_size.x = conv(5.08,
+                                        units=detector.pixel_size_unit)
+                    detector.pixel_size.y = conv(5.08,
+                                        units=detector.pixel_size_unit)
                 else:
-                    output.xaxis("\\rm{Q}", 'A^{-1}')
-                if data_conv_i is not None:
-                    output.yaxis("\\rm{Intensity}", output.y_unit)
+                    detector.pixel_size.x = 5.08
+                    detector.pixel_size.y = 5.08
+
+                # Store beam center in distance units
+                # Det 640 x 640 mm
+                if self.has_converter and detector.beam_center_unit != 'mm':
+                    conv = Converter('mm')
+                    detector.beam_center.x = conv(center_x * 5.08,
+                                     units=detector.beam_center_unit)
+                    detector.beam_center.y = conv(center_y * 5.08,
+                                    units=detector.beam_center_unit)
                 else:
-                    output.yaxis("\\rm{Intensity}", "cm^{-1}")
-                    
-                # Store loading process information
-                output.meta_data['loader'] = self.type_name
-                return output
+                    detector.beam_center.x = center_x * 5.08
+                    detector.beam_center.y = center_y * 5.08
+
+                # 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:
+                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=base_q_unit)
+                        _dx = data_conv_q(_dx, units=base_q_unit)
+
+                    if data_conv_i is not None:
+                        _y = data_conv_i(_y, units=base_i_unit)
+                        _dy = data_conv_i(_dy, units=base_i_unit)
+
+                    self.current_dataset.x[data_line] = _x
+                    self.current_dataset.y[data_line] = _y
+                    self.current_dataset.dy[data_line] = _dy
+                    self.current_dataset.dx[data_line] = _dx
+                    data_line += 1
+
+                except ValueError:
+                    # 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
+
+        self.remove_empty_q_values(True, True)
+
+        # Sanity check
+        if not len(self.current_dataset.y) == len(self.current_dataset.dy):
+            self.set_all_to_none()
+            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(self.current_dataset.x) == 0:
+            self.set_all_to_none()
+            raise ValueError("ascii_reader: could not load file")
+
+        if data_conv_q is not None:
+            self.current_dataset.xaxis("\\rm{Q}", base_q_unit)
         else:
-            raise RuntimeError, "%s is not a file" % path
-        return None
+            self.current_dataset.xaxis("\\rm{Q}", 'A^{-1}')
+        if data_conv_i is not None:
+            self.current_dataset.yaxis("\\rm{Intensity}", base_i_unit)
+        else:
+            self.current_dataset.yaxis("\\rm{Intensity}", "cm^{-1}")
+
+        # Store loading process information
+        self.current_datainfo.meta_data['loader'] = self.type_name
+        self.send_to_output()
Index: src/sas/sascalc/dataloader/readers/ascii_reader.py
===================================================================
--- src/sas/sascalc/dataloader/readers/ascii_reader.py	(revision da8bb53be7e5e725c5c588a677fbc7eb7238e129)
+++ src/sas/sascalc/dataloader/readers/ascii_reader.py	(revision ad92c5a96ecb73ee7094bafca363a6a7a61a530d)
@@ -150,13 +150,5 @@
             raise FileContentsException(msg)
 
-        # Remove any point where Q == 0
-        x = self.current_dataset.x
-        self.current_dataset.x = self.current_dataset.x[x != 0]
-        self.current_dataset.y = self.current_dataset.y[x != 0]
-        self.current_dataset.dy = self.current_dataset.dy[x != 0] if \
-            has_error_dy else np.zeros(len(self.current_dataset.y))
-        self.current_dataset.dx = self.current_dataset.dx[x != 0] if \
-            has_error_dx else np.zeros(len(self.current_dataset.x))
-
+        self.remove_empty_q_values(has_error_dx, has_error_dy)
         self.current_dataset.xaxis("\\rm{Q}", 'A^{-1}')
         self.current_dataset.yaxis("\\rm{Intensity}", "cm^{-1}")
@@ -165,13 +157,2 @@
         self.current_datainfo.meta_data['loader'] = self.type_name
         self.send_to_output()
-
-    def reset_data_list(self, no_lines):
-        """
-        Reset the plottable_1D object
-        """
-        # Initialize data sets with arrays the maximum possible size
-        x = np.zeros(no_lines)
-        y = np.zeros(no_lines)
-        dy = np.zeros(no_lines)
-        dx = np.zeros(no_lines)
-        self.current_dataset = plottable_1D(x, y, dx, dy)
