source: sasview/invariantview/perspectives/invariant/invariant.py @ 8ee56a9

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 8ee56a9 was e88ebfd, checked in by Gervaise Alina <gervyh@…>, 14 years ago

working on guiframe

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