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

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

Check all items in the list box by default. More documentation.

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