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

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

edit event

  • Property mode set to 100644
File size: 12.2 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       
[a07e72f]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
[c128284]130    def _compute_invariant(self, event):   
131        """
[d7a39e5]132        Open the invariant panel to invariant computation
[c128284]133        """
134        self.panel = event.GetEventObject()
[4a2b054]135        Plugin.on_perspective(self, event=event)
[a07e72f]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)
[4e1c362]145               
[f1e06a8e]146    def set_data(self, data_list):
147        """
148        receive a list of data and compute invariant
149        """
[a07e72f]150        data = None
[f1e06a8e]151        if len(data_list) > 1:
[cacbd7d]152            msg = "invariant panel does not allow multiple data!\n"
153            msg += "Please select one.\n"
154            from invariant_widgets import DataDialog
155            dlg = DataDialog(data_list=data_list, text=msg)
156            if dlg.ShowModal() == wx.ID_OK:
157                data = dlg.get_data()
[f1e06a8e]158        elif len(data_list) == 1:
[a07e72f]159            data = data_list[0]
160        if data is None:
161            return
162        if issubclass(data.__class__, Data1D):
163            wx.PostEvent(self.parent, NewPlotEvent(plot=data,
164                                       title=data.title))
165            self.compute_helper(data)
166        else:   
167            msg = "invariant cannot be computed for data of "
168            msg += "type %s" % (data.__class__.__name__)
169            wx.PostEvent(self.parent, 
170                     StatusEvent(status=msg, info='error'))
171   
[cb69775]172    def clear_panel(self):
[a07e72f]173        """
174        """
[cb69775]175        self.invariant_panel.clear_panel()
176       
[343fdb6]177    def compute_helper(self, data):
178        """
179        """
180        if data is None:
181            return 
[f24925ab]182        # set current data if not it's a state data
183        if not self.invariant_panel.is_state_data:
[9c1f463]184            # Store reference to data
185            self.__data = data
186            # Set the data set to be user for invariant calculation
[210ff4f]187            self.invariant_panel.set_data(data=data)
[f1e06a8e]188           
[4e1c362]189    def save_file(self, filepath, state=None):
190        """
191        Save data in provided state object.
192               
193        :param filepath: path of file to write to
194        :param state: invariant state
195        """     
196        # Write the state to file
197        # First, check that the data is of the right type
198        current_plottable = self.__data
199
200        if issubclass(current_plottable.__class__, LoaderData1D):
201            self.state_reader.write(filepath, current_plottable, state)
202        else:
[4a2b054]203            msg = "invariant.save_file: the data being saved is"
204            msg += " not a DataLoader.data_info.Data1D object" 
205            raise RuntimeError, msg
[4e1c362]206
[75fbd17]207    def set_state(self, state=None, datainfo=None):   
[4e1c362]208        """
209        Call-back method for the state reader.
[9b18735]210        This method is called when a .inv/.svs file is loaded.
[4e1c362]211       
212        :param state: State object
213        """
[4da35bc]214        self.temp_state = None
[4e1c362]215        try:
[75fbd17]216            if datainfo.__class__.__name__ == 'list':
217                data = datainfo[0]
[cb69775]218            else:
219                data = datainfo
[75fbd17]220            if data is None:
[4a2b054]221                msg = "invariant.set_state: datainfo parameter cannot"
222                msg += " be None in standalone mode"
223                raise RuntimeError, msg
[9b18735]224           
[75fbd17]225            name = data.meta_data['invstate'].file
226            data.meta_data['invstate'].file = name
227            data.name = name
228            data.filename = name
[cb69775]229            data = self.parent.create_gui_data(data,None)
[75fbd17]230            #self.__data = datainfo
231            #self.__data.group_id = data.filename
232            #self.__data.id = datainfo.filename
233            self.__data = data
234            wx.PostEvent(self.parent, NewPlotEvent(plot=self.__data,
235                                        reset=True, title=self.__data.title))
236            #temp_state = copy.deepcopy(state)
[cb69775]237            #temp_state = self.state_reader.get_state()
[f24925ab]238            # set state
239            self.invariant_panel.is_state_data = True
[9b18735]240           
[4e1c362]241            # Make sure the user sees the invariant panel after loading
[75fbd17]242            #self.parent.set_perspective(self.perspective)
243            self.on_perspective(event=None)
[9b18735]244            # Load the invariant states
[cb69775]245            self.temp_state = state
246            self.invariant_panel.set_state(state=state,data=self.__data)         
[75fbd17]247           
248        except: 
[4e1c362]249            logging.error("invariant.set_state: %s" % sys.exc_value)
[4da35bc]250           
[9b18735]251    def on_set_state_helper(self, event=None):
[4da35bc]252        """
[9b18735]253        Set the state when called by EVT_STATE_UPDATE event from guiframe
254        after a .inv/.svs file is loaded
[4da35bc]255        """
[4a2b054]256        self.invariant_panel.set_state(state=self.temp_state,
257                                       data=self.__data)
[4da35bc]258        self.temp_state = None
[c128284]259       
[9b18735]260       
[2661d8b]261    def plot_theory(self, data=None, name=None):
[c128284]262        """
[d7a39e5]263        Receive a data set and post a NewPlotEvent to parent.
264       
265        :param data: extrapolated data to be plotted
266        :param name: Data's name to use for the legend
[c128284]267        """
[4a2b054]268        #import copy
[2661d8b]269        if data is None:
[a07e72f]270            id = str(self.__data.id) + name
271            self.__data.group_id
272            wx.PostEvent(self.parent, NewPlotEvent(id=id,
273                                               group_id=group_id,
[c85c180]274                                               action='Remove'))
[a07e72f]275            return
276   
277        new_plot = Data1D(x=[], y=[], dy=None)
278        new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
279        scale = self.invariant_panel.get_scale()
280        background = self.invariant_panel.get_background()
281       
282        if scale != 0:
283            # Put back the sacle and bkg for plotting
284            data.y = (data.y + background)/scale
285            new_plot = Data1D(x=data.x, y=data.y, dy=None)
286            new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
[2661d8b]287        else:
[a07e72f]288            msg = "Scale can not be zero."
289            raise ValueError, msg
290        if len(new_plot.x)== 0 :
291            return
292       
[c128284]293        new_plot.name = name
[2661d8b]294        new_plot.xaxis(self.__data._xaxis, self.__data._xunit)
295        new_plot.yaxis(self.__data._yaxis, self.__data._yunit)
296        new_plot.group_id = self.__data.group_id
[a07e72f]297        new_plot.id = str(self.__data.id) + name
[f1e06a8e]298        new_plot.title = self.__data.title
[4e1c362]299        # Save theory_data in a state
300        if data != None:
301            name_head = name.split('-')
[4a2b054]302            if name_head[0] == 'Low':
[4e1c362]303                self.invariant_panel.state.theory_lowQ = copy.deepcopy(new_plot)
[4a2b054]304            elif name_head[0] == 'High':
[f1e06a8e]305                self.invariant_panel.state.theory_highQ =copy.deepcopy(new_plot)
[c85c180]306           
307        self.parent.append_theory(data_id=self.__data.id, theory=new_plot)
[4a2b054]308        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
[f1e06a8e]309                                               title=self.__data.title))
[6d55d81]310       
[18d0bba]311    def plot_data(self, scale, background):
[6d55d81]312        """
[d7a39e5]313        replot the current data if the user enters a new scale or background
[6d55d81]314        """
[18d0bba]315        new_plot = scale * self.__data - background
316        new_plot.name = self.__data.name
317        new_plot.group_id = self.__data.group_id
318        new_plot.id = self.__data.id
[f1e06a8e]319        new_plot.title = self.__data.title
[4e1c362]320       
321        # Save data in a state: but seems to never happen
322        if new_plot != None:
323            self.invariant_panel.state.data = copy.deepcopy(new_plot)
[4a2b054]324        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
[f1e06a8e]325                                               title=new_plot.title))
[c128284]326       
Note: See TracBrowser for help on using the repository browser.