source: sasview/src/sas/sasgui/guiframe/local_perspectives/plotting/parameters_panel_slicer.py @ 1661cd5

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.2.2ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 1661cd5 was f15da54, checked in by krzywon, 7 years ago

Apply slicer to plots via events. Look for loaded plots instead of loaded data.

  • Property mode set to 100644
File size: 10.8 KB
Line 
1
2
3import wx
4import wx.lib.newevent
5import time
6#from copy import deepcopy
7from sas.sasgui.guiframe.events import EVT_SLICER_PARS
8from sas.sasgui.guiframe.utils import format_number
9from sas.sasgui.guiframe.events import EVT_SLICER
10from sas.sasgui.guiframe.events import SlicerParameterEvent, SlicerEvent
11from Plotter2D import ModelPanel2D
12from sas.sascalc.dataloader.data_info import Data1D, Data2D
13ApplyParams, EVT_APPLY_PARAMS = wx.lib.newevent.NewEvent()
14
15
16class SlicerParameterPanel(wx.Dialog):
17    """
18    Panel class to show the slicer parameters
19    """
20    # TODO: show units
21    # TODO: order parameters properly
22
23    def __init__(self, parent, *args, **kwargs):
24        """
25        Dialog window that allow to edit parameters slicer
26        by entering new values
27        """
28        wx.Dialog.__init__(self, parent, *args, **kwargs)
29        self.params = {}
30        self.parent = parent
31        self.type = None
32        self.listeners = []
33        self.parameters = []
34        self.bck = wx.GridBagSizer(5, 5)
35        self.SetSizer(self.bck)
36        label = "Right-click on 2D plot for slicer options"
37        title = wx.StaticText(self, -1, label, style=wx.ALIGN_LEFT)
38        self.bck.Add(title, (0, 0), (1, 2),
39                     flag=wx.LEFT | wx.ALIGN_CENTER_VERTICAL, border=15)
40        # Bindings
41        self.parent.Bind(EVT_SLICER, self.onEVT_SLICER)
42        self.parent.Bind(EVT_SLICER_PARS, self.onParamChange)
43        self.Bind(EVT_APPLY_PARAMS, self.apply_params_list)
44
45    def onEVT_SLICER(self, event):
46        """
47        Process EVT_SLICER events
48        When the slicer changes, update the panel
49
50        :param event: EVT_SLICER event
51        """
52        event.Skip()
53        if event.obj_class is None:
54            self.set_slicer(None, None)
55        else:
56            self.set_slicer(event.type, event.params)
57
58    def set_slicer(self, type, params):
59        """
60        Rebuild the panel
61        """
62        self.bck.Clear(True)
63        self.bck.Add((5, 5), (0, 0), (1, 1),
64                     wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 5)
65        self.type = type
66        if type is None:
67            label = "Right-click on 2D plot for slicer options"
68            title = wx.StaticText(self, -1, label, style=wx.ALIGN_LEFT)
69            self.bck.Add(title, (1, 0), (1, 2),
70                         flag=wx.LEFT | wx.ALIGN_CENTER_VERTICAL, border=15)
71        else:
72            title = wx.StaticText(self, -1,
73                                  "Slicer Parameters:", style=wx.ALIGN_LEFT)
74            self.bck.Add(title, (1, 0), (1, 2),
75                         flag=wx.LEFT | wx.ALIGN_CENTER_VERTICAL, border=15)
76            iy = 1
77            self.parameters = []
78            keys = params.keys()
79            keys.sort()
80            for item in keys:
81                iy += 1
82                ix = 0
83                if not item in ["count", "errors"]:
84                    text = wx.StaticText(self, -1, item, style=wx.ALIGN_LEFT)
85                    self.bck.Add(text, (iy, ix), (1, 1),
86                                 wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
87                    ctl = wx.TextCtrl(self, -1, size=(80, 20),
88                                      style=wx.TE_PROCESS_ENTER)
89                    hint_msg = "Modify the value of %s to change" % item
90                    hint_msg += " the 2D slicer"
91                    ctl.SetToolTipString(hint_msg)
92                    ix = 1
93                    ctl.SetValue(format_number(str(params[item])))
94                    self.Bind(wx.EVT_TEXT_ENTER, self.onTextEnter)
95                    self.parameters.append([item, ctl])
96                    self.bck.Add(ctl, (iy, ix), (1, 1),
97                                 wx.EXPAND | wx.ADJUST_MINSIZE, 0)
98                    ix = 3
99                    self.bck.Add((20, 20), (iy, ix), (1, 1),
100                                 wx.EXPAND | wx.ADJUST_MINSIZE, 0)
101                else:
102                    text = wx.StaticText(self, -1, item + " : ",
103                                         style=wx.ALIGN_LEFT)
104                    self.bck.Add(text, (iy, ix), (1, 1),
105                                 wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
106                    ctl = wx.StaticText(self, -1,
107                                        format_number(str(params[item])),
108                                        style=wx.ALIGN_LEFT)
109                    ix = 1
110                    self.bck.Add(ctl, (iy, ix), (1, 1),
111                                 wx.EXPAND | wx.ADJUST_MINSIZE, 0)
112            ix = 0
113            iy += 1
114
115            # Change slicer within the window
116            txt = "Slicer"
117            text = wx.StaticText(self, -1, txt, style=wx.ALIGN_LEFT)
118            self.bck.Add(text, (iy, ix), (1, 1),
119                         wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
120            type_list = ["SectorInteractor", "AnnulusInteractor",
121                         "BoxInteractorX", "BoxInteractorY"]
122            self.type_select = wx.ComboBox(parent=self, choices=type_list)
123            self.Bind(wx.EVT_COMBOBOX, self.onChangeSlicer)
124            index = self.type_select.FindString(self.type)
125            self.type_select.SetSelection(index)
126            self.bck.Add(self.type_select, (iy, 1), (1, 1),
127                         wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
128
129            # batch slicing parameters
130            title_text = "Batch Slicing Options:"
131            title = wx.StaticText(self, -1, title_text, style=wx.ALIGN_LEFT)
132            iy += 1
133            ln = wx.StaticLine(self, -1, style=wx.LI_VERTICAL)
134            ln.SetSize((60,60))
135            self.bck.Add(ln, (iy, ix), (1, 2),
136                         wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
137            iy += 1
138            self.bck.Add(title, (iy, ix), (1, 1),
139                         wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
140            iy += 1
141            self.process_list()
142            self.bck.Add(self.data_list, (iy, ix), (1, 1),
143                         wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
144            iy += 1
145            button_label = "Apply Slicer to Selected Plots"
146            self.batch_slicer_button = wx.Button(parent=self,
147                                                 label=button_label)
148            self.Bind(wx.EVT_BUTTON, self.onBatchSlice)
149            self.bck.Add(self.batch_slicer_button, (iy, ix), (1, 1),
150                             wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
151            # TODO: Select all button
152            # TODO: Check box for saving file
153            # TODO: append to file information and file type
154            # TODO: Send to fitting options
155
156            iy += 1
157            self.bck.Add((5, 5), (iy, ix), (1, 1),
158                         wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 5)
159        self.bck.Layout()
160        self.bck.Fit(self)
161        self.parent.GetSizer().Layout()
162
163    def onParamChange(self, evt):
164        """
165        receive an event end reset value text fields
166        inside self.parameters
167        """
168        evt.Skip()
169        if evt.type == "UPDATE":
170            for item in self.parameters:
171                if item[0] in evt.params:
172                    item[1].SetValue("%-5.3g" % evt.params[item[0]])
173                    item[1].Refresh()
174
175    def onTextEnter(self, evt):
176        """
177        Parameters have changed
178        """
179        params = {}
180        has_error = False
181        for item in self.parameters:
182            try:
183                params[item[0]] = float(item[1].GetValue())
184                item[1].SetBackgroundColour(
185                    wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
186                item[1].Refresh()
187            except:
188                has_error = True
189                item[1].SetBackgroundColour("pink")
190                item[1].Refresh()
191
192        if not has_error:
193            # Post parameter event
194            # parent here is plotter2D
195            event = SlicerParameterEvent(type=self.type, params=params)
196            wx.PostEvent(self.parent, event)
197
198    def onBatchSlice(self, evt=None):
199        """
200        Method invoked with batch slicing button is pressed
201        :param evt: Event triggering hide/show of the batch slicer parameters
202        """
203        apply_to_list = []
204        spp = self.parent.parent
205        params = self.parent.slicer.get_params()
206        type = self.type_select.GetStringSelection()
207
208        # Find loaded 2D data panels
209        for key, mgr in spp.plot_panels.iteritems():
210            if mgr.graph.prop['title'] in self.data_list.CheckedStrings:
211                apply_to_list.append(mgr)
212
213        # Apply slicer to selected panels
214        for item in apply_to_list:
215            self._apply_slicer_to_plot(item, type)
216
217        event = ApplyParams(params=params, plot_list=apply_to_list)
218        wx.PostEvent(self, event)
219
220        # TODO: save file (if desired)
221        # TODO: send to fitting (if desired)
222
223    def onChangeSlicer(self, evt):
224        """
225        Event driven slicer change when self.type_select changes
226        :param evt: Event triggering this change
227        """
228        self._apply_slicer_to_plot(self.parent)
229
230    def _apply_slicer_to_plot(self, plot, type=None):
231        """
232        Apply a slicer to *any* plot window, not just parent window
233        :param plot: 2D plot panel to apply a slicer to
234        :param type: The type of slicer to apply to the panel
235        :return: Return the plot with the slicer applied
236        """
237        if type is None:
238            type = self.type_select.GetStringSelection()
239        if type == "SectorInteractor":
240            plot.onSectorQ(None)
241        elif type == "AnnulusInteractor":
242            plot.onSectorPhi(None)
243        elif type == "BoxInteractorX":
244            plot.onBoxavgX(None)
245        elif type == "BoxInteractorY":
246            plot.onBoxavgY(None)
247
248    def process_list(self):
249        self.checkme = None
250        main_window = self.parent.parent
251        self.loaded_data = []
252        id = wx.NewId()
253        for key, value in main_window.plot_panels.iteritems():
254            if isinstance(value, ModelPanel2D):
255                self.loaded_data.append(value.data2D.name)
256                if value.data2D.id == self.parent.data2D.id:
257                    self.checkme = self.loaded_data.index(value.data2D.name)
258        self.data_list = wx.CheckListBox(parent=self, id=id,
259                                         choices=self.loaded_data,
260                                         name="Apply Slicer to 2D Plots:")
261        if self.checkme is not None:
262            self.data_list.Check(self.checkme)
263        self.data_list.Bind(wx.EVT_CHECKLISTBOX, self.onCheckBoxList)
264
265    def onCheckBoxList(self, e):
266        """
267        Do not allow a checkbox to be unchecked
268        :param e: Event triggered when a checkbox list item is checked
269        """
270        index = e.GetSelection()
271        if index == self.checkme:
272            self.data_list.Check(index)
273
274    def apply_params_list(self, evt=None):
275        for item in evt.plot_list:
276            item.slicer.set_params(evt.params)
277            item.slicer.base.update()
278        self.Destroy()
Note: See TracBrowser for help on using the repository browser.