source: sasview/DataLoader/loader.py @ d831626

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since d831626 was daa56d0, checked in by Mathieu Doucet <doucetm@…>, 16 years ago

Mostly completed DataLoader?. Reimplemented using REFL registry as base class. Added writing capability and dynamic loading of readers (need zip file support for future py2exe use). All tests pass.

  • Property mode set to 100644
File size: 6.5 KB
Line 
1"""
2    File handler to support different file extensions.
3    Uses reflectometry's registry utility.
4"""
5
6"""
7This software was developed by the University of Tennessee as part of the
8Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
9project funded by the US National Science Foundation.
10
11See the license text in license.txt
12
13copyright 2008, University of Tennessee
14"""
15
16from data_util.registry import ExtensionRegistry
17import os 
18import sys
19import logging
20import imp
21import time
22
23class Registry(ExtensionRegistry):
24    """
25        Registry class for file format extensions.
26        Readers and writers are supported.
27    """
28   
29    def __init__(self):
30        super(Registry, self).__init__()
31       
32        ## Writers
33        self.writers = {}
34       
35        ## Creation time, for testing
36        self._created = time.time()
37       
38        # Find internal readers
39        try:
40            cwd = os.path.split(__file__)[0]
41        except:
42            cwd = os.getcwd()
43            logging.error("Registry: could not find the installed reader's directory\n %s" % sys.exc_value)
44           
45        dir = os.path.join(cwd, 'readers')
46        n = self.find_plugins(dir)
47        logging.info("Loader found %i readers" % n)
48       
49    def find_plugins(self, dir):
50        """
51            Find readers in a given directory
52           
53            @param dir: directory to search into
54            @return: number of readers found
55        """
56        readers_found = 0
57        for item in os.listdir(dir):
58            full_path = os.path.join(dir, item)
59            if os.path.isfile(full_path) and item.endswith('.py'):
60                toks = os.path.splitext(os.path.basename(item))
61                name = toks[0]
62                path = [os.path.abspath(dir)]
63                file = None
64                try:
65                    (file, path, info) = imp.find_module(name, path)
66                    module = imp.load_module( name, file, item, info )
67                    if hasattr(module, "Reader"):
68                        try:
69                            # Find supported extensions
70                            loader = module.Reader()
71                            for ext in loader.ext:
72                                if ext not in self.loaders:
73                                    self.loaders[ext] = []
74                                self.loaders[ext].insert(0,loader.read)
75                            readers_found += 1
76                           
77                            # Check whether writing is supported
78                            if hasattr(loader, 'write'):
79                                for ext in loader.ext:
80                                    if ext not in self.writers:
81                                        self.writers[ext] = []
82                                    self.writers[ext].insert(0,loader.write)
83                        except:
84                            logging.error("Loader: Error accessing Reader in %s\n  %s" % (name, sys.exc_value))
85                except :
86                    logging.error("Loader: Error importing %s\n  %s" % (name, sys.exc_value))
87                finally:
88                    if not file==None:
89                        file.close()
90        return readers_found
91
92    def lookup_writers(self, path):
93        """
94        Return the loader associated with the file type of path.
95       
96        Raises ValueError if file type is not known.
97        """       
98        # Find matching extensions
99        extlist = [ext for ext in self.extensions() if path.endswith(ext)]
100        # Sort matching extensions by decreasing order of length
101        extlist.sort(lambda a,b: len(a)<len(b))
102        # Combine loaders for matching extensions into one big list
103        writers = []
104        for L in [self.writers[ext] for ext in extlist]:
105            writers.extend(L)
106        # Remove duplicates if they exist
107        if len(writers) != len(set(writers)):
108            result = []
109            for L in writers:
110                if L not in result: result.append(L)
111            writers = L
112        # Raise an error if there are no matching extensions
113        if len(writers) == 0:
114            raise ValueError, "Unknown file type for "+path
115        # All done
116        return writers
117
118    def save(self, path, data, format=None):
119        """
120        Call the writer for the file type of path.
121
122        Raises ValueError if no writer is available.
123        Raises KeyError if format is not available.
124        May raise a writer-defined exception if writer fails.       
125        """
126        if format is None:
127            writers = self.lookup_writers(path)
128        else:
129            writers = self.writers[format]
130        for fn in writers:
131            try:
132                return fn(path, data)
133            except:
134                pass # give other loaders a chance to succeed
135        # If we get here it is because all loaders failed
136        raise # reraises last exception
137
138       
139class Loader(object):
140    """
141        Utility class to use the Registry as a singleton.
142    """
143    ## Registry instance
144    __registry = Registry()
145   
146    def load(self, file, format=None):
147        """
148            Load a file
149           
150            @param file: file name (path)
151            @param format: specified format to use (optional)
152            @return: DataInfo object
153        """
154        return self.__registry.load(file, format)
155   
156    def save(self, file, data, format):
157        """
158            Save a DataInfo object to file
159            @param file: file name (path)
160            @param data: DataInfo object
161            @param format: format to write the data in
162        """
163        return self.__registry.save(file, data, format)
164       
165    def _get_registry_creation_time(self):
166        """
167            Internal method used to test the uniqueness
168            of the registry object
169        """
170        return self.__registry._created
171   
172    def find_plugins(self, dir):
173        """
174            Find plugins in a given directory
175            @param dir: directory to look into to find new readers/writers
176        """
177        return self.__registry.find_plugins(dir)
178   
179       
180if __name__ == "__main__": 
181    logging.basicConfig(level=logging.INFO,
182                        format='%(asctime)s %(levelname)s %(message)s',
183                        filename='loader.log',
184                        filemode='w')
185    l = Loader()
186    data = l.load('test/cansas1d.xml')
187    l.save('test_file.xml', data)
188       
189       
190   
Note: See TracBrowser for help on using the repository browser.