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

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 a099131 was a099131, checked in by krzywon, 7 years ago

Slicer applied to all data files when slowly stepping through. Need to sync events with batch.

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