Index: DataLoader/loader.py
===================================================================
--- DataLoader/loader.py	(revision 579ba85b3ae066f0c232974fcfbc64c128eec44f)
+++ DataLoader/loader.py	(revision daa56d02ac884aa84b81111db375d2dab7e1edcf)
@@ -1,28 +1,62 @@
-# This program is public domain
 """
-    @organization: Module loader contains class Loader which uses 
-    some readers to return values contained in a file readed.
-    @ author : Paul Kienzler
-    @modifiied by gervaise alina
+    File handler to support different file extensions.
+    Uses reflectometry's registry utility.
 """
-import imp,os,sys
+
+"""
+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
+"""
+
+from data_util.registry import ExtensionRegistry
+import os 
+import sys
 import logging
-import os.path
-logging.basicConfig(level=logging.ERROR,
-                    format='%(asctime)s %(levelname)s %(message)s',
-                    filename='test_log.txt',
-                    filemode='w')
+import imp
+import time
 
-def _findReaders(dir):
-    # List of plugin objects
-    plugins = []
-    # Go through files in plug-in directory
-    try:
+class Registry(ExtensionRegistry):
+    """
+        Registry class for file format extensions.
+        Readers and writers are supported.
+    """
+    
+    def __init__(self):
+        super(Registry, self).__init__()
         
-        list = os.listdir(dir)
-        for item in list:
+        ## Writers
+        self.writers = {}
+        
+        ## Creation time, for testing
+        self._created = time.time()
+        
+        # Find internal readers
+        try:
+            cwd = os.path.split(__file__)[0]
+        except:
+            cwd = os.getcwd()
+            logging.error("Registry: could not find the installed reader's directory\n %s" % sys.exc_value)
             
-            toks = os.path.splitext(os.path.basename(item))
-            if toks[1]=='.py' and not toks[0]=='__init__':
+        dir = os.path.join(cwd, 'readers')
+        n = self.find_plugins(dir)
+        logging.info("Loader found %i readers" % n)
+        
+    def find_plugins(self, dir):
+        """
+            Find readers in a given directory
+            
+            @param dir: directory to search into
+            @return: number of readers found
+        """
+        readers_found = 0
+        for item in os.listdir(dir):
+            full_path = os.path.join(dir, item)
+            if os.path.isfile(full_path) and item.endswith('.py'):
+                toks = os.path.splitext(os.path.basename(item))
                 name = toks[0]
                 path = [os.path.abspath(dir)]
@@ -33,223 +67,124 @@
                     if hasattr(module, "Reader"):
                         try:
-                            plugins.append(module.Reader())
+                            # Find supported extensions
+                            loader = module.Reader()
+                            for ext in loader.ext:
+                                if ext not in self.loaders:
+                                    self.loaders[ext] = []
+                                self.loaders[ext].insert(0,loader.read)
+                            readers_found += 1
+                            
+                            # Check whether writing is supported
+                            if hasattr(loader, 'write'):
+                                for ext in loader.ext:
+                                    if ext not in self.writers:
+                                        self.writers[ext] = []
+                                    self.writers[ext].insert(0,loader.write)
                         except:
-                            logging.error("Error accessing Reader in %s\n  %s" % (name, sys.exc_value))
+                            logging.error("Loader: Error accessing Reader in %s\n  %s" % (name, sys.exc_value))
                 except :
-                    logging.error("Error importing %s\n  %s" % (name, sys.exc_value))
+                    logging.error("Loader: Error importing %s\n  %s" % (name, sys.exc_value))
                 finally:
                     if not file==None:
                         file.close()
-    except:
-        # Should raise and catch at a higher level and display error on status bar
-        pass   
-    return plugins
+        return readers_found 
 
+    def lookup_writers(self, path):
+        """
+        Return the loader associated with the file type of path.
+        
+        Raises ValueError if file type is not known.
+        """        
+        # Find matching extensions
+        extlist = [ext for ext in self.extensions() if path.endswith(ext)]
+        # Sort matching extensions by decreasing order of length
+        extlist.sort(lambda a,b: len(a)<len(b))
+        # Combine loaders for matching extensions into one big list
+        writers = []
+        for L in [self.writers[ext] for ext in extlist]:
+            writers.extend(L)
+        # Remove duplicates if they exist
+        if len(writers) != len(set(writers)):
+            result = []
+            for L in writers:
+                if L not in result: result.append(L)
+            writers = L
+        # Raise an error if there are no matching extensions
+        if len(writers) == 0:
+            raise ValueError, "Unknown file type for "+path
+        # All done
+        return writers
 
+    def save(self, path, data, format=None):
+        """
+        Call the writer for the file type of path.
+
+        Raises ValueError if no writer is available.
+        Raises KeyError if format is not available.
+        May raise a writer-defined exception if writer fails.        
+        """
+        if format is None:
+            writers = self.lookup_writers(path)
+        else:
+            writers = self.writers[format]
+        for fn in writers:
+            try:
+                return fn(path, data)
+            except:
+                pass # give other loaders a chance to succeed
+        # If we get here it is because all loaders failed
+        raise # reraises last exception
+
+        
 class Loader(object):
     """
-        Loader class extracts data from a given file.
-        This provides routines for opening files based on extension,
-        and readers built-in file extensions.
-        It uses functionalities for class Load
-        @note: For loader to operate properly each readers used should 
-        contain a class name "Reader" that contains a field call ext.
-        Can be used as follow:
-        L=Loader()
-        self.assertEqual(l.__contains__('.tiff'),True)
-        #Recieves data 
-        data=L.load(path)
+        Utility class to use the Registry as a singleton.
     """
