source: sasview/invariantview/perspectives/invariant/invariant.py @ 5cc393b8

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 5cc393b8 was a1f2002, checked in by Gervaise Alina <gervyh@…>, 14 years ago

fix misspell

  • Property mode set to 100644
File size: 13.3 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#import os
14import sys
15import wx
16import copy
17import logging
18#import time
19#from sans.invariant import invariant
20
21from DataLoader.data_info import Data1D as LoaderData1D
22from sans.guiframe.dataFitting import Theory1D
23from sans.guiframe.dataFitting import Data1D
24
25from sans.guicomm.events import NewPlotEvent
26from sans.guicomm.events import ERR_DATA
27from invariant_state import Reader as reader
28from DataLoader.loader import Loader
29from invariant_panel import InvariantPanel
30from sans.guicomm.events import EVT_INVSTATE_UPDATE
31
32class Plugin:
33    """
34    This class defines the interface for invariant Plugin class
35    that can be used by the gui_manager.       
36    """
37   
38    def __init__(self, standalone=False):
39        """
40        Abstract class for gui_manager Plugins.
41        """
42        ## Plug-in name. It will appear on the application menu.
43        self.sub_menu = "Invariant"
44       
45        ## Reference to the parent window. Filled by get_panels() below.
46        self.parent = None
47        #dictionary containing data name and error on dy of that data
48        self.err_dy = {}
49        ## List of panels that you would like to open in AUI windows
50        #  for your plug-in. This defines your plug-in "perspective"
51        self.perspective = []
52        #default state objects
53        self.state_reader = None 
54        self.temp_state = None 
55        self.__data = None 
56        """
57        # Create a CanSAS/Pr reader
58        self.state_reader = Reader(self.set_state)
59        l = Loader()
60        l.associate_file_reader('.inv', self.state_reader) 
61        """   
62        # Log startup
63        logging.info("Invariant plug-in started")
64       
65    def populate_menu(self, id, parent):
66        """
67        Create and return the list of application menu
68        items for the plug-in.
69       
70        :param id: deprecated. Un-used.
71        :param parent: parent window
72       
73        :return: plug-in menu
74        """
75        return []
76   
77    def help(self, evt):
78        """
79        Show a general help dialog.
80        """
81        from help_panel import  HelpWindow
82        frame = HelpWindow(None, -1)   
83        frame.Show(True)
84       
85    def get_panels(self, parent):
86        """
87        Create and return the list of wx.Panels for your plug-in.
88        Define the plug-in perspective.
89       
90        Panels should inherit from DefaultPanel defined below,
91        or should present the same interface. They must define
92        "window_caption" and "window_name".
93       
94        :param parent: parent window
95       
96        :return: list of panels
97        """
98        ## Save a reference to the parent
99        self.parent = parent
100        #add error back to the data
101        self.parent.Bind(ERR_DATA, self._on_data_error)
102        self.parent.Bind(EVT_INVSTATE_UPDATE, self.on_set_state_helper)
103       
104        self.invariant_panel = InvariantPanel(parent=self.parent)
105        self.invariant_panel.set_manager(manager=self)
106        self.perspective.append(self.invariant_panel.window_name) 
107        #Create reader when fitting panel are created
108        self.state_reader = reader(self.set_state)   
109        #append that reader to list of available reader
110        loader = Loader()
111        loader.associate_file_reader(".inv", self.state_reader)
112        loader.associate_file_reader(".svs", self.state_reader)
113        # Return the list of panels
114        return [self.invariant_panel]
115   
116    def get_tools(self):
117        """
118        Returns a set of menu entries for tools
119        """
120        return []
121       
122   
123    def get_context_menu(self, graph=None):
124        """
125        This method is optional.
126   
127        When the context menu of a plot is rendered, the
128        get_context_menu method will be called to give you a
129        chance to add a menu item to the context menu.
130       
131        A ref to a Graph object is passed so that you can
132        investigate the plot content and decide whether you
133        need to add items to the context menu. 
134       
135        This method returns a list of menu items.
136        Each item is itself a list defining the text to
137        appear in the menu, a tool-tip help text, and a
138        call-back method.
139       
140        :param graph: the Graph object to which we attach the context menu
141       
142        :return: a list of menu items with call-back function
143        """
144        self.graph = graph
145        invariant_option = "Compute invariant"
146        invariant_hint = "Will displays the invariant panel for"
147        invariant_hint += " futher computation"
148       
149        for item in self.graph.plottables:
150            if item.name == graph.selected_plottable :
151                if issubclass(item.__class__, LoaderData1D):
152           
153                    if item.name != "$I_{obs}(q)$" and \
154                        item.name != " $P_{fit}(r)$":
155                        if hasattr(item, "group_id"):
156                            return [[invariant_option, 
157                                        invariant_hint, 
158                                        self._compute_invariant]]
159        return []   
160
161   
162    def get_perspective(self):
163        """
164        Get the list of panel names for this perspective
165        """
166        return self.perspective
167   
168    def on_perspective(self, event):
169        """
170        Call back function for the perspective menu item.
171        We notify the parent window that the perspective
172        has changed.
173       
174        :param event: menu event
175        """
176        self.parent.set_perspective(self.perspective)
177   
178    def post_init(self):
179        """
180        Post initialization call back to close the loose ends
181        """
182        pass
183   
184    def set_default_perspective(self):
185        """
186        Call back method that True to notify the parent that the current plug-in
187        can be set as default  perspective.
188        when returning False, the plug-in is not candidate for an automatic
189        default perspective setting
190        """
191        return False
192   
193    def copy_data(self, item, dy=None):
194        """
195        receive a data 1D and the list of errors on dy
196        and create a new data1D data
197        """
198        id = None
199        if hasattr(item,"id"):
200            id = item.id
201
202        data = Data1D(x=item.x, y=item.y, dx=None, dy=None)
203        data.copy_from_datainfo(item)
204        item.clone_without_data(clone=data)   
205        data.dy = dy
206        data.name = item.name
207       
208        ## allow to highlight data when plotted
209        data.interactive = item.interactive
210        ## when 2 data have the same id override the 1 st plotted
211        data.id = id
212        data.group_id = item.group_id
213        return data
214   
215    def _on_data_error(self, event):
216        """
217        receives and event from plotting plu-gins to store the data name and
218        their errors of y coordinates for 1Data hide and show error
219        """
220        self.err_dy = event.err_dy
221       
222    def _compute_invariant(self, event):   
223        """
224        Open the invariant panel to invariant computation
225        """
226        self.panel = event.GetEventObject()
227        Plugin.on_perspective(self, event=event)
228        for plottable in self.panel.graph.plottables:
229            if plottable.name == self.panel.graph.selected_plottable:
230                ## put the errors values back to the model if the errors
231                ## were hiden before sending them to the fit engine
232                if len(self.err_dy) > 0:
233                    dy = plottable.dy
234                    if plottable.name in  self.err_dy.iterkeys():
235                        dy = self.err_dy[plottable.name]
236                    data = self.copy_data(plottable, dy)
237                else:
238                    data = plottable
239                self.compute_helper(data=data)
240               
241    def compute_helper(self, data):
242        """
243        """
244        if data is None:
245            return 
246        # set current data if not it's a state data
247        if not self.invariant_panel.is_state_data:
248            # Store reference to data
249            self.__data = data
250            # Set the data set to be user for invariant calculation
251            self.invariant_panel.set_data(data=data)
252       
253    def save_file(self, filepath, state=None):
254        """
255        Save data in provided state object.
256               
257        :param filepath: path of file to write to
258        :param state: invariant state
259        """     
260        # Write the state to file
261        # First, check that the data is of the right type
262        current_plottable = self.__data
263
264        if issubclass(current_plottable.__class__, LoaderData1D):
265            self.state_reader.write(filepath, current_plottable, state)
266        else:
267            msg = "invariant.save_file: the data being saved is"
268            msg += " not a DataLoader.data_info.Data1D object" 
269            raise RuntimeError, msg
270
271    def set_state(self, state, datainfo=None):   
272        """
273        Call-back method for the state reader.
274        This method is called when a .inv/.svs file is loaded.
275       
276        :param state: State object
277        """
278        self.temp_state = None
279        try:
280           
281            if datainfo is None:
282                msg = "invariant.set_state: datainfo parameter cannot"
283                msg += " be None in standalone mode"
284                raise RuntimeError, msg
285           
286            name = datainfo.meta_data['invstate'].file
287            datainfo.meta_data['invstate'].file = name
288            datainfo.name = name
289            datainfo.filename = name
290            self.__data = datainfo
291            self.__data.group_id = datainfo.filename
292            self.__data.id = datainfo.filename
293
294            temp_state = copy.deepcopy(state)
295            # set state
296            self.invariant_panel.is_state_data = True
297           
298            # Make sure the user sees the invariant panel after loading
299            self.parent.set_perspective(self.perspective)
300            # Load the invariant states
301            self.temp_state = temp_state
302            #self.invariant_panel.set_state(state=temp_state,data=self.__data)         
303           
304        except:
305            logging.error("invariant.set_state: %s" % sys.exc_value)
306           
307    def on_set_state_helper(self, event=None):
308        """
309        Set the state when called by EVT_STATE_UPDATE event from guiframe
310        after a .inv/.svs file is loaded
311        """
312        self.invariant_panel.set_state(state=self.temp_state,
313                                       data=self.__data)
314        self.temp_state = None
315       
316       
317       
318    def plot_theory(self, data=None, name=None):
319        """
320        Receive a data set and post a NewPlotEvent to parent.
321       
322        :param data: extrapolated data to be plotted
323        :param name: Data's name to use for the legend
324        """
325        #import copy
326        if data is None:
327            new_plot = Theory1D(x=[], y=[], dy=None)
328        else:
329            scale = self.invariant_panel.get_scale()
330            background = self.invariant_panel.get_background()
331           
332            if scale != 0:
333                # Put back the sacle and bkg for plotting
334                data.y = (data.y + background)/scale
335                new_plot = Theory1D(x=data.x, y=data.y, dy=None)
336            else:
337                msg = "Scale can not be zero."
338                raise ValueError, msg
339
340        new_plot.name = name
341        new_plot.xaxis(self.__data._xaxis, self.__data._xunit)
342        new_plot.yaxis(self.__data._yaxis, self.__data._yunit)
343        new_plot.group_id = self.__data.group_id
344        new_plot.id = self.__data.id + name
345        # Save theory_data in a state
346        if data != None:
347            name_head = name.split('-')
348            if name_head[0] == 'Low':
349                self.invariant_panel.state.theory_lowQ = copy.deepcopy(new_plot)
350            elif name_head[0] == 'High':
351                self.invariant_panel.state.theory_highQ = copy.deepcopy(new_plot)
352
353        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
354                                               title=self.__data.name))
355       
356    def plot_data(self, scale, background):
357        """
358        replot the current data if the user enters a new scale or background
359        """
360        new_plot = scale * self.__data - background
361        new_plot.name = self.__data.name
362        new_plot.group_id = self.__data.group_id
363        new_plot.id = self.__data.id
364       
365        # Save data in a state: but seems to never happen
366        if new_plot != None:
367            self.invariant_panel.state.data = copy.deepcopy(new_plot)
368        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
369                                               title=new_plot.name))
370       
Note: See TracBrowser for help on using the repository browser.