source: sasview/invariantview/perspectives/invariant/invariant.py @ ec1584e

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

edit context menu of invariant

  • Property mode set to 100644
File size: 12.5 KB
RevLine 
[c128284]1
2
[d7a39e5]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################################################################################
[d65a00a]13
14
[4e1c362]15import sys
[272d91e]16import wx
[4e1c362]17import copy
[4a2b054]18import logging
[d65a00a]19
[c128284]20
[a07e72f]21from sans.guiframe.dataFitting import Data1D
[f1e06a8e]22from sans.guiframe.events import NewPlotEvent
[a07e72f]23from sans.guiframe.gui_style import GUIFRAME_ID
[f1e06a8e]24from .invariant_state import Reader as reader
[4e1c362]25from DataLoader.loader import Loader
[f1e06a8e]26from .invariant_panel import InvariantPanel
[d65a00a]27from sans.guiframe.plugin_base import PluginBase
28
29class Plugin(PluginBase):
[c128284]30    """
[d7a39e5]31    This class defines the interface for invariant Plugin class
[4e1c362]32    that can be used by the gui_manager.       
[c128284]33    """
34   
35    def __init__(self, standalone=False):
[d65a00a]36        PluginBase.__init__(self, name="Invariant", standalone=standalone)
[c128284]37       
38        #dictionary containing data name and error on dy of that data
39        self.err_dy = {}
[d65a00a]40       
[4da35bc]41        #default state objects
42        self.state_reader = None 
[35f2f49]43        self._extensions = '.inv'
[4da35bc]44        self.temp_state = None 
45        self.__data = None 
[d65a00a]46       
[4e1c362]47        # Log startup
48        logging.info("Invariant plug-in started")
[c128284]49       
[f29a433]50    def help(self, evt):
51        """
[d7a39e5]52        Show a general help dialog.
[f29a433]53        """
[f1e06a8e]54        from .help_panel import  HelpWindow
[f29a433]55        frame = HelpWindow(None, -1)   
56        frame.Show(True)
57       
[35f2f49]58    def get_data(self):
59        """
60        """
61        return self.__data
62   
[c128284]63    def get_panels(self, parent):
64        """
[d7a39e5]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
[c128284]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)
[4e1c362]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)
[b35d3d1]86        loader.associate_file_reader(".svs", self.state_reader)
[c128284]87        # Return the list of panels
88        return [self.invariant_panel]
[d65a00a]89 
[a07e72f]90    def get_context_menu(self, plotpanel=None):
[c128284]91        """
[d7a39e5]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
[c128284]110        """
[a07e72f]111        graph = plotpanel.graph
[c128284]112        invariant_option = "Compute invariant"
[4a2b054]113        invariant_hint = "Will displays the invariant panel for"
[a1f2002]114        invariant_hint += " futher computation"
[4e1c362]115       
[a07e72f]116        if graph.selected_plottable not in plotpanel.plots:
117            return []
118        data = plotpanel.plots[graph.selected_plottable]
[c128284]119       
[ec1584e]120        if issubclass(data.__class__, Data1D):
121           if data.name != "$I_{obs}(q)$" and  data.name != " $P_{fit}(r)$":
122               return [[invariant_option, invariant_hint, 
[a07e72f]123                                        self._compute_invariant]]
124        return []
125
[c128284]126    def _compute_invariant(self, event):   
127        """
[d7a39e5]128        Open the invariant panel to invariant computation
[c128284]129        """
130        self.panel = event.GetEventObject()
[4a2b054]131        Plugin.on_perspective(self, event=event)
[a07e72f]132        id = self.panel.graph.selected_plottable
133        data = self.panel.plots[self.panel.graph.selected_plottable]
134        if data is None:
135            return
136        if not issubclass(data.__class__, Data1D):
137            name = data.__class__.__name__
138            msg = "Invariant use only Data1D got: [%s] " % str(name)
139            raise ValueError, msg
140        self.compute_helper(data=data)
[4e1c362]141               
[e88ebfd]142    def set_data(self, data_list=None):
[f1e06a8e]143        """
144        receive a list of data and compute invariant
145        """
[a07e72f]146        data = None
[14cd91b1]147        if data_list is None:
148            data_list = []
[e88ebfd]149        if len(data_list) >= 1:
150            if len(data_list) == 1:
151                data = data_list[0]
152            else:
153                msg = "invariant panel does not allow multiple data!\n"
154                msg += "Please select one.\n"
155                from invariant_widgets import DataDialog
156                dlg = DataDialog(data_list=data_list, text=msg)
157                if dlg.ShowModal() == wx.ID_OK:
158                    data = dlg.get_data()
159            if data is None:
160                return
161            if issubclass(data.__class__, Data1D):
162                wx.PostEvent(self.parent, NewPlotEvent(plot=data,
163                                           title=data.title))
164                try:
165                    self.compute_helper(data)
166                except:
167                    msg = "Prview Set_data: " + str(sys.exc_value)
168                    wx.PostEvent(self.parent, StatusEvent(status=msg,
169                                                                info="error"))
[a07e72f]170        else:   
171            msg = "invariant cannot be computed for data of "
172            msg += "type %s" % (data.__class__.__name__)
173            wx.PostEvent(self.parent, 
174                     StatusEvent(status=msg, info='error'))
[20b482f]175    def delete_data(self, data_id):
176        """
177        """
178        for id in data_id:
179            if id == self.__data.id:
180                self.clear_panel()
181               
[cb69775]182    def clear_panel(self):
[a07e72f]183        """
184        """
[cb69775]185        self.invariant_panel.clear_panel()
186       
[343fdb6]187    def compute_helper(self, data):
188        """
189        """
190        if data is None:
191            return 
[f24925ab]192        # set current data if not it's a state data
193        if not self.invariant_panel.is_state_data:
[9c1f463]194            # Store reference to data
195            self.__data = data
196            # Set the data set to be user for invariant calculation
[210ff4f]197            self.invariant_panel.set_data(data=data)
[f1e06a8e]198           
[4e1c362]199    def save_file(self, filepath, state=None):
200        """
201        Save data in provided state object.
202               
203        :param filepath: path of file to write to
204        :param state: invariant state
205        """     
206        # Write the state to file
207        # First, check that the data is of the right type
208        current_plottable = self.__data
209
210        if issubclass(current_plottable.__class__, LoaderData1D):
211            self.state_reader.write(filepath, current_plottable, state)
212        else:
[4a2b054]213            msg = "invariant.save_file: the data being saved is"
214            msg += " not a DataLoader.data_info.Data1D object" 
215            raise RuntimeError, msg
[4e1c362]216
[75fbd17]217    def set_state(self, state=None, datainfo=None):   
[4e1c362]218        """
219        Call-back method for the state reader.
[9b18735]220        This method is called when a .inv/.svs file is loaded.
[4e1c362]221       
222        :param state: State object
223        """
[4da35bc]224        self.temp_state = None
[4e1c362]225        try:
[75fbd17]226            if datainfo.__class__.__name__ == 'list':
227                data = datainfo[0]
[cb69775]228            else:
229                data = datainfo
[75fbd17]230            if data is None:
[4a2b054]231                msg = "invariant.set_state: datainfo parameter cannot"
232                msg += " be None in standalone mode"
233                raise RuntimeError, msg
[9b18735]234           
[75fbd17]235            name = data.meta_data['invstate'].file
236            data.meta_data['invstate'].file = name
237            data.name = name
238            data.filename = name
[cb69775]239            data = self.parent.create_gui_data(data,None)
[75fbd17]240            self.__data = data
241            wx.PostEvent(self.parent, NewPlotEvent(plot=self.__data,
242                                        reset=True, title=self.__data.title))
[2f97794]243            data_dict = {self.__data.id:self.__data}
244            self.parent.add_data(data_list=data_dict)
[f24925ab]245            # set state
246            self.invariant_panel.is_state_data = True
[9b18735]247           
[4e1c362]248            # Make sure the user sees the invariant panel after loading
[75fbd17]249            #self.parent.set_perspective(self.perspective)
250            self.on_perspective(event=None)
[9b18735]251            # Load the invariant states
[cb69775]252            self.temp_state = state
253            self.invariant_panel.set_state(state=state,data=self.__data)         
[75fbd17]254           
255        except: 
[4e1c362]256            logging.error("invariant.set_state: %s" % sys.exc_value)
[4da35bc]257           
[9b18735]258    def on_set_state_helper(self, event=None):
[4da35bc]259        """
[9b18735]260        Set the state when called by EVT_STATE_UPDATE event from guiframe
261        after a .inv/.svs file is loaded
[4da35bc]262        """
[4a2b054]263        self.invariant_panel.set_state(state=self.temp_state,
264                                       data=self.__data)
[4da35bc]265        self.temp_state = None
[c128284]266       
[9b18735]267       
[2661d8b]268    def plot_theory(self, data=None, name=None):
[c128284]269        """
[d7a39e5]270        Receive a data set and post a NewPlotEvent to parent.
271       
272        :param data: extrapolated data to be plotted
273        :param name: Data's name to use for the legend
[c128284]274        """
[4a2b054]275        #import copy
[2661d8b]276        if data is None:
[a07e72f]277            id = str(self.__data.id) + name
[e88ebfd]278            group_id = self.__data.group_id
[a07e72f]279            wx.PostEvent(self.parent, NewPlotEvent(id=id,
280                                               group_id=group_id,
[c85c180]281                                               action='Remove'))
[a07e72f]282            return
283   
284        new_plot = Data1D(x=[], y=[], dy=None)
285        new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
286        scale = self.invariant_panel.get_scale()
287        background = self.invariant_panel.get_background()
288       
289        if scale != 0:
290            # Put back the sacle and bkg for plotting
291            data.y = (data.y + background)/scale
292            new_plot = Data1D(x=data.x, y=data.y, dy=None)
293            new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
[2661d8b]294        else:
[a07e72f]295            msg = "Scale can not be zero."
296            raise ValueError, msg
297        if len(new_plot.x)== 0 :
298            return
299       
[c128284]300        new_plot.name = name
[2661d8b]301        new_plot.xaxis(self.__data._xaxis, self.__data._xunit)
302        new_plot.yaxis(self.__data._yaxis, self.__data._yunit)
303        new_plot.group_id = self.__data.group_id
[a07e72f]304        new_plot.id = str(self.__data.id) + name
[f1e06a8e]305        new_plot.title = self.__data.title
[4e1c362]306        # Save theory_data in a state
307        if data != None:
308            name_head = name.split('-')
[4a2b054]309            if name_head[0] == 'Low':
[4e1c362]310                self.invariant_panel.state.theory_lowQ = copy.deepcopy(new_plot)
[4a2b054]311            elif name_head[0] == 'High':
[f1e06a8e]312                self.invariant_panel.state.theory_highQ =copy.deepcopy(new_plot)
[c85c180]313           
[27f4bee]314        self.parent.update_theory(data_id=self.__data.id, theory=new_plot)
[4a2b054]315        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
[f1e06a8e]316                                               title=self.__data.title))
[6d55d81]317       
[18d0bba]318    def plot_data(self, scale, background):
[6d55d81]319        """
[d7a39e5]320        replot the current data if the user enters a new scale or background
[6d55d81]321        """
[18d0bba]322        new_plot = scale * self.__data - background
323        new_plot.name = self.__data.name
324        new_plot.group_id = self.__data.group_id
325        new_plot.id = self.__data.id
[f1e06a8e]326        new_plot.title = self.__data.title
[4e1c362]327       
328        # Save data in a state: but seems to never happen
329        if new_plot != None:
330            self.invariant_panel.state.data = copy.deepcopy(new_plot)
[4a2b054]331        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
[f1e06a8e]332                                               title=new_plot.title))
[c128284]333       
Note: See TracBrowser for help on using the repository browser.