source: sasview/DataLoader/loader.py @ 67e258c

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 67e258c was f118fe2f, checked in by Jae Cho <jhjcho@…>, 14 years ago

added cansa reader in addition to ascii reader when an error araised

  • Property mode set to 100644
File size: 13.6 KB
Line 
1
2#####################################################################
3#This software was developed by the University of Tennessee as part of the
4#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
5#project funded by the US National Science Foundation.
6#See the license text in license.txt
7#copyright 2008, University of Tennessee
8######################################################################
9
10"""
11    File handler to support different file extensions.
12    Uses reflectometry's registry utility.
13   
14    The default readers are found in the 'readers' sub-module
15    and registered by default at initialization time.
16   
17    To add a new default reader, one must register it in
18    the register_readers method found in readers/__init__.py.
19   
20    A utility method (find_plugins) is available to inspect
21    a directory (for instance, a user plug-in directory) and
22    look for new readers/writers.
23"""
24
25from data_util.registry import ExtensionRegistry
26import os 
27import sys
28import logging
29import time
30from zipfile import ZipFile
31
32# Default readers are defined in the readers sub-module
33import readers
34from readers import ascii_reader,cansas_reader
35
36class Registry(ExtensionRegistry):
37    """
38    Registry class for file format extensions.
39    Readers and writers are supported.
40    """
41   
42    def __init__(self):
43        super(Registry, self).__init__()
44       
45        ## Writers
46        self.writers = {}
47       
48        ## List of wildcards
49        self.wildcards = ['All (*.*)|*.*']
50       
51        ## Creation time, for testing
52        self._created = time.time()
53       
54        # Register default readers
55        readers.read_associations(self)
56       
57        #TODO: remove the following line when ready to switch to the new default readers
58        #readers.register_readers(self._identify_plugin)
59       
60        # Look for plug-in readers
61        self.find_plugins('plugins')
62
63       
64    def load(self, path, format=None):
65        """
66        Call the loader for the file type of path.
67
68        :param path: file path
69        :param format: explicit extension, to force the use of a particular reader
70
71        Defaults to the ascii (multi-column) reader
72        if no reader was registered for the file's
73        extension.   
74        """
75        try:
76            return super(Registry, self).load(path, format=format)
77        except:
78            try:
79                # No reader was found. Default to the ascii reader.
80                ascii_loader = ascii_reader.Reader()
81                return ascii_loader.read(path)
82            except:
83                cansas_loader = cansas_reader.Reader()
84                return cansas_loader.read(path)
85    def find_plugins(self, dir):
86        """
87        Find readers in a given directory. This method
88        can be used to inspect user plug-in directories to
89        find new readers/writers.
90       
91        :param dir: directory to search into
92       
93        :return: number of readers found
94        """
95        readers_found = 0
96       
97        # Check whether the directory exists
98        if not os.path.isdir(dir): 
99            logging.warning("DataLoader couldn't load from %s" % dir)
100            return readers_found
101       
102        for item in os.listdir(dir):
103            full_path = os.path.join(dir, item)
104            if os.path.isfile(full_path):
105               
106                # Process python files
107                if item.endswith('.py'):
108                    toks = os.path.splitext(os.path.basename(item))
109                    try:
110                        sys.path.insert(0, os.path.abspath(dir))
111                        module = __import__(toks[0], globals(), locals())
112                        if self._identify_plugin(module):
113                            readers_found += 1
114                    except :
115                        logging.error("Loader: Error importing %s\n  %s" % (item, sys.exc_value))
116                           
117                # Process zip files
118                elif item.endswith('.zip'):
119                    try:
120                        # Find the modules in the zip file
121                        zfile = ZipFile(item)
122                        nlist = zfile.namelist()
123                       
124                        sys.path.insert(0, item)
125                        for mfile in nlist:
126                            try:
127                                # Change OS path to python path
128                                fullname = mfile.replace('/', '.')
129                                fullname = os.path.splitext(fullname)[0]
130                                module = __import__(fullname, globals(), locals(), [""])
131                                if self._identify_plugin(module):
132                                    readers_found += 1
133                            except:
134                                logging.error("Loader: Error importing %s\n  %s" % (mfile, sys.exc_value))
135                           
136                    except:
137                        logging.error("Loader: Error importing %s\n  %s" % (item, sys.exc_value))
138                     
139        return readers_found
140   
141    def associate_file_type(self, ext, module):
142        """
143        Look into a module to find whether it contains a
144        Reader class. If so, APPEND it to readers and (potentially)
145        to the list of writers for the given extension
146       
147        :param ext: file extension [string]
148        :param module: module object
149        """
150        reader_found = False
151       
152        if hasattr(module, "Reader"):
153            try:
154                # Find supported extensions
155                loader = module.Reader()
156                if ext not in self.loaders:
157                    self.loaders[ext] = []
158                # Append the new reader to the list
159                self.loaders[ext].append(loader.read)
160
161                reader_found = True
162               
163                # Keep track of wildcards
164                type_name = module.__name__
165                if hasattr(loader, 'type_name'):
166                    type_name = loader.type_name
167                   
168                wcard = "%s files (*%s)|*%s" % (type_name, ext.lower(), ext.lower())
169                if wcard not in self.wildcards:
170                    self.wildcards.append(wcard)
171                           
172                # Check whether writing is supported
173                if hasattr(loader, 'write'):
174                    if ext not in self.writers:
175                        self.writers[ext] = []
176                    # Append the new writer to the list
177                    self.writers[ext].append(loader.write)
178                       
179            except:
180                logging.error("Loader: Error accessing Reader in %s\n  %s" % (module.__name__, sys.exc_value))
181        return reader_found
182
183    def associate_file_reader(self, ext, loader):
184        """
185        Append a reader object to readers
186       
187        :param ext: file extension [string]
188        :param module: reader object
189        """
190        reader_found = False
191       
192        try:
193            # Find supported extensions
194            if ext not in self.loaders:
195                self.loaders[ext] = []
196            # Append the new reader to the list
197            self.loaders[ext].append(loader.read)
198
199            reader_found = True
200           
201            # Keep track of wildcards
202            if hasattr(loader, 'type_name'):
203                type_name = loader.type_name
204               
205                wcard = "%s files (*%s)|*%s" % (type_name, ext.lower(), ext.lower())
206                if wcard not in self.wildcards:
207                    self.wildcards.append(wcard)
208                 
209        except:
210            logging.error("Loader: Error accessing Reader in %s\n  %s" % (module.__name__, sys.exc_value))
211        return reader_found
212
213   
214    def _identify_plugin(self, module):
215        """
216        Look into a module to find whether it contains a
217        Reader class. If so, add it to readers and (potentially)
218        to the list of writers.
219        :param module: module object
220       
221        """
222        reader_found = False
223       
224        if hasattr(module, "Reader"):
225            try:
226                # Find supported extensions
227                loader = module.Reader()
228                for ext in loader.ext:
229                    if ext not in self.loaders:
230                        self.loaders[ext] = []
231                    # When finding a reader at run time, treat this reader as the new
232                    # default
233                    self.loaders[ext].insert(0,loader.read)
234
235                    reader_found = True
236                   
237                    # Keep track of wildcards
238                    type_name = module.__name__
239                    if hasattr(loader, 'type_name'):
240                        type_name = loader.type_name
241                    wcard = "%s files (*%s)|*%s" % (type_name, ext.lower(), ext.lower())
242                    if wcard not in self.wildcards:
243                        self.wildcards.append(wcard)
244                           
245                # Check whether writing is supported
246                if hasattr(loader, 'write'):
247                    for ext in loader.ext:
248                        if ext not in self.writers:
249                            self.writers[ext] = []
250                        self.writers[ext].insert(0,loader.write)
251                       
252            except:
253                logging.error("Loader: Error accessing Reader in %s\n  %s" % (module.__name__, sys.exc_value))
254        return reader_found
255
256    def lookup_writers(self, path):
257        """
258        :return: the loader associated with the file type of path.
259       
260        :Raises ValueError: if file type is not known.
261        """       
262        # Find matching extensions
263        extlist = [ext for ext in self.extensions() if path.endswith(ext)]
264        # Sort matching extensions by decreasing order of length
265        extlist.sort(lambda a,b: len(a)<len(b))
266        # Combine loaders for matching extensions into one big list
267        writers = []
268        for L in [self.writers[ext] for ext in extlist]:
269            writers.extend(L)
270        # Remove duplicates if they exist
271        if len(writers) != len(set(writers)):
272            result = []
273            for L in writers:
274                if L not in result: result.append(L)
275            writers = L
276        # Raise an error if there are no matching extensions
277        if len(writers) == 0:
278            raise ValueError, "Unknown file type for "+path
279        # All done
280        return writers
281
282    def save(self, path, data, format=None):
283        """
284        Call the writer for the file type of path.
285
286        Raises ValueError if no writer is available.
287        Raises KeyError if format is not available.
288       
289        May raise a writer-defined exception if writer fails.       
290        """
291        if format is None:
292            writers = self.lookup_writers(path)
293        else:
294            writers = self.writers[format]
295        for fn in writers:
296            try:
297                return fn(path, data)
298            except:
299                pass # give other loaders a chance to succeed
300        # If we get here it is because all loaders failed
301        raise # reraises last exception
302
303       
304class Loader(object):
305    """
306    Utility class to use the Registry as a singleton.
307    """
308    ## Registry instance
309    __registry = Registry()
310   
311    def associate_file_type(self, ext, module):
312        """
313        Look into a module to find whether it contains a
314        Reader class. If so, append it to readers and (potentially)
315        to the list of writers for the given extension
316       
317        :param ext: file extension [string]
318        :param module: module object
319        """
320        return self.__registry.associate_file_type(ext, module)
321
322    def associate_file_reader(self, ext, loader):
323        """
324        Append a reader object to readers
325       
326        :param ext: file extension [string]
327        :param module: reader object
328        """
329        return self.__registry.associate_file_reader(ext, loader)
330
331    def load(self, file, format=None):
332        """
333        Load a file
334       
335        :param file: file name (path)
336        :param format: specified format to use (optional)
337        :return: DataInfo object
338        """
339        return self.__registry.load(file, format)
340   
341    def save(self, file, data, format):
342        """
343        Save a DataInfo object to file
344        :param file: file name (path)
345        :param data: DataInfo object
346        :param format: format to write the data in
347        """
348        return self.__registry.save(file, data, format)
349       
350    def _get_registry_creation_time(self):
351        """
352        Internal method used to test the uniqueness
353        of the registry object
354        """
355        return self.__registry._created
356   
357    def find_plugins(self, dir):
358        """
359        Find plugins in a given directory
360       
361        :param dir: directory to look into to find new readers/writers
362        """
363        return self.__registry.find_plugins(dir)
364   
365    def get_wildcards(self):
366        return self.__registry.wildcards
367       
368if __name__ == "__main__": 
369    logging.basicConfig(level=logging.INFO,
370                        format='%(asctime)s %(levelname)s %(message)s',
371                        filename='loader.log',
372                        filemode='w')
373    l = Loader()
374    data = l.load('test/cansas1d.xml')
375    l.save('test_file.xml', data, '.xml')
376   
377    print l.get_wildcards()
378       
379       
380   
Note: See TracBrowser for help on using the repository browser.