-    #Store instance of class Load
-    __load = None
+    ## Registry instance
+    __registry = Registry()
     
+    def load(self, file, format=None):
+        """
+            Load a file
+            
+            @param file: file name (path)
+            @param format: specified format to use (optional)
+            @return: DataInfo object
+        """
+        return self.__registry.load(file, format)
     
-    class Load(object):
+    def save(self, file, data, format):
+        """
+            Save a DataInfo object to file
+            @param file: file name (path)
+            @param data: DataInfo object
+            @param format: format to write the data in 
+        """
+        return self.__registry.save(file, data, format)
+        
+    def _get_registry_creation_time(self):
+        """
+            Internal method used to test the uniqueness
+            of the registry object
+        """
+        return self.__registry._created
     
-        def __init__(self):
-            #Dictionary containing readers and extension as keys
-            self.readers = {}
-            #Load all readers in plugins
-            
-            #TODO: misuse of __setitem__
-            #TODO: this bad call is done twice: here, and in Loader.__init__
-            #self.__setitem__()
-            
-            
-        def __setitem__(self,dir=None, ext=None, reader=None):
-            """
-                __setitem__  sets in a dictionary(self.readers) a given reader
-                with a file extension that it can read.
-                @param ext: extension given of type string
-                @param reader:instance Reader class
-                @param dir: directory name where plugins readers will be saved
-                @raise : ValueError will be raise if a "plugins" directory is not found
-                and the user didn't add a reader as parameter or if the user didn't 
-                add a reader as a parameter and plugins directory doesn't contain
-                plugin reader.
-                if an extension is not specified and a reader does not contain a field
-                ext , a warning is printed in test_log.txt file.
-                @note: when called without parameters __setitem__ will try to load
-                readers inside a "readers" directory 
-                if call with a directory name will try find readers 
-                from that directory "dir"
-            """
-            if dir==None:
-                dir = 'readers'
-                
-            #TODO Probably name the new path something else...
-            
-            #TODO: The whole concept of plug-ins was missed here.
-            # First we want to always load the reader we have (in 'readers')
-            # and THEN we want to add any additional readers found in
-            # a pre-defined plug-in path (that path should be a variable).
-            dir=os.path.join(os.path.dirname(os.path.abspath(__file__)),dir)
-            
-            if (reader==None and  ext==None) or dir:#1st load
-                plugReader=None
-                if os.path.isdir(dir):
-                    plugReader=_findReaders(dir)# import all module in plugins
-                
-                #TODO The following just doesn't make sense
-                # ../C:\Python25\lib... ????
-                if os.path.isdir('../'+dir):
-                    plugReader=_findReaders('../'+dir)
- 
-                
-                if plugReader !=None:
-                    list=[]
-                    for preader in plugReader:# for each modules takes list of extensions
-                        #TODO should use hasattr rather than a try/except block
-                        try:
-                            list=preader.ext
-                        except AttributeError,msg:
-                            logging.warning(msg)
-                            pass
-                            #raise  AttributeError," %s instance has no attribute 'ext'"\
-                            #%(preader.__class__)
-                        if list !=[]:
-                            for item in list:
-                                ext=item
-                                if ext not in self.readers:#assign extension with its reader
-                                    self.readers[ext] = []
-                                self.readers[ext].insert(0,preader)
-            #Reader and extension are given
-            elif reader !=None and  ext !=None:
-                if ext not in self.readers:
-                    self.readers[ext] = []
-                self.readers[ext].insert(0,reader)
-            elif reader!=None:
-                #only reader is receive try to find a field ext
-                try:
-                    list=preader.ext
-                except:
-                    raise AttributeError," Reader instance has no attribute 'ext'"
-                for item in list:
-                
-                    ext=item
-                    if ext not in self.readers:#assign extension with its reader
-                        self.readers[ext] = []
-                    self.readers[ext].insert(0,reader)
-
-            else:
-                raise ValueError,"missing reader"
-                
-            
-        def __getitem__(self, ext):
-            """
-                __getitem__ get a list of readers that can read a file with that extension
-                @param ext: file extension
-                @return self.readers[ext]:list of readers that can read a file 
-                with that extension
-            """
-            return self.readers[ext]
-            
-        def __contains__(self, ext):
-            """
-                @param ext:file extension
-                @return: True or False whether there is a reader file with that extension
-            """
-            return ext in self.readers
+    def find_plugins(self, dir):
+        """
+            Find plugins in a given directory
+            @param dir: directory to look into to find new readers/writers
+        """
+        return self.__registry.find_plugins(dir)
+    
+        
+if __name__ == "__main__": 
+    logging.basicConfig(level=logging.INFO,
+                        format='%(asctime)s %(levelname)s %(message)s',
+                        filename='loader.log',
+                        filemode='w')
+    l = Loader()
+    data = l.load('test/cansas1d.xml')
+    l.save('test_file.xml', data)
         
         
-        def formats(self, name=True, ext=False):
-            """
-            Return a list of the registered formats.  If name=True then
-            named formats are returned.  If ext=True then extensions
-            are returned.
-            """
-            names = [a for a in self.readers.keys() if not a.startswith('.')]
-            exts = [a for a in self.readers.keys() if a.startswith('.')]
-            names.sort()
-            exts.sort()
-            ret = []
-            if name: ret += names
-            if ext: ret += exts
-            return ret
-            
-        def lookup(self, path):
-            """
-            Return the loader associated with the file type of path.
-            """        
-            file = os.path.basename(path)
-            idx = file.find('.')
-            ext = file[idx:] if idx >= 0 else ''
-           
-            try:
-                return self.readers[ext]
-            except:
-                logging.warning("Unknown file type '%s'"%ext)
-                raise RuntimeError, "Unknown file type '%s'"%ext
-                
-       
-        
-        def load(self, path, format=None):
-            """
-                Call reader for the file type of path.
-                @param path: path to file to load
-                @param format: extension of file to load
-                @return Data if sucessful
-                  or None is not reader was able to read that file
-                Raises ValueError if no reader is available.
-                May raise a loader-defined exception if loader fails.
-            """
-            try:
-                os.path.isfile( os.path.abspath(path)) 
-            except:
-                raise ValueError," file path unknown"
-            
-            if format is None:
-                try:
-                    readers = self.lookup(path)
-                except :
-                    raise 
-            else:
-                readers = self.readers[format]
-            if readers!=None:
-                for fn in readers:
-                    try:
-                        value=fn.read(path)
-                        return value
-                    except:
-                        logging.error("Load Error: %s"% (sys.exc_value))
-            else:
-                raise ValueError,"Loader contains no reader"
-                        
-                         
-    def __init__(self):
-        """ Create singleton instance """
-        # Check whether we already have an instance
-        if Loader.__load is None:
-            # Create and remember instance
-            Loader.__load = Loader.Load()
-            Loader.__load.__setitem__()
-        # Store instance reference as the only member in the handle
-        self.__dict__['_Loader__load'] = Loader.__load
-
-    def __getattr__(self, attr):
-        """ Delegate access to implementation """
-        return getattr(self.__load, attr)
-
-    def __setattr__(self, attr, value):
-        """ Delegate access to implementation """
-        return setattr(self.__load, attr, value)
+    
Index: DataLoader/notes.txt
===================================================================
--- DataLoader/notes.txt	(revision daa56d02ac884aa84b81111db375d2dab7e1edcf)
+++ DataLoader/notes.txt	(revision daa56d02ac884aa84b81111db375d2dab7e1edcf)
@@ -0,0 +1,2 @@
+- Need support for images. tiff_reader.py needs to be tested.
+- Need support for zip file plugins for when we use py2exe.
Index: DataLoader/plugins/TXT2_Reader.py
===================================================================
--- DataLoader/plugins/TXT2_Reader.py	(revision 16d8e5fb43348001cacbc6967a6922266e68fe6e)
+++ 	(revision )
@@ -1,131 +1,0 @@
-# class Loader  to load any king of file
-import wx
-import string,numpy
-import logging
-class ReaderInfo:
-    """
-        This class is a container of data. It stores values read from files
-    """
-    ## Wavelength [A]
-    wavelength = 0.0
-    ## Number of x bins
-    xbins = 128
-    ## Number of y bins
-    ybins = 128
-    ## Beam center X [pixel number]
-    center_x = 65
-    ## Beam center Y [pixel number]
-    center_y = 65
-    ## Distance from sample to detector [m]
-    distance = 11.0
-    ## Qx values [A-1]
-    x_vals = []
-    ## Qy xalues [A-1]
-    y_vals = []
-    ## Qx min
-    xmin = 0.0
-    ## Qx max
-    xmax = 1.0
-    ## Qy min
-    ymin = 0.0
-    ## Qy max
-    ymax = 1.0
-    ## Image
-    image = None
-    ## Pixel size
-    pixel_size = 0.5
-    ## x coordinate
-    x=[]
-    ##y coordinate
-    y=[]
-    ##dx error on y
-    dx=None
-    ## dy error on y
-    dy=None
-    ## Error on each pixel
-    error = None
-    ##type of data
-    type=""
-    ##z
-    Z=None
-
-class Reader:
-    """
-        This class is loading values from given file or value giving by the user
-        should be able to read only 2 columns of data
-    """
-    ext=['.txt','.dat'] 
-    def _init_(self,x=None,y=None,dx=None,dy=None):
-        # variable to store loaded values
-        self.x = x
-        self.y = y
-        self.dx = dx
-        self.dy = dy
-        
-    def read(self,path, format=None):
-        """ Store the values loaded from file in local variables """
-        if not path == None:
-            read_it = False
-             
-            for item in self.ext:
-                if path.lower().find(item)>=0:
-                    read_it = True
-            #print "this is the flag",read_it, path.lower()
-            if read_it==False:
-                return None
-            else:
-                try:
-                    input_f =  open(path,'r')
-                except :
-                    raise  RuntimeError,"TXT2_Reader cannot open %s"%(path)
-                buff = input_f.read()
-                lines = buff.split('\n')
-                self.x=[]
-                self.y=[]
-                self.dx = [] 
-                self.dy=[]
-                for line in lines:
-                    toks = line.split()
-                    try:
-                        x = float(toks[0])
-                        self.x.append(x)
-                    except:
-                        pass
-                        #print "READ ERROR", line
-                    try:
-                        y = float(toks[1])
-                        self.y.append(y)
-                    except:
-                        pass
-                        #print "READ ERROR", line
-                    try:
-                        dy=float(toks[2])
-                        self.dy.append(dy)
-    
-                    except:
-                        pass
-                        #print "READ ERROR", line
-    
-                if(( self.x==[])or (self.y==[])) or (self.dy !=[]):
-                    #print "went here"
-                    #return value
-                    raise ValueError, "TXT2_Reader can't read %s"%path
-                else:
-                    #msg="R1 reading: \n"+"this x :"+ str(self.x) +"\n"+"this y:"+str(self.y)+"\n"+"this dy :"+str(self.dy)+"\n"
-                    #return msg
-                    logging.info("TXT2_Reader reading  %s\n" %path)
-                    output = ReaderInfo()
-                    output.x    = self.x
-                    output.y    = self.y
-                    output.type = "1D"
-                    
-                    return output
-        return None
-   
-       
-    
-if __name__ == "__main__": 
-    read= Reader()
-    read.load("testdata_line.txt")
-    
-            
Index: DataLoader/plugins/TXT3_Reader.py
===================================================================
--- DataLoader/plugins/TXT3_Reader.py	(revision 16d8e5fb43348001cacbc6967a6922266e68fe6e)
+++ 	(revision )
@@ -1,133 +1,0 @@
-# class Loader  to load any king of file
-import wx
-import string,numpy
-import logging
-class ReaderInfo:
-    """
-        This class is a container of data. It stores values read from files
-    """
-    ## Wavelength [A]
-    wavelength = 0.0
-    ## Number of x bins
-    xbins = 128
-    ## Number of y bins
-    ybins = 128
-    ## Beam center X [pixel number]
-    center_x = 65
-    ## Beam center Y [pixel number]
-    center_y = 65
-    ## Distance from sample to detector [m]
-    distance = 11.0
-    ## Qx values [A-1]
-    x_vals = []
-    ## Qy xalues [A-1]
-    y_vals = []
-    ## Qx min
-    xmin = 0.0
-    ## Qx max
-    xmax = 1.0
-    ## Qy min
-    ymin = 0.0
-    ## Qy max
-    ymax = 1.0
-    ## Image
-    image = None
-    ## Pixel size
-    pixel_size = 0.5
-    ## x coordinate
-    x=[]
-    ##y coordinate
-    y=[]
-    ##dx error on y
-    dx=None
-    ## dy error on y
-    dy=None
-    ## Error on each pixel
-    error = None
-    ##type of data
-    type=""
-    ##z
-    Z=None
-class Reader:
-    """
-        This class is loading values from given file or value giving by the user
-    """
-    ext=['.txt','.dat']  
-    def _init_(self,filename=None,x=None,y=None,dx=None,dy=None):
-        # variable to store loaded values
-        self.x = x
-        self.y = y
-        self.dx = dx
-        self.dy = dy
-        self.filename = filename
-        
-        
-    def read(self,path, format=None):
-        """ Store the values loaded from file in local variables 
-            can read 3 columns of data
-        """
-        
-        if not path == None:
-            read_it = False
-            
-            for item in self.ext:
-                if path.lower().find(item)>=0:
-                    read_it = True
-            #print "this is the flag",read_it, path.lower()
-            if read_it==False:
-                return None
-            else:
-                try:
-                    input_f =  open(path,'r')
-                except :
-                    raise  RuntimeError,"TXT3_Reader cannot open %s"%(path)
-                buff = input_f.read()
-                lines = buff.split('\n')
-                self.x=[]
-                self.y=[]
-                self.dx = [] 
-                self.dy=[]
-                for line in lines:
-                    toks = line.split()
-                    try:  
-                        x = float(toks[0])
-                        y = float(toks[1]) 
-                        dy = float(toks[2])
-                       
-                        self.x.append(x)
-                        self.y.append(y)
-                        self.dy.append(dy)
-                   
-                    except:
-                        pass
-                        #print "READ ERROR", line
-            
-                    self.dx = numpy.zeros(len(self.x))
-                    # Sanity check
-                    if not len(self.x) == len(self.dx):
-                        raise ValueError, "x and dx have different length"
-                    if not len(self.y) == len(self.dy):
-                        raise ValueError, "y and dy have different length"
-               
-                if (self.x==[] or self.y==[])and (self.dy==[]):
-                    raise ValueError, "TXT3_Reader can't read %s"%path
-                else:
-                   
-                    logging.info ("TXT3_Reader reading %s \n" %(path))
-                      
-                    output = ReaderInfo()
-                    output.x    = self.x
-                    output.y    = self.y
-                    output.dy   = self.dy
-                    output.type = "1D"
-                    
-                    return output
-                
-        return None
-if __name__ == "__main__": 
-    read= Reader()
-    #read= Reader(filename="testdata_line.txt")
-    print read.load("test.dat")
-    
-    
-            
Index: DataLoader/plugins/test_reader.py
===================================================================
--- DataLoader/plugins/test_reader.py	(revision daa56d02ac884aa84b81111db375d2dab7e1edcf)
+++ DataLoader/plugins/test_reader.py	(revision daa56d02ac884aa84b81111db375d2dab7e1edcf)
@@ -0,0 +1,63 @@
+"""
+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, os
+from DataLoader.data_info import Data1D
+
+
+class Reader:
+    """
+        Test reader to check plugin functionality
+    """
+    ## File type
+    type = ["ASCII files (*.test)|*.test"]
+    ## List of allowed extensions
+    ext=['.test']  
+    
+    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, "ascii_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)
+                output = Data1D(x, y, dy=dy)
+                self.filename = output.filename = basename
+           
+                for line in lines:
+                    x  = numpy.append(x,  float(line)) 
+                    
+                output.x = x
+                return output
+        else:
+            raise RuntimeError, "%s is not a file" % path
+        return None
+    
+if __name__ == "__main__": 
+    reader = Reader()
+    output = reader.read("../test/test_data.test")
+    print output.x
+    
+    
+                        
Index: DataLoader/plugins/tiff_reader.py
===================================================================
--- DataLoader/plugins/tiff_reader.py	(revision 16d8e5fb43348001cacbc6967a6922266e68fe6e)
+++ 	(revision )
@@ -1,165 +1,0 @@
-
-import Image
-import math
-class ReaderInfo:
-    """
-        This class is a container of data. It stores values read from files
-    """
-    ## Wavelength [A]
-    wavelength = 0.0
-    ## Number of x bins
-    xbins = 128
-    ## Number of y bins
-    ybins = 128
-    ## Beam center X [pixel number]
-    center_x = 65
-    ## Beam center Y [pixel number]
-    center_y = 65
-    ## Distance from sample to detector [m]
-    distance = 11.0
-    ## Qx values [A-1]
-    x_vals = []
-    ## Qy xalues [A-1]
-    y_vals = []
-    ## Qx min
-    xmin = 0.0
-    ## Qx max
-    xmax = 1.0
-    ## Qy min
-    ymin = 0.0
-    ## Qy max
-    ymax = 1.0
-    ## Image
-    image = None
-    ## Pixel size
-    pixel_size = 0.5
-    ## x coordinate
-    x=[]
-    ##y coordinate
-    y=[]
-    ##dx error on y
-    dx=None
-    ## dy error on y
-    dy=None
-    ## Error on each pixel
-    error = None
-    ##type of data
-    type=""
-    ##z
-    Z=None
-
-class Reader:
-    """
-        Example data manipulation
-    """
-    ## File type
-    type = []
-    ## Extension
-    ext  = ['tif', 'jpg', '.png', 'jpeg', '.tiff', 'gif', 'bmp']    
-        
-    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:
-            import Image
-            import pylab
-            import copy
-            import numpy
-            
-            wavelength, distance, center_x, center_y, pixel = 10.0, 11.0, 65, 65, 1.0
-            
-            
-            
-            # Initialize 
-            x_vals = []
-            y_vals = [] 
-            ymin = None
-            ymax = None
-            xmin = None
-            xmax = None
-            Z = None
-        
-            try:
-                im = Image.open(filename)
-            except :
-                raise  RuntimeError,"cannot open %s"%(filename)
-            # Detector size should be 128x128, the file is 190x190
-            print "-> Image size:", im.size, im.format, im.mode
-            data = im.getdata()
-            x = numpy.zeros(im.size[0])
-            y = numpy.zeros(im.size[1])
-            X, Y = pylab.meshgrid(x, y)
-            Z = copy.deepcopy(X)
-            itot = 0
-            i_x = 0
-            i_y = 0
-            
-            # Qx and Qy vectors
-            for i_x in range(im.size[0]):
-                theta = (i_x-center_x+1)*pixel / distance / 100.0
-                qx = 4.0*math.pi/wavelength * math.sin(theta/2.0)
-                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(im.size[1]):
-                theta = (i_y-center_y+1)*pixel / distance / 100.0
-                qy = 4.0*math.pi/wavelength * math.sin(theta/2.0)
-                y_vals.append(qy)
-                if ymin==None or qy<ymin:
-                    ymin = qy
-                if ymax==None or qy>ymax:
-                    ymax = qy
-            
-            for val in data:
-                
-                try:
-                    value = float(val)
-                except:
-                    continue
-                
-                # Get bin number
-                if math.fmod(itot, im.size[0])==0:
-                    i_x = 0
-                    i_y += 1
-                else:
-                    i_x += 1
-                    
-                Z[im.size[1]-1-i_y][i_x] = value
-                
-                itot += 1
-                
-            output = ReaderInfo()
-            output.wavelength = wavelength
-            output.xbins      = im.size[0]
-            output.ybins      = im.size[1]
-            output.center_x   = center_x
-            output.center_y   = center_y
-            output.distance   = distance
-            output.x_vals     = x_vals
-            output.y_vals     = y_vals
-            output.xmin       = xmin
-            output.xmax       = xmax
-            output.ymin       = ymin
-            output.ymax       = ymax
-            output.image      = Z
-            output.pixel_size = pixel
-            output.type       ="2D"
-              
-            return output
-        
-        return None
-
-
Index: DataLoader/readers/ascii_reader.py
===================================================================
--- DataLoader/readers/ascii_reader.py	(revision 99d1af6082f75428716f6bace3bc5a668ba7a9b6)
+++ DataLoader/readers/ascii_reader.py	(revision daa56d02ac884aa84b81111db375d2dab7e1edcf)
@@ -13,4 +13,5 @@
 from DataLoader.data_info import Data1D
 
+# Check whether we have a converter available
 has_converter = True
 try:
@@ -116,10 +117,10 @@
                 # Sanity check
                 if has_error == True and not len(y) == len(dy):
-                    raise ValueError, "ascii_reader: y and dy have different length"
+                    raise RuntimeError, "ascii_reader: y and dy have different length"
 
                 # 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"
+                    raise RuntimeError, "ascii_reader: could not load file"
                
                 output.x = x
Index: DataLoader/readers/tiff_reader.py
===================================================================
--- DataLoader/readers/tiff_reader.py	(revision 8bd8ea439767ebb5cd5480a4da37e8e080d4f3df)
+++ DataLoader/readers/tiff_reader.py	(revision daa56d02ac884aa84b81111db375d2dab7e1edcf)
@@ -1,5 +1,20 @@
+"""
+    Image reader. Untested. 
+"""
 
-import math,logging
+"""
+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: 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:
@@ -8,117 +23,80 @@
     """
     ## File type
-    type = []
+    type = ["TIF files (*.tif)|*.tif",
+            "JPG files (*.jpg)|*.jpg",
+            "JPEG files (*.jpeg)|*.jpeg",
+            "PNG files (*.png)|*.png",
+            "TIFF files (*.tiff)|*.tiff",
+            "BMP files (*.bmp)|*.bmp",
+            "GIF files (*.gif)|*.gif",
+            ]
     ## Extension
-    ext  = ['tif', 'jpg', '.png', 'jpeg', '.tiff', 'gif', 'bmp']    
+    ext  = ['.tif', '.jpg', '.png', '.jpeg', '.tiff', '.gif', '.bmp']    
         
     def read(self, filename=None):
-        import Image
-        print "in tiff"
         """
             Open and read the data in a file
             @param file: path of the file
         """
+        try:
+            import Image
+        except:
+            raise RuntimeError, "tiff_reader: could not load file. Missing Image module."
         
-        read_it = False
-        for item in self.ext:
-            if filename.lower().find(item)>=0:
-                read_it = True
+        # 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]])
+        
+        # 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
                 
-        if read_it:
-            import Image
-            import pylab
-            import copy
-            import numpy
+            output.data[im.size[1]-1-i_y][i_x] = value
             
-            wavelength, distance, center_x, center_y, pixel = 10.0, 11.0, 65, 65, 1.0
-            
-            
-            
-            # Initialize 
-            x_vals = []
-            y_vals = [] 
-            ymin = None
-            ymax = None
-            xmin = None
-            xmax = None
-            Z = None
+            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
         
-            try:
-                im = Image.open(filename)
-            except :
-                raise  RuntimeError,"cannot open %s"%(filename)
-            # Detector size should be 128x128, the file is 190x190
-            print "-> Image size:", im.size, im.format, im.mode
-            data = im.getdata()
-            x = numpy.zeros(im.size[0])
-            y = numpy.zeros(im.size[1])
-            X, Y = pylab.meshgrid(x, y)
-            Z = copy.deepcopy(X)
-            itot = 0
-            i_x = 0
-            i_y = 0
-            
-            # Qx and Qy vectors
-            for i_x in range(im.size[0]):
-                theta = (i_x-center_x+1)*pixel / distance / 100.0
-                qx = 4.0*math.pi/wavelength * math.sin(theta/2.0)
-                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(im.size[1]):
-                theta = (i_y-center_y+1)*pixel / distance / 100.0
-                qy = 4.0*math.pi/wavelength * math.sin(theta/2.0)
-                y_vals.append(qy)
-                if ymin==None or qy<ymin:
-                    ymin = qy
-                if ymax==None or qy>ymax:
-                    ymax = qy
-            
-            for val in data:
-                
-                try:
-                    value = float(val)
-                except:
-                    continue
-                
-                # Get bin number
-                if math.fmod(itot, im.size[0])==0:
-                    i_x = 0
-                    i_y += 1
-                else:
-                    i_x += 1
-                    
-                Z[im.size[1]-1-i_y][i_x] = value
-                
-                itot += 1
-            from readInfo import ReaderInfo      
-            output = ReaderInfo()
-            output.wavelength = wavelength
-            output.xbins      = im.size[0]
-            output.ybins      = im.size[1]
-            output.center_x   = center_x
-            output.center_y   = center_y
-            output.distance   = distance
-            output.x_vals     = x_vals
-            output.y_vals     = y_vals
-            output.xmin       = xmin
-            output.xmax       = xmax
-            output.ymin       = ymin
-            output.ymax       = ymax
-            output.image      = Z
-            output.pixel_size = pixel
-            output.x          = x_vals
-            output.y          = y_vals
-            output.type       ="2D"
-            logging.info("tiff_reader reading %s"%(filename))
-            
-            return output
+        return output
         
-        return None
 
 
Index: DataLoader/test/error_conditions.py
===================================================================
--- DataLoader/test/error_conditions.py	(revision f9474b5ebc4952a097cbc06f1276e8eba3e69c48)
+++ DataLoader/test/error_conditions.py	(revision daa56d02ac884aa84b81111db375d2dab7e1edcf)
@@ -9,7 +9,7 @@
         """
             self.s.load('blah.mat') on an unknown type
