Index: src/sas/sascalc/dataloader/file_reader_base_class.py
===================================================================
--- src/sas/sascalc/dataloader/file_reader_base_class.py	(revision 9d786e572492d279fc9ae1e2c7ca8c4c8e855623)
+++ src/sas/sascalc/dataloader/file_reader_base_class.py	(revision 2f85af7145254a68c54575abc23e44599ebef7ae)
@@ -155,9 +155,5 @@
                     dataset.y_bins = dataset.qy_data[0::int(n_cols)]
                     dataset.x_bins = dataset.qx_data[:int(n_cols)]
-                    dataset.data = dataset.data.flatten()
-                else:
-                    dataset.y_bins = []
-                    dataset.x_bins = []
-                    dataset.data = dataset.data.flatten()
+                dataset.data = dataset.data.flatten()
                 final_list.append(dataset)
         self.output = final_list
Index: src/sas/sascalc/dataloader/readers/red2d_reader.py
===================================================================
--- src/sas/sascalc/dataloader/readers/red2d_reader.py	(revision 959eb0181ad06828a748f04512f953aad5b31659)
+++ src/sas/sascalc/dataloader/readers/red2d_reader.py	(revision 2f85af7145254a68c54575abc23e44599ebef7ae)
@@ -5,5 +5,5 @@
 #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. 
+#project funded by the US National Science Foundation.
 #See the license text in license.txt
 #copyright 2008, University of Tennessee
@@ -12,5 +12,7 @@
 import numpy as np
 import math
-from sas.sascalc.dataloader.data_info import Data2D, Detector
+from sas.sascalc.dataloader.data_info import plottable_2D, DataInfo, Detector
+from sas.sascalc.dataloader.file_reader_base_class import FileReader
+from sas.sascalc.dataloader.loader_exceptions import FileContentsException
 
 # Look for unit converter
@@ -20,6 +22,6 @@
 except:
     has_converter = False
-    
-    
+
+
 def check_point(x_point):
     """
@@ -31,7 +33,7 @@
     except:
         return 0
-      
-        
-class Reader:
+
+
+class Reader(FileReader):
     """ Simple data reader for Igor data files """
     ## File type
@@ -41,9 +43,9 @@
     ## Extension
     ext = ['.DAT', '.dat']
-    
+
     def write(self, filename, data):
         """
         Write to .dat
-        
+
         :param filename: file name to write
         :param data: data2D
@@ -51,71 +53,49 @@
         import 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
-
+        try:
+            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]))
+        finally:
+            fd.close()
+
+    def get_file_contents(self):
         # Read file
-        f = open(filename, 'r')
-        buf = f.read()
-        f.close()
+        buf = self.f_open.read()
+        self.f_open.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)
-                
+        self.current_dataset = plottable_2D()
+        self.current_datainfo = DataInfo()
+        self.current_datainfo.filename = os.path.basename(self.f_open.name)
+        self.current_datainfo.detector.append(Detector())
+
         # Get content
-        dataStarted = False
-        
+        data_started = False
+
         ## Defaults
         lines = buf.split('\n')
         x = []
         y = []
-        
+
         wavelength = None
         distance = None
         transmission = None
-        
+
         pixel_x = None
         pixel_y = None
-        
-        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)
-        
-              
+
+        is_info = False
+        is_center = False
+
         # Remove the last lines before the for loop if the lines are empty
         # to calculate the exact number of data points
@@ -133,6 +113,6 @@
             ## Reading the header applies only to IGOR/NIST 2D q_map data files
             # Find setup info line
-            if isInfo:
-                isInfo = False
+            if is_info:
+                is_info = False
                 line_toks = line.split()
                 # Wavelength in Angstrom
@@ -141,8 +121,8 @@
                     # Units
                     if has_converter == True and \
-                    output.source.wavelength_unit != 'A':
+                    self.current_datainfo.source.wavelength_unit != 'A':
                         conv = Converter('A')
                         wavelength = conv(wavelength,
-                                          units=output.source.wavelength_unit)
+                                          units=self.current_datainfo.source.wavelength_unit)
                 except:
                     #Not required
@@ -152,11 +132,12 @@
                     distance = float(line_toks[3])
                     # Units
-                    if has_converter == True and detector.distance_unit != 'm':
+                    if has_converter == True and self.current_datainfo.detector[0].distance_unit != 'm':
                         conv = Converter('m')
-                        distance = conv(distance, units=detector.distance_unit)
+                        distance = conv(distance,
+                            units=self.current_datainfo.detector[0].distance_unit)
                 except:
                     #Not required
                     pass
-                
+
                 # Distance in meters
                 try:
@@ -165,11 +146,11 @@
                     #Not required
                     pass
