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

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 dcb91cf was dcb91cf, checked in by lewis, 7 years ago

Make suggested changes

  • Property mode set to 100644
File size: 10.5 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                exception_occurred = True
226                logger.error(e.message)
227
228                error_message = "Loading data failed!\n" + e.message
229                self.load_update(output=None, message=e.message, info="warning")
230
231            except Exception as e:
232                exception_occurred = True
233                logger.error(e.message)
234
235                file_err = "The Data file you selected could not be "
236                file_err += "loaded.\nMake sure the content of your file"
237                file_err += " is properly formatted.\n"
238                file_err += "When contacting the SasView team, mention the"
239                file_err += " following:\n"
240                file_err += e.message
241                file_errors[basename] = [file_err]
242
243        if len(file_errors) > 0:
244            error_message = ""
245            for filename, error_array in file_errors.iteritems():
246                error_message += "The following errors occured whilst "
247                error_message += "loading {}:\n".format(filename)
248                for message in error_array:
249                    error_message += message + "\n"
250                error_message += "\n"
251            if not exception_occurred: # Some data loaded but with errors
252                self.load_update(output=output, message=error_message, info="error")
253
254        if not exception_occurred: # Everything loaded as expected
255            self.load_complete(output=output, message="Loading data complete!",
256                               info="info")
257        else:
258            self.load_complete(output=None, message=error_message, info="error")
259
260
261    def load_update(self, output=None, message="", info="warning"):
262        """
263        print update on the status bar
264        """
265        if message != "":
266            wx.PostEvent(self.parent, StatusEvent(status=message, info=info,
267                                                  type="progress"))
268
269    def load_complete(self, output, message="", info="warning"):
270        """
271         post message to status bar and return list of data
272        """
273        wx.PostEvent(self.parent, StatusEvent(status=message, info=info,
274                                              type="stop"))
275        if output is not None:
276            self.parent.add_data(data_list=output)
Note: See TracBrowser for help on using the repository browser.