source: sasview/invariantview/src/sans/perspectives/invariant/invariant.py @ 64b4f0f

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 64b4f0f was 64b4f0f, checked in by Gervaise Alina <gervyh@…>, 13 years ago

add icon for help window

  • Property mode set to 100644
File size: 12.8 KB
Line 
1
2
3
4################################################################################
5#This software was developed by the University of Tennessee as part of the
6#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
7#project funded by the US National Science Foundation.
8#
9#See the license text in license.txt
10#
11#copyright 2009, University of Tennessee
12################################################################################
13
14
15import sys
16import wx
17import copy
18import logging
19
20from sans.guiframe.dataFitting import Data1D
21from sans.guiframe.events import NewPlotEvent
22from sans.guiframe.gui_style import GUIFRAME_ID
23from .invariant_state import Reader as reader
24from sans.dataloader.loader import Loader
25from .invariant_panel import InvariantPanel
26from sans.guiframe.plugin_base import PluginBase
27
28class Plugin(PluginBase):
29    """
30    This class defines the interface for invariant Plugin class
31    that can be used by the gui_manager.       
32    """
33   
34    def __init__(self, standalone=False):
35        PluginBase.__init__(self, name="Invariant", standalone=standalone)
36       
37        #dictionary containing data name and error on dy of that data
38        self.err_dy = {}
39       
40        #default state objects
41        self.state_reader = None 
42        self._extensions = '.inv'
43        self.temp_state = None 
44        self.__data = None 
45       
46        # Log startup
47        logging.info("Invariant plug-in started")
48       
49    def help(self, evt):
50        """
51        Show a general help dialog.
52        """
53        from help_panel import  HelpWindow
54        frame = HelpWindow(None, -1) 
55        if hasattr(frame, "IsIconized"):
56            if not frame.IsIconized():
57                try:
58                    icon = self.parent.GetIcon()
59                    frame.SetIcon(icon)
60                except:
61                    pass 
62        frame.Show(True)
63       
64    def get_data(self):
65        """
66        """
67        return self.__data
68   
69    def get_panels(self, parent):
70        """
71        Create and return the list of wx.Panels for your plug-in.
72        Define the plug-in perspective.
73       
74        Panels should inherit from DefaultPanel defined below,
75        or should present the same interface. They must define
76        "window_caption" and "window_name".
77       
78        :param parent: parent window
79       
80        :return: list of panels
81        """
82        ## Save a reference to the parent
83        self.parent = parent
84        self.invariant_panel = InvariantPanel(parent=self.parent)
85        self.invariant_panel.set_manager(manager=self)
86        self.perspective.append(self.invariant_panel.window_name) 
87        #Create reader when fitting panel are created
88        self.state_reader = reader(self.set_state)   
89        #append that reader to list of available reader
90        loader = Loader()
91        loader.associate_file_reader(".inv", self.state_reader)
92        #loader.associate_file_reader(".svs", self.state_reader)
93        # Return the list of panels
94        return [self.invariant_panel]
95 
96    def get_context_menu(self, plotpanel=None):
97        """
98        This method is optional.
99   
100        When the context menu of a plot is rendered, the
101        get_context_menu method will be called to give you a
102        chance to add a menu item to the context menu.
103       
104        A ref to a Graph object is passed so that you can
105        investigate the plot content and decide whether you
106        need to add items to the context menu. 
107       
108        This method returns a list of menu items.
109        Each item is itself a list defining the text to
110        appear in the menu, a tool-tip help text, and a
111        call-back method.
112       
113        :param graph: the Graph object to which we attach the context menu
114       
115        :return: a list of menu items with call-back function
116        """
117        graph = plotpanel.graph
118        invariant_option = "Compute invariant"
119        invariant_hint = "Will displays the invariant panel for"
120        invariant_hint += " further computation"
121       
122        if graph.selected_plottable not in plotpanel.plots:
123            return []
124        data = plotpanel.plots[graph.selected_plottable]
125       
126        if issubclass(data.__class__, Data1D):
127           if data.name != "$I_{obs}(q)$" and  data.name != " $P_{fit}(r)$":
128               return [[invariant_option, invariant_hint, 
129                                        self._compute_invariant]]
130        return []
131
132    def _compute_invariant(self, event):   
133        """
134        Open the invariant panel to invariant computation
135        """
136        self.panel = event.GetEventObject()
137        Plugin.on_perspective(self, event=event)
138        id = self.panel.graph.selected_plottable
139        data = self.panel.plots[self.panel.graph.selected_plottable]
140        if data is None:
141            return
142        if not issubclass(data.__class__, Data1D):
143            name = data.__class__.__name__
144            msg = "Invariant use only Data1D got: [%s] " % str(name)
145            raise ValueError, msg
146        self.compute_helper(data=data)
147               
148    def set_data(self, data_list=None):
149        """
150        receive a list of data and compute invariant
151        """
152        data = None
153        if data_list is None:
154            data_list = []
155        if len(data_list) >= 1:
156            if len(data_list) == 1:
157                data = data_list[0]
158            else:
159                msg = "invariant panel does not allow multiple data!\n"
160                msg += "Please select one.\n"
161                from invariant_widgets import DataDialog
162                dlg = DataDialog(data_list=data_list, text=msg)
163                if dlg.ShowModal() == wx.ID_OK:
164                    data = dlg.get_data()
165            if data is None:
166                return
167            if issubclass(data.__class__, Data1D):
168                wx.PostEvent(self.parent, NewPlotEvent(plot=data,
169                                           title=data.title))
170                try:
171                    self.compute_helper(data)
172                except:
173                    msg = "Prview Set_data: " + str(sys.exc_value)
174                    wx.PostEvent(self.parent, StatusEvent(status=msg,
175                                                                info="error"))
176        else:   
177            msg = "invariant cannot be computed for data of "
178            msg += "type %s" % (data.__class__.__name__)
179            wx.PostEvent(self.parent, 
180                     StatusEvent(status=msg, info='error'))
181    def delete_data(self, data_id):
182        """
183        """
184        if self.__data is None:
185            return
186        for id in data_id:
187            if id == self.__data.id:
188                self.clear_panel()
189               
190    def clear_panel(self):
191        """
192        """
193        self.invariant_panel.clear_panel()
194       
195    def compute_helper(self, data):
196        """
197        """
198        if data is None:
199            return 
200        # set current data if not it's a state data
201        if not self.invariant_panel.is_state_data:
202            # Store reference to data
203            self.__data = data
204            # Set the data set to be user for invariant calculation
205            self.invariant_panel.set_data(data=data)
206           
207    def save_file(self, filepath, state=None):
208        """
209        Save data in provided state object.
210               
211        :param filepath: path of file to write to
212        :param state: invariant state
213        """     
214        # Write the state to file
215        # First, check that the data is of the right type
216        current_plottable = self.__data
217
218        if issubclass(current_plottable.__class__, Data1D):
219            self.state_reader.write(filepath, current_plottable, state)
220        else:
221            msg = "invariant.save_file: the data being saved is"
222            msg += " not a sans.dataloader.data_info.Data1D object" 
223            raise RuntimeError, msg
224
225    def set_state(self, state=None, datainfo=None):   
226        """
227        Call-back method for the state reader.
228        This method is called when a .inv/.svs file is loaded.
229       
230        :param state: State object
231        """
232        self.temp_state = None
233        try:
234            if datainfo.__class__.__name__ == 'list':
235                data = datainfo[0]
236            else:
237                data = datainfo
238            if data is None:
239                msg = "invariant.set_state: datainfo parameter cannot"
240                msg += " be None in standalone mode"
241                raise RuntimeError, msg
242            # Make sure the user sees the invariant panel after loading
243            #self.parent.set_perspective(self.perspective)
244            self.on_perspective(event=None)
245            name = data.meta_data['invstate'].file
246            data.meta_data['invstate'].file = name
247            data.name = name
248            data.filename = name
249
250            data = self.parent.create_gui_data(data,None)
251            self.__data = data
252            wx.PostEvent(self.parent, NewPlotEvent(plot=self.__data,
253                                        reset=True, title=self.__data.title))
254            data_dict = {self.__data.id:self.__data}
255            self.parent.add_data(data_list=data_dict)
256            # set state
257            self.invariant_panel.is_state_data = True
258           
259            # Load the invariant states
260            self.temp_state = state
261            # Requires to have self.__data and self.temp_state  first.
262            self.on_set_state_helper(None)
263
264        except: 
265            logging.error("invariant.set_state: %s" % sys.exc_value)
266           
267    def on_set_state_helper(self, event=None):
268        """
269        Set the state when called by EVT_STATE_UPDATE event from guiframe
270        after a .inv/.svs file is loaded
271        """
272        self.invariant_panel.set_state(state=self.temp_state,
273                                       data=self.__data)
274        self.temp_state = None
275       
276       
277    def plot_theory(self, data=None, name=None):
278        """
279        Receive a data set and post a NewPlotEvent to parent.
280       
281        :param data: extrapolated data to be plotted
282        :param name: Data's name to use for the legend
283        """
284        #import copy
285        if data is None:
286            id = str(self.__data.id) + name
287            group_id = self.__data.group_id
288            wx.PostEvent(self.parent, NewPlotEvent(id=id,
289                                               group_id=group_id,
290                                               action='Remove'))
291            return
292   
293        new_plot = Data1D(x=[], y=[], dy=None)
294        new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
295        scale = self.invariant_panel.get_scale()
296        background = self.invariant_panel.get_background()
297       
298        if scale != 0:
299            # Put back the sacle and bkg for plotting
300            data.y = (data.y + background)/scale
301            new_plot = Data1D(x=data.x, y=data.y, dy=None)
302            new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
303        else:
304            msg = "Scale can not be zero."
305            raise ValueError, msg
306        if len(new_plot.x)== 0 :
307            return
308       
309        new_plot.name = name
310        new_plot.xaxis(self.__data._xaxis, self.__data._xunit)
311        new_plot.yaxis(self.__data._yaxis, self.__data._yunit)
312        new_plot.group_id = self.__data.group_id
313        new_plot.id = str(self.__data.id) + name
314        new_plot.title = self.__data.title
315        # Save theory_data in a state
316        if data != None:
317            name_head = name.split('-')
318            if name_head[0] == 'Low':
319                self.invariant_panel.state.theory_lowQ = copy.deepcopy(new_plot)
320            elif name_head[0] == 'High':
321                self.invariant_panel.state.theory_highQ =copy.deepcopy(new_plot)
322           
323        self.parent.update_theory(data_id=self.__data.id, theory=new_plot)
324        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
325                                               title=self.__data.title))
326       
327    def plot_data(self, scale, background):
328        """
329        replot the current data if the user enters a new scale or background
330        """
331        new_plot = scale * self.__data - background
332        new_plot.name = self.__data.name
333        new_plot.group_id = self.__data.group_id
334        new_plot.id = self.__data.id
335        new_plot.title = self.__data.title
336       
337        # Save data in a state: but seems to never happen
338        if new_plot != None:
339            self.invariant_panel.state.data = copy.deepcopy(new_plot)
340        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
341                                               title=new_plot.title))
342       
Note: See TracBrowser for help on using the repository browser.