-            should raise a runtime exception
+            should raise a ValueError exception (thrown by data_util.registry)
         """
-        self.assertRaises(RuntimeError, self.s.load, 'angles_flat.mat')
+        self.assertRaises(ValueError, self.s.load, 'angles_flat.mat')
         
     def test_corrupt(self):
Index: DataLoader/test/sequence_tests.py
===================================================================
--- DataLoader/test/sequence_tests.py	(revision b99ac22702d9634282d084e8a7da3aa3064bccf2)
+++ DataLoader/test/sequence_tests.py	(revision daa56d02ac884aa84b81111db375d2dab7e1edcf)
@@ -29,2 +29,3 @@
     single_igor()
     single_abs()
+    print "Test passed"
Index: DataLoader/test/testLoad.py
===================================================================
--- DataLoader/test/testLoad.py	(revision b99ac22702d9634282d084e8a7da3aa3064bccf2)
+++ DataLoader/test/testLoad.py	(revision daa56d02ac884aa84b81111db375d2dab7e1edcf)
@@ -16,5 +16,13 @@
 import DataLoader
 from DataLoader.loader import  Loader
- 
+
+# Check whether we should test image loading on this system 
+HAS_IMAGE = False
+try:
+    import Image
+    HAS_IMAGE = True
+except:
+    print "IMAGE TESTS WILL NOT BE PERFORMED: MISSING PIL MODULE"
+    
 import os.path
 
@@ -24,17 +32,12 @@
         self.loader = Loader()
         
-        
     def test_singleton(self):
         """
             Testing whether Loader is truly a singleton
         """
-        # Set a new data member
-        self.loader._test_data_member = 1.45
-        
         # Create a 'new' Loader
         b = Loader()
-        
-        # Test that the new loader has the new data member
-        self.assertEqual(b._test_data_member, self.loader._test_data_member)
+        self.assertEqual(self.loader._get_registry_creation_time(),
+                         b._get_registry_creation_time())
 
 class testLoader(unittest.TestCase):
@@ -53,5 +56,5 @@
     def testLoad0(self):
         """test reading empty file"""
-        self.assertEqual(self.L.load('empty.txt'),None)
+        self.assertRaises(RuntimeError, self.L.load, 'empty.txt')
         
     def testLoad1(self):
@@ -87,4 +90,19 @@
             self.assertEqual(output.dy[i],dy[i])
        
+    def testLoad2_uppercase(self):
+        """Testing loading a txt file of 3 columns"""
+        output= self.L.load('test_3_columns.TXT') 
+        x=[0,0.204082,0.408163,0.612245,0.816327,1.02041,1.22449]    
+        y=[2.83954,3.44938,5.82026,5.27591,5.2781,5.22531,7.47487]
+        dx=[]
+        dy=[0.6,0.676531,0.753061,0.829592,0.906122,0.982653,1.05918]
+        self.assertEqual(len(output.x),len(x))
+        self.assertEqual(len(output.y),len(y))
+        self.assertEqual(len(output.dy),len(dy))
+        for i in range(len(x)):
+            self.assertEqual(output.x[i],x[i])
+            self.assertEqual(output.y[i],y[i])
+            self.assertEqual(output.dy[i],dy[i])
+       
     
     def testload3(self):
@@ -92,4 +110,19 @@
         #tested good file.asc
         output= self.L.load('MAR07232_rest.ASC') 
+        self.assertEqual(output.xmin,-0.018558945804750416)
+        self.assertEqual(output.xmax, 0.016234058202440633,)
+        self.assertEqual(output.ymin,-0.01684257151702391)
+        self.assertEqual(output.ymax,0.017950440578015116)
+       
+        #tested corrupted file.asc
+        try:self.L.load('AR07232_rest.ASC')
+        except ValueError,msg:
+           #logging.log(10,str(msg))
+           logging.error(str(msg))
+
+    def testload3_lowercase(self):
+        """ Testing loading Igor data"""
+        #tested good file.asc
+        output= self.L.load('MAR07232_rest.asc') 
         self.assertEqual(output.xmin,-0.018558945804750416)
         self.assertEqual(output.xmax, 0.016234058202440633,)
@@ -118,23 +151,19 @@
     def testload5(self):
         """ Testing loading image file"""
-        output=self.L.load('angles_flat.png')
-        self.assertEqual(output.xbins ,200)
+        if HAS_IMAGE:
+            output=self.L.load('angles_flat.png')
+            self.assertEqual(output.xbins ,200)
         
     def testload6(self):
         """test file with unknown extension"""
-        try:self.L.load('hello.missing')
-        except RuntimeError,msg:
-           self.assertEqual( str(msg),"Unknown file type '.missing'")
-        else: raise ValueError,"No error raised for missing extension"
+        self.assertRaises(ValueError, self.L.load, 'hello.missing')
         
-        #self.L.lookup('hello.missing')
-        try: self.L.lookup('hello.missing')
-        except RuntimeError,msg:
-           self.assertEqual( str(msg),"Unknown file type '.missing'")
-        else: raise ValueError,"No error raised for missing extension"
+        # Lookup is not supported as a public method
+        #self.assertRaises(ValueError, self.L.lookup, 'hello.missing')
+        
         
     def testload7(self):
         """ test file containing an image but as extension .txt"""
-        self.assertEqual(self.L.load('angles_flat.txt'),None)
+        self.assertRaises(RuntimeError, self.L.load, 'angles_flat.txt')
 
 if __name__ == '__main__':
Index: DataLoader/test/test_data.test
===================================================================
--- DataLoader/test/test_data.test	(revision daa56d02ac884aa84b81111db375d2dab7e1edcf)
+++ DataLoader/test/test_data.test	(revision daa56d02ac884aa84b81111db375d2dab7e1edcf)
@@ -0,0 +1,1 @@
+1234.0
Index: DataLoader/test/testplugings.py
===================================================================
--- DataLoader/test/testplugings.py	(revision 4c00964bdd074de333f3ea90840473f22102bb04)
+++ DataLoader/test/testplugings.py	(revision daa56d02ac884aa84b81111db375d2dab7e1edcf)
@@ -4,52 +4,34 @@
 
 import unittest
-import math
-import DataLoader
-from DataLoader.loader import  Loader
-from DataLoader.readers import TXT3_Reader,TXT2_Reader
-from DataLoader.readers import IgorReader,danse_reader,tiff_reader
-import os.path
-import os 
-import logging
-logging.basicConfig(level=logging.DEBUG,
-                    format='%(asctime)s %(levelname)s %(message)s',
-                    filename='test_log.txt',
-                    filemode='w')
+from DataLoader.loader import  Loader, Registry
 class testLoader(unittest.TestCase):
     
-    try:L=Loader()
-    except AttributeError,msg:
-        logging.warning(msg)
+    def setUp(self):
+        self.L=Loader()
+        self.L.find_plugins('../plugins')
+            
     def testplugin(self):
-        """ test loading with readers"""
+        """ 
+            test loading with a test reader only 
+            found in the plugins directory
+        """
+        output = self.L.load('test_data.test')
+        self.assertEqual(output.x[0], 1234.)
         
-        self.assertEqual(self.L.__contains__('.tiff'),True)
-        self.assertEqual(self.L.__contains__('.png'),True)
-        self.assertEqual(self.L.__contains__('.txt'),True)
-         #tested corrupted file.asc
-        try:self.L.load('MAR07232_rest.ASC')
-        except AttributeError,msg:
-           #logging.log(10,str(msg))
-           logging.warning(str(msg))
-    def testplugin1(self):
-        """ test loading with plugging"""
-        self.L.__setitem__(dir='plugins')
-        read3=IgorReader.Reader()
-        self.L.__setitem__('plugins','.ASC',read3)
-        self.assertEqual(self.L.__contains__('.ASC'),True)
-        #Testing loading a txt file of 2 columns, the only reader should be read1 
-        output=self.L.load('test_2_columns.txt') 
-        x=[2.83954,0.204082,0.408163,0.612245,0.816327,1.02041,1.22449,1.42857,1.63265]
-        y=[0.6,3.44938, 5.82026,5.27591,5.2781,5.22531,7.47487,7.85852,10.2278]
-        dx=[]
-        dy=[]
-        self.assertEqual(len(output.x),len(x))
-        self.assertEqual(len(output.y),len(y))
+class testRegistry(unittest.TestCase):
+    
+    def setUp(self):
+        self.L=Registry()
+        self.L.find_plugins('../plugins')
+            
+    def testplugin(self):
+        """ 
+            test loading with a test reader only 
+            found in the plugins directory
+        """
+        output = self.L.load('test_data.test')
+        self.assertEqual(output.x[0], 1234.)
+        self.assertTrue(self.L.loaders.has_key('.test'))
         
-        for i in range(len(x)):
-            self.assertEqual(output.x[i],x[i])
-            self.assertEqual(output.y[i],y[i])
-
-# How about actually executing the tests...
 if __name__ == '__main__':
     unittest.main()
