source: sasview/src/sas/sasgui/guiframe/local_perspectives/data_loader/data_loader.py @ 8dec7e7

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.2.2ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 8dec7e7 was 8dec7e7, checked in by lewis, 7 years ago

Raise DefaultReaderException? in NXcanSAS reader and handle correctly

  • Property mode set to 100644
File size: 10.4 KB
Line 
1
2"""
3plugin DataLoader responsible of loading data
4"""
5import os
6import sys
7import wx
8import logging
9
10logger = logging.getLogger(__name__)
11
12from sas.sascalc.dataloader.loader import Loader
13from sas.sascalc.dataloader.loader_exceptions import NoKnownLoaderException
14from sas.sasgui.guiframe.plugin_base import PluginBase
15from sas.sasgui.guiframe.events import StatusEvent
16from sas.sasgui.guiframe.gui_style import GUIFRAME
17from sas.sasgui.guiframe.gui_manager import DEFAULT_OPEN_FOLDER
18try:
19    # Try to find a local config
20    import imp
21    path = os.getcwd()
22    if(os.path.isfile("%s/%s.py" % (path, 'local_config'))) or \
23        (os.path.isfile("%s/%s.pyc" % (path, 'local_config'))):
24        fObj, path, descr = imp.find_module('local_config', [path])
25        config = imp.load_module('local_config', fObj, path, descr)
26    else:
27        # Try simply importing local_config
28        import local_config as config
29except:
30    # Didn't find local config, load the default
31    import sas.sasgui.guiframe.config as config
32
33if config is None:
34    import sas.sasgui.guiframe.config as config
35
36
37extension_list = []
38if config.APPLICATION_STATE_EXTENSION is not None:
39    extension_list.append(config.APPLICATION_STATE_EXTENSION)
40EXTENSIONS = config.PLUGIN_STATE_EXTENSIONS + extension_list
41PLUGINS_WLIST = config.PLUGINS_WLIST
42APPLICATION_WLIST = config.APPLICATION_WLIST
43
44
45class Plugin(PluginBase):
46
47    def __init__(self):
48        PluginBase.__init__(self, name="DataLoader")
49        # Default location
50        self._default_save_location = DEFAULT_OPEN_FOLDER
51        self.loader = Loader()
52        self._data_menu = None
53
54    def populate_file_menu(self):
55        """
56        get a menu item and append it under file menu of the application
57        add load file menu item and load folder item
58        """
59        # menu for data files
60        data_file_hint = "load one or more data in the application"
61        menu_list = [('&Load Data File(s)', data_file_hint, self.load_data)]
62        gui_style = self.parent.get_style()
63        style = gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
64        if style == GUIFRAME.MULTIPLE_APPLICATIONS:
65            # menu for data from folder
66            data_folder_hint = "load multiple data in the application"
67            menu_list.append(('&Load Data Folder', data_folder_hint,
68                              self._load_folder))
69        return menu_list
70
71    def load_data(self, event):
72        """
73        Load data
74        """
75        path = None
76        self._default_save_location = self.parent._default_save_location
77        if self._default_save_location is None:
78            self._default_save_location = os.getcwd()
79
80        cards = self.loader.get_wildcards()
81        temp = [APPLICATION_WLIST] + PLUGINS_WLIST
82        for item in temp:
83            if item in cards:
84                cards.remove(item)
85        wlist = '|'.join(cards)
86        style = wx.OPEN | wx.FD_MULTIPLE
87        dlg = wx.FileDialog(self.parent,
88                            "Choose a file",
89                            self._default_save_location, "",
90                            wlist,
91                            style=style)
92        if dlg.ShowModal() == wx.ID_OK:
93            file_list = dlg.GetPaths()
94            if len(file_list) >= 0 and file_list[0] is not None:
95                self._default_save_location = os.path.dirname(file_list[0])
96                path = self._default_save_location
97        dlg.Destroy()
98
99        if path is None or not file_list or file_list[0] is None:
100            return
101        self.parent._default_save_location = self._default_save_location
102        self.get_data(file_list)
103
104    def can_load_data(self):
105        """
106        if return True, then call handler to laod data
107        """
108        return True
109
110    def _load_folder(self, event):
111        """
112        Load entire folder
113        """
114        path = None
115        self._default_save_location = self.parent._default_save_location
116        if self._default_save_location is None:
117            self._default_save_location = os.getcwd()
118        dlg = wx.DirDialog(self.parent, "Choose a directory",
119                           self._default_save_location,
120                           style=wx.DD_DEFAULT_STYLE)
121        if dlg.ShowModal() == wx.ID_OK:
122            path = dlg.GetPath()
123            self._default_save_location = path
124        dlg.Destroy()
125        if path is not None:
126            self._default_save_location = os.path.dirname(path)
127        else:
128            return
129        file_list = self.get_file_path(path)
130        self.get_data(file_list)
131        self.parent._default_save_location = self._default_save_location
132
133    def load_error(self, error=None):
134        """
135        Pop up an error message.
136
137        :param error: details error message to be displayed
138        """
139        if error is not None or str(error).strip() != "":
140            dial = wx.MessageDialog(self.parent, str(error),
141                                    'Error Loading File',
142                                    wx.OK | wx.ICON_EXCLAMATION)
143            dial.ShowModal()
144
145    def get_file_path(self, path):
146        """
147        Receive a list containing folder then return a list of file
148        """
149        if os.path.isdir(path):
150            return [os.path.join(os.path.abspath(path), filename) for filename
151                    in os.listdir(path)]
152
153    def _process_data_and_errors(self, item, p_file, output, message):
154        """
155        Check to see if data set loaded with any errors. If so, append to
156            error message to be sure user knows the issue.
157        """
158        data_error = False
159        if hasattr(item, 'errors'):
160            for error_data in item.errors:
161                data_error = True
162                message += "\tError: {0}\n".format(error_data)
163        else:
164            logger.error("Loader returned an invalid object:\n %s" % str(item))
165            data_error = True
166
167        data = self.parent.create_gui_data(item, p_file)
168        output[data.id] = data
169        return output, message, data_error
170
171    def get_data(self, path, format=None):
172        """
173        """
174        file_errors = {}
175        output = {}
176        exception_occurred = False
177
178        for p_file in path:
179            basename = os.path.basename(p_file)
180            # Skip files that start with a period
181            if basename.startswith("."):
182                msg = "The folder included a potential hidden file - %s." \
183                      % basename
184                msg += " Do you wish to load this file as data?"
185                msg_box = wx.MessageDialog(None, msg, 'Warning',
186                                           wx.OK | wx.CANCEL)
187                if msg_box.ShowModal() == wx.ID_CANCEL:
188                    continue
189            _, extension = os.path.splitext(basename)
190            if extension.lower() in EXTENSIONS:
191                log_msg = "Data Loader cannot "
192                log_msg += "load: {}\n".format(str(p_file))
193                log_msg += "Please try to open that file from \"open project\""
194                log_msg += "or \"open analysis\" menu."
195                logger.info(log_msg)
196                file_errors[basename] = [log_msg]
197                continue
198
199            try:
200                message = "Loading {}...\n".format(p_file)
201                self.load_update(output=output, message=message, info="info")
202                temp = self.loader.load(p_file, format)
203                if not isinstance(temp, list):
204                    temp = [temp]
205                for item in temp:
206                    error_message = ""
207                    output, error_message, data_error = \
208                        self._process_data_and_errors(item,
209                                                      p_file,
210                                                      output,
211                                                      error_message)
212                    if data_error:
213                        if basename in file_errors.keys():
214                            file_errors[basename] += [error_message]
215                        else:
216                            file_errors[basename] = [error_message]
217                        self.load_update(output=output,
218                            message=error_message, info="warning")
219
220                self.load_update(output=output,
221                message="Loaded {}\n".format(p_file),
222                info="info")
223
224            except NoKnownLoaderException as e:
225                logging.error(e.message)
226                error_message = "Loading data failed!\n" + e.message
227                self.load_update(output=None, message=e.message, info="warning")
228                self.load_complete(output=None,
229                                   message=error_message,
230                                   info="error")
231            except:
232                logger.error(sys.exc_value)
233
234                error_message = "The Data file you selected could not be "
235                error_message += "loaded.\nMake sure the content of your file"
236                error_message += " is properly formatted.\n"
237                error_message += "When contacting the SasView team, mention the"
238                error_message += " following:\n"
239                error_message += "Error: " + str(sys.exc_info()[1])
240                file_errors[basename] = [error_message]
241                self.load_update(output=output, message=error_message,
242                                 info="warning")
243
244        if len(file_errors) > 0:
245            error_message = ""
246            for filename, error_array in file_errors.iteritems():
247                error_message += "The following errors occured whilst "
248                error_message += "loading {}:\n".format(filename)
249                for message in error_array:
250                    error_message += message + "\n"
251                error_message += "\n"
252            self.load_update(output=output, message=error_message, info="error")
253
254        self.load_complete(output=output, message="Loading data complete!",
255                           info="info")
256
257    def load_update(self, output=None, message="", info="warning"):
258        """
259        print update on the status bar
260        """
261        if message != "":
262            wx.PostEvent(self.parent, StatusEvent(status=message, info=info,
263                                                  type="progress"))
264
265    def load_complete(self, output, message="", info="warning"):
266        """
267         post message to status bar and return list of data
268        """
269        wx.PostEvent(self.parent, StatusEvent(status=message, info=info,
270                                              type="stop"))
271        if output is not None:
272            self.parent.add_data(data_list=output)
Note: See TracBrowser for help on using the repository browser.