-                                            
+
             if line.count("LAMBDA") > 0:
-                isInfo = True
-                
+                is_info = True
+
             # Find center info line
-            if isCenter:
-                isCenter = False
+            if is_center:
+                is_center = False
                 line_toks = line.split()
                 # Center in bin number
@@ -178,5 +159,5 @@
 
             if line.count("BCENT") > 0:
-                isCenter = True
+                is_center = True
             # Check version
             if line.count("Data columns") > 0:
@@ -185,14 +166,14 @@
             # Find data start
             if line.count("ASCII data") > 0:
-                dataStarted = True
+                data_started = True
                 continue
 
             ## Read and get data.
-            if dataStarted == True:
+            if data_started == True:
                 line_toks = line.split()
                 if len(line_toks) == 0:
                     #empty line
                     continue
-                # the number of columns must be stayed same 
+                # the number of columns must be stayed same
                 col_num = len(line_toks)
                 break
@@ -202,5 +183,5 @@
         # index for lines_array
         lines_index = np.arange(len(lines))
-        
+
         # get the data lines
         data_lines = lines_array[lines_index >= (line_num - 1)]
@@ -211,5 +192,5 @@
         # 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
@@ -231,6 +212,6 @@
             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
+            msg = "red2d_reader can't read this file: Incorrect number of data points provided."
+            raise FileContentsException(msg)
         ## Get the all data: Let's HARDcoding; Todo find better way
         # Defaults
@@ -255,10 +236,10 @@
         #if col_num > (6 + ver): mask[data_point[(6 + ver)] < 1] = False
         q_data = np.sqrt(qx_data*qx_data+qy_data*qy_data+qz_data*qz_data)
-           
-        # Extra protection(it is needed for some data files): 
+
+        # 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 = np.min(qx_data)
@@ -267,27 +248,20 @@
         ymax = np.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 = np.arange(xmin, xmax + xstep, xstep)
         y_bins = np.arange(ymin, ymax + ystep, ystep)
-       
+
         # get the limits of q values
         xmin = xmin - xstep / 2
@@ -295,36 +269,36 @@
         ymin = ymin - ystep / 2
         ymax = ymax + ystep / 2
-        
+
         #Store data in outputs
         #TODO: Check the lengths
-        output.data = data
+        self.current_dataset.data = data
         if (err_data == 1).all():
-            output.err_data = np.sqrt(np.abs(data))
-            output.err_data[output.err_data == 0.0] = 1.0
+            self.current_dataset.err_data = np.sqrt(np.abs(data))
+            self.current_dataset.err_data[self.current_dataset.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
-        
+            self.current_dataset.err_data = err_data
+
+        self.current_dataset.qx_data = qx_data
+        self.current_dataset.qy_data = qy_data
+        self.current_dataset.q_data = q_data
+        self.current_dataset.mask = mask
+
+        self.current_dataset.x_bins = x_bins
+        self.current_dataset.y_bins = y_bins
+
+        self.current_dataset.xmin = xmin
+        self.current_dataset.xmax = xmax
+        self.current_dataset.ymin = ymin
+        self.current_dataset.ymax = ymax
+
+        self.current_datainfo.source.wavelength = wavelength
+
         # Store pixel size in mm
-        detector.pixel_size.x = pixel_x
-        detector.pixel_size.y = pixel_y
-        
+        self.current_datainfo.detector[0].pixel_size.x = pixel_x
+        self.current_datainfo.detector[0].pixel_size.y = pixel_y
+
         # Store the sample to detector distance
-        detector.distance = distance
-        
+        self.current_datainfo.detector[0].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:
@@ -338,30 +312,23 @@
                     cos_th = qx_data / diag
                     sin_th = qy_data / diag
-                    output.dqx_data = np.sqrt((dqx_data * cos_th) * \
+                    self.current_dataset.dqx_data = np.sqrt((dqx_data * cos_th) * \
                                                  (dqx_data * cos_th) \
                                                  + (dqy_data * sin_th) * \
                                                   (dqy_data * sin_th))
-                    output.dqy_data = np.sqrt((dqx_data * sin_th) * \
+                    self.current_dataset.dqy_data = np.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
+                    self.current_dataset.dqx_data = dqx_data
+                    self.current_dataset.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}")
-    
+        self.current_dataset.xaxis("\\rm{Q_{x}}", 'A^{-1}')
+        self.current_dataset.yaxis("\\rm{Q_{y}}", 'A^{-1}')
+        self.current_dataset.zaxis("\\rm{Intensity}", "cm^{-1}")
+
         # Store loading process information
-        output.meta_data['loader'] = self.type_name
-
-        return output
+        self.current_datainfo.meta_data['loader'] = self.type_name
+
+        self.send_to_output()
