Changeset f4a1433 in sasview for src/sas/sasgui/guiframe/local_perspectives
- Timestamp:
- Oct 24, 2017 2:44:26 AM (7 years ago)
- Branches:
- ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc
- Children:
- fca1f50, d6b234b
- Parents:
- 16afe01 (diff), 5582b078 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - Location:
- src/sas/sasgui/guiframe/local_perspectives
- Files:
-
- 1 added
- 1 deleted
- 9 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
src/sas/sasgui/guiframe/local_perspectives/data_loader/data_loader.py
r235f514 rb963b20 10 10 logger = logging.getLogger(__name__) 11 11 12 from sas import get_local_config 13 12 14 from sas.sascalc.dataloader.loader import Loader 15 from sas.sascalc.dataloader.loader_exceptions import NoKnownLoaderException 16 13 17 from sas.sasgui.guiframe.plugin_base import PluginBase 14 18 from sas.sasgui.guiframe.events import StatusEvent 15 19 from sas.sasgui.guiframe.gui_style import GUIFRAME 16 20 from sas.sasgui.guiframe.gui_manager import DEFAULT_OPEN_FOLDER 17 try: 18 # Try to find a local config 19 import imp 20 path = os.getcwd() 21 if(os.path.isfile("%s/%s.py" % (path, 'local_config'))) or \ 22 (os.path.isfile("%s/%s.pyc" % (path, 'local_config'))): 23 fObj, path, descr = imp.find_module('local_config', [path]) 24 config = imp.load_module('local_config', fObj, path, descr) 25 else: 26 # Try simply importing local_config 27 import local_config as config 28 except: 29 # Didn't find local config, load the default 30 import sas.sasgui.guiframe.config as config 31 32 if config is None: 33 import sas.sasgui.guiframe.config as config 34 35 21 22 config = get_local_config() 36 23 extension_list = [] 37 24 if config.APPLICATION_STATE_EXTENSION is not None: … … 41 28 APPLICATION_WLIST = config.APPLICATION_WLIST 42 29 30 43 31 class Plugin(PluginBase): 44 32 … … 56 44 """ 57 45 # menu for data files 58 menu_list = []59 46 data_file_hint = "load one or more data in the application" 60 47 menu_list = [('&Load Data File(s)', data_file_hint, self.load_data)] 61 48 gui_style = self.parent.get_style() 62 49 style = gui_style & GUIFRAME.MULTIPLE_APPLICATIONS 63 style1 = gui_style & GUIFRAME.DATALOADER_ON64 50 if style == GUIFRAME.MULTIPLE_APPLICATIONS: 65 51 # menu for data from folder … … 102 88 self.get_data(file_list) 103 89 104 105 90 def can_load_data(self): 106 91 """ … … 108 93 """ 109 94 return True 110 111 95 112 96 def _load_folder(self, event): … … 140 124 """ 141 125 if error is not None or str(error).strip() != "": 142 dial = wx.MessageDialog(self.parent, str(error), 'Error Loading File', 126 dial = wx.MessageDialog(self.parent, str(error), 127 'Error Loading File', 143 128 wx.OK | wx.ICON_EXCLAMATION) 144 129 dial.ShowModal() … … 149 134 """ 150 135 if os.path.isdir(path): 151 return [os.path.join(os.path.abspath(path), filename) for filename in os.listdir(path)] 136 return [os.path.join(os.path.abspath(path), filename) for filename 137 in os.listdir(path)] 152 138 153 139 def _process_data_and_errors(self, item, p_file, output, message): … … 178 164 for p_file in path: 179 165 basename = os.path.basename(p_file) 166 # Skip files that start with a period 167 if basename.startswith("."): 168 msg = "The folder included a potential hidden file - %s." \ 169 % basename 170 msg += " Do you wish to load this file as data?" 171 msg_box = wx.MessageDialog(None, msg, 'Warning', 172 wx.OK | wx.CANCEL) 173 if msg_box.ShowModal() == wx.ID_CANCEL: 174 continue 180 175 _, extension = os.path.splitext(basename) 181 176 if extension.lower() in EXTENSIONS: … … 213 208 info="info") 214 209 215 except: 216 logger.error(sys.exc_value) 217 218 error_message = "The Data file you selected could not be loaded.\n" 219 error_message += "Make sure the content of your file" 220 error_message += " is properly formatted.\n" 221 error_message += "When contacting the SasView team, mention the" 222 error_message += " following:\n" 223 error_message += "Error: " + str(sys.exc_info()[1]) 224 file_errors[basename] = [error_message] 225 self.load_update(output=output, message=error_message, info="warning") 210 except NoKnownLoaderException as e: 211 exception_occurred = True 212 logger.error(e.message) 213 214 error_message = "Loading data failed!\n" + e.message 215 self.load_update(output=None, message=e.message, info="warning") 216 217 except Exception as e: 218 exception_occurred = True 219 logger.error(e.message) 220 221 file_err = "The Data file you selected could not be " 222 file_err += "loaded.\nMake sure the content of your file" 223 file_err += " is properly formatted.\n" 224 file_err += "When contacting the SasView team, mention the" 225 file_err += " following:\n" 226 file_err += e.message 227 file_errors[basename] = [file_err] 226 228 227 229 if len(file_errors) > 0: … … 233 235 error_message += message + "\n" 234 236 error_message += "\n" 235 self.load_update(output=output, message=error_message, info="error") 236 237 self.load_complete(output=output, message="Loading data complete!", 238 info="info") 237 if not exception_occurred: # Some data loaded but with errors 238 self.load_update(output=output, message=error_message, info="error") 239 240 if not exception_occurred: # Everything loaded as expected 241 self.load_complete(output=output, message="Loading data complete!", 242 info="info") 243 else: 244 self.load_complete(output=None, message=error_message, info="error") 245 239 246 240 247 def load_update(self, output=None, message="", info="warning"): … … 245 252 wx.PostEvent(self.parent, StatusEvent(status=message, info=info, 246 253 type="progress")) 247 def load_complete(self, output, message="", error_message="", path=None, 248 info="warning"): 249 """ 250 post message to status bar and return list of data 251 """ 252 wx.PostEvent(self.parent, StatusEvent(status=message, 253 info=info, 254 255 def load_complete(self, output, message="", info="warning"): 256 """ 257 post message to status bar and return list of data 258 """ 259 wx.PostEvent(self.parent, StatusEvent(status=message, info=info, 254 260 type="stop")) 255 # if error_message != "": 256 # self.load_error(error_message) 257 self.parent.add_data(data_list=output) 261 if output is not None: 262 self.parent.add_data(data_list=output) -
src/sas/sasgui/guiframe/local_perspectives/plotting/Plotter2D.py
r7432acb r3e5648b 361 361 if self.slicer.__class__.__name__ != "BoxSum": 362 362 wx_id = ids.next() 363 slicerpop.Append(wx_id, '&Edit Slicer Parameters') 363 name = '&Edit Slicer Parameters and Batch Slicing' 364 slicerpop.Append(wx_id, name) 364 365 wx.EVT_MENU(self, wx_id, self._onEditSlicer) 365 366 slicerpop.AppendSeparator() … … 532 533 533 534 """ 534 # #Clear current slicer535 # Clear current slicer 535 536 if self.slicer is not None: 536 537 self.slicer.clear() 537 # #Create a new slicer538 # Create a new slicer 538 539 self.slicer_z += 1 539 540 self.slicer = slicer(self, self.subplot, zorder=self.slicer_z) 540 541 self.subplot.set_ylim(self.data2D.ymin, self.data2D.ymax) 541 542 self.subplot.set_xlim(self.data2D.xmin, self.data2D.xmax) 542 # #Draw slicer543 # Draw slicer 543 544 self.update() 544 545 self.slicer.update() … … 572 573 npt = math.floor(npt) 573 574 from sas.sascalc.dataloader.manipulations import CircularAverage 574 # #compute the maximum radius of data2D575 # compute the maximum radius of data2D 575 576 self.qmax = max(math.fabs(self.data2D.xmax), 576 577 math.fabs(self.data2D.xmin)) … … 578 579 math.fabs(self.data2D.ymin)) 579 580 self.radius = math.sqrt(math.pow(self.qmax, 2) + math.pow(self.ymax, 2)) 580 # #Compute beam width581 # Compute beam width 581 582 bin_width = (self.qmax + self.qmax) / npt 582 # #Create data1D circular average of data2D583 # Create data1D circular average of data2D 583 584 Circle = CircularAverage(r_min=0, r_max=self.radius, 584 585 bin_width=bin_width) … … 599 600 new_plot.name = "Circ avg " + self.data2D.name 600 601 new_plot.source = self.data2D.source 601 # new_plot.info = self.data2D.info602 # new_plot.info = self.data2D.info 602 603 new_plot.interactive = True 603 604 new_plot.detector = self.data2D.detector 604 605 605 # #If the data file does not tell us what the axes are, just assume...606 # If the data file does not tell us what the axes are, just assume... 606 607 new_plot.xaxis("\\rm{Q}", "A^{-1}") 607 608 if hasattr(self.data2D, "scale") and \ … … 615 616 new_plot.id = "Circ avg " + self.data2D.name 616 617 new_plot.is_data = True 617 self.parent.update_theory(data_id=self.data2D.id, \ 618 theory=new_plot) 618 self.parent.update_theory(data_id=self.data2D.id, theory=new_plot) 619 619 wx.PostEvent(self.parent, 620 620 NewPlotEvent(plot=new_plot, title=new_plot.name)) … … 630 630 """ 631 631 if self.slicer is not None: 632 from SlicerParametersimport SlicerParameterPanel632 from parameters_panel_slicer import SlicerParameterPanel 633 633 dialog = SlicerParameterPanel(self, -1, "Slicer Parameters") 634 634 dialog.set_slicer(self.slicer.__class__.__name__, … … 668 668 params = self.slicer.get_params() 669 669 ## Create a new panel to display results of summation of Data2D 670 from slicerpanelimport SlicerPanel670 from parameters_panel_boxsum import SlicerPanel 671 671 win = MDIFrame(self.parent, None, 'None', (100, 200)) 672 672 new_panel = SlicerPanel(parent=win, id=-1, … … 758 758 if default_name.count('.') > 0: 759 759 default_name = default_name.split('.')[0] 760 #default_name += "_out"761 760 if self.parent is not None: 762 761 self.parent.show_data2d(data, default_name) 763 762 764 763 def modifyGraphAppearance(self, e): 765 self.graphApp = graphAppearance(self, 'Modify graph appearance', legend=False) 764 self.graphApp = graphAppearance(self, 'Modify graph appearance', 765 legend=False) 766 766 self.graphApp.setDefaults(self.grid_on, self.legend_on, 767 767 self.xaxis_label, self.yaxis_label, -
src/sas/sasgui/guiframe/local_perspectives/plotting/parameters_panel_boxsum.py
r7432acb r37d461c 1 1 import wx 2 2 import wx.lib.newevent 3 #from copy import deepcopy 3 from parameters_panel_slicer import SlicerParameterPanel 4 4 from sas.sasgui.guiframe.utils import format_number 5 from sas.sasgui.guiframe. events import SlicerParameterEvent6 from sas.sasgui.guiframe.events import EVT_SLICER_PARS7 from sas.sasgui.guiframe.events import EVT_SLICER 5 from sas.sasgui.guiframe.panel_base import PanelBase 6 from sas.sasgui.guiframe.events import (SlicerParameterEvent, EVT_SLICER_PARS, 7 EVT_SLICER) 8 8 9 from sas.sasgui.guiframe.panel_base import PanelBase10 9 11 10 class SlicerPanel(wx.Panel, PanelBase): … … 13 12 Panel class to show the slicer parameters 14 13 """ 15 #TODO: show units 16 #TODO: order parameters properly 17 ## Internal name for the AUI manager 14 # Internal name for the AUI manager 18 15 window_name = "Slicer panel" 19 # #Title to appear on top of the window16 # Title to appear on top of the window 20 17 window_caption = "Slicer Panel" 21 18 CENTER_PANE = False … … 25 22 wx.Panel.__init__(self, parent, id, *args, **kwargs) 26 23 PanelBase.__init__(self) 27 # #Initialization of the class24 # Initialization of the class 28 25 self.base = base 29 26 if params is None: … … 44 41 else: 45 42 self.set_slicer(type, params) 46 ## Bindings 47 self.parent.Bind(EVT_SLICER, self.onEVT_SLICER) 48 self.parent.Bind(EVT_SLICER_PARS, self.onParamChange) 49 50 def onEVT_SLICER(self, event): 51 """ 52 Process EVT_SLICER events 53 When the slicer changes, update the panel 54 55 :param event: EVT_SLICER event 56 57 """ 58 event.Skip() 59 if event.obj_class is None: 60 self.set_slicer(None, None) 61 else: 62 self.set_slicer(event.type, event.params) 43 # Bindings 44 self.parent.Bind(EVT_SLICER, SlicerParameterPanel.on_evt_slicer) 45 self.parent.Bind(EVT_SLICER_PARS, SlicerParameterPanel.on_param_change) 63 46 64 47 def set_slicer(self, type, params): … … 84 67 keys.sort() 85 68 for item in keys: 86 if not item.lower() in ["num_points", "avg", "avg_error", "sum", "sum_error"]: 69 if not item.lower() in ["num_points", "avg", "avg_error", "sum", 70 "sum_error"]: 87 71 n += 1 88 72 text = wx.StaticText(self, -1, item, style=wx.ALIGN_LEFT) 89 73 self.bck.Add(text, (n - 1, 0), 90 flag=wx.LEFT | wx.ALIGN_CENTER_VERTICAL, border=15) 74 flag=wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 75 border=15) 91 76 ctl = wx.TextCtrl(self, -1, size=(80, 20), 92 77 style=wx.TE_PROCESS_ENTER) … … 95 80 ctl.SetToolTipString(hint_msg) 96 81 ctl.SetValue(str(format_number(params[item]))) 97 self.Bind(wx.EVT_TEXT_ENTER, self.on TextEnter)98 ctl.Bind(wx.EVT_SET_FOCUS, self.on SetFocus)99 ctl.Bind(wx.EVT_KILL_FOCUS, self.on TextEnter)82 self.Bind(wx.EVT_TEXT_ENTER, self.on_text_enter) 83 ctl.Bind(wx.EVT_SET_FOCUS, self.on_set_focus) 84 ctl.Bind(wx.EVT_KILL_FOCUS, self.on_text_enter) 100 85 self.parameters.append([item, ctl]) 101 self.bck.Add(ctl, (n - 1, 1), flag=wx.TOP | wx.BOTTOM, border=0) 86 self.bck.Add(ctl, (n - 1, 1), flag=wx.TOP | wx.BOTTOM, 87 border=0) 102 88 for item in keys: 103 if item.lower() in ["num_points", "avg", "avg_error", "sum", "sum_error"]: 89 if item.lower() in ["num_points", "avg", "avg_error", "sum", 90 "sum_error"]: 104 91 n += 1 105 text = wx.StaticText(self, -1, item + ": ", style=wx.ALIGN_LEFT) 106 self.bck.Add(text, (n - 1, 0), flag=wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 92 text = wx.StaticText(self, -1, item + ": ", 93 style=wx.ALIGN_LEFT) 94 self.bck.Add(text, (n - 1, 0), 95 flag=wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 107 96 border=15) 108 97 ctl = wx.StaticText(self, -1, … … 110 99 style=wx.ALIGN_LEFT) 111 100 ctl.SetToolTipString("Result %s" % item) 112 self.bck.Add(ctl, (n - 1, 1), flag=wx.TOP | wx.BOTTOM, border=0) 101 self.bck.Add(ctl, (n - 1, 1), flag=wx.TOP | wx.BOTTOM, 102 border=0) 113 103 self.bck.Layout() 114 104 self.Layout() 115 p sizer = self.parent.GetSizer()116 if p sizer is not None:117 p sizer.Layout()105 p_sizer = self.parent.GetSizer() 106 if p_sizer is not None: 107 p_sizer.Layout() 118 108 119 def on SetFocus(self, evt):109 def on_set_focus(self, evt): 120 110 """ 121 111 Highlight the txtcrtl … … 126 116 # Select the whole control, after this event resolves 127 117 wx.CallAfter(widget.SetSelection, -1, -1) 128 return129 118 130 def onParamChange(self, evt): 131 """ 132 Receive and event and reset the text field contained in self.parameters 133 134 """ 135 evt.Skip() 136 for item in self.parameters: 137 if item[0] in evt.params: 138 item[1].SetValue(format_number(evt.params[item[0]])) 139 item[1].Refresh() 140 141 def onTextEnter(self, evt): 119 def on_text_enter(self, evt): 142 120 """ 143 121 Parameters have changed … … 149 127 try: 150 128 params[item[0]] = float(item[1].GetValue()) 151 item[1].SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)) 129 item[1].SetBackgroundColour(wx.SystemSettings_GetColour( 130 wx.SYS_COLOUR_WINDOW)) 152 131 item[1].Refresh() 153 132 except: … … 155 134 item[1].SetBackgroundColour("pink") 156 135 item[1].Refresh() 157 158 if has_error == False: 136 if not has_error: 159 137 # Post parameter event 160 # #base is guiframe is this case138 # base is guiframe is this case 161 139 event = SlicerParameterEvent(type=self.type, params=params) 162 140 wx.PostEvent(self.base, event) … … 166 144 On Close Event 167 145 """ 168 ID= self.uid169 self.parent.delete_panel( ID)146 uid = self.uid 147 self.parent.delete_panel(uid) 170 148 self.frame.Destroy() -
src/sas/sasgui/guiframe/local_perspectives/plotting/plotting.py
r235f514 r2d9526d 14 14 import wx 15 15 import sys 16 from copy import deepcopy 16 17 from sas.sasgui.guiframe.events import EVT_NEW_PLOT 17 18 from sas.sasgui.guiframe.events import EVT_PLOT_QRANGE … … 275 276 action_check = True 276 277 else: 278 if action_string == 'update': 279 # Update all existing plots of data with this ID 280 for data in event.plots: 281 for panel in self.plot_panels.values(): 282 if data.id in panel.plots.keys(): 283 plot_exists = True 284 # Pass each panel it's own copy of the data 285 # that's being updated, otherwise things like 286 # colour and line thickness are unintentionally 287 # synced across panels 288 self.update_panel(deepcopy(data), panel) 289 return 290 277 291 group_id = event.group_id 278 if group_id in self.plot_panels .keys():292 if group_id in self.plot_panels: 279 293 #remove data from panel 280 294 if action_string == 'remove': -
src/sas/sasgui/guiframe/local_perspectives/plotting/AnnulusSlicer.py
r7432acb r83eb5208 1 # TODO: the line slicer should listen to all 2DREFRESH events, get the data and slice it 2 # before pushing a new 1D data update. 3 4 # 5 # TODO: NEED MAJOR REFACTOR 6 # 7 8 import math 9 import wx 10 # from copy import deepcopy 11 # Debug printout 12 from sas.sasgui.guiframe.events import NewPlotEvent 13 from sas.sasgui.guiframe.events import StatusEvent 14 from sas.sasgui.guiframe.events import SlicerParameterEvent 15 from sas.sasgui.guiframe.events import EVT_SLICER_PARS 1 import numpy 2 from PyQt4 import QtGui 3 from PyQt4 import QtCore 4 16 5 from BaseInteractor import _BaseInteractor 17 6 from sas.sasgui.guiframe.dataFitting import Data1D 18 19 class AnnulusInteractor(_BaseInteractor): 7 import sas.qtgui.Utilities.GuiUtils as GuiUtils 8 from sas.qtgui.Utilities.GuiUtils import formatNumber 9 from sas.qtgui.Plotting.SlicerModel import SlicerModel 10 11 class AnnulusInteractor(_BaseInteractor, SlicerModel): 20 12 """ 21 13 Select an annulus through a 2D plot. … … 24 16 this class is defined by 2 Ringinterators. 25 17 """ 26 def __init__(self, base, axes, color='black', zorder=3):18 def __init__(self, base, axes, item=None, color='black', zorder=3): 27 19 28 20 _BaseInteractor.__init__(self, base, axes, color=color) 21 SlicerModel.__init__(self) 22 29 23 self.markers = [] 30 24 self.axes = axes 31 25 self.base = base 32 self.qmax = min(math.fabs(self.base.data2D.xmax), 33 math.fabs(self.base.data2D.xmin)) # must be positive 26 self._item = item 27 self.qmax = min(numpy.fabs(self.base.data.xmax), 28 numpy.fabs(self.base.data.xmin)) # must be positive 34 29 self.connect = self.base.connect 35 30 36 # #Number of points on the plot31 # Number of points on the plot 37 32 self.nbins = 36 38 33 # Cursor position of Rings (Left(-1) or Right(1)) 39 self.xmaxd = self.base.data 2D.xmax40 self.xmind = self.base.data 2D.xmin34 self.xmaxd = self.base.data.xmax 35 self.xmind = self.base.data.xmin 41 36 42 37 if (self.xmaxd + self.xmind) > 0: … … 45 40 self.sign = -1 46 41 # Inner circle 47 self.inner_circle = RingInteractor(self, self. base.subplot,42 self.inner_circle = RingInteractor(self, self.axes, 48 43 zorder=zorder, 49 44 r=self.qmax / 2.0, sign=self.sign) 50 45 self.inner_circle.qmax = self.qmax 51 self.outer_circle = RingInteractor(self, self. base.subplot,46 self.outer_circle = RingInteractor(self, self.axes, 52 47 zorder=zorder + 1, r=self.qmax / 1.8, 53 48 sign=self.sign) … … 56 51 self._post_data() 57 52 58 # Bind to slice parameter events 59 self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS) 60 61 def _onEVT_SLICER_PARS(self, event): 62 """ 63 receive an event containing parameters values to reset the slicer 64 65 :param event: event of type SlicerParameterEvent with params as 66 attribute 67 68 """ 69 wx.PostEvent(self.base, 70 StatusEvent(status="AnnulusSlicer._onEVT_SLICER_PARS")) 71 event.Skip() 72 if event.type == self.__class__.__name__: 73 self.set_params(event.params) 74 self.base.update() 53 self.setModelFromParams() 75 54 76 55 def set_layer(self, n): … … 92 71 self.inner_circle.clear() 93 72 self.base.connect.clearall() 94 self.base.Unbind(EVT_SLICER_PARS)95 73 96 74 def update(self): … … 108 86 can restore on Esc. 109 87 """ 110 self.base.freeze_axes()111 88 self.inner_circle.save(ev) 112 89 self.outer_circle.save(ev) … … 120 97 """ 121 98 # Data to average 122 data = self.base.data2D 123 # If we have no data, just return 99 data = self.base.data 124 100 if data is None: 125 101 return 126 102 127 103 from sas.sascalc.dataloader.manipulations import Ring 128 rmin = min( math.fabs(self.inner_circle.get_radius()),129 math.fabs(self.outer_circle.get_radius()))130 rmax = max( math.fabs(self.inner_circle.get_radius()),131 math.fabs(self.outer_circle.get_radius()))132 # if the user does not specify the numbers of points to plot104 rmin = min(numpy.fabs(self.inner_circle.get_radius()), 105 numpy.fabs(self.outer_circle.get_radius())) 106 rmax = max(numpy.fabs(self.inner_circle.get_radius()), 107 numpy.fabs(self.outer_circle.get_radius())) 108 # If the user does not specify the numbers of points to plot 133 109 # the default number will be nbins= 36 134 110 if nbins is None: … … 136 112 else: 137 113 self.nbins = nbins 138 # # create the data1D Q average of data2D114 # Create the data1D Q average of data2D 139 115 sect = Ring(r_min=rmin, r_max=rmax, nbins=self.nbins) 140 sector = sect(self.base.data 2D)116 sector = sect(self.base.data) 141 117 142 118 if hasattr(sector, "dxl"): … … 148 124 else: 149 125 dxw = None 150 new_plot = Data1D(x=(sector.x - math.pi) * 180 / math.pi,126 new_plot = Data1D(x=(sector.x - numpy.pi) * 180 / numpy.pi, 151 127 y=sector.y, dy=sector.dy) 152 128 new_plot.dxl = dxl 153 129 new_plot.dxw = dxw 154 new_plot.name = "AnnulusPhi" + "(" + self.base.data 2D.name + ")"155 156 new_plot.source = self.base.data2D.source 157 # new_plot.info=self.base.data2D.info130 new_plot.name = "AnnulusPhi" + "(" + self.base.data.name + ")" 131 new_plot.title = "AnnulusPhi" + "(" + self.base.data.name + ")" 132 133 new_plot.source = self.base.data.source 158 134 new_plot.interactive = True 159 new_plot.detector = self.base.data 2D.detector135 new_plot.detector = self.base.data.detector 160 136 # If the data file does not tell us what the axes are, just assume... 161 137 new_plot.xaxis("\\rm{\phi}", 'degrees') 162 138 new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}") 163 139 if hasattr(data, "scale") and data.scale == 'linear' and \ 164 self.base.data 2D.name.count("Residuals") > 0:140 self.base.data.name.count("Residuals") > 0: 165 141 new_plot.ytransform = 'y' 166 142 new_plot.yaxis("\\rm{Residuals} ", "/") 167 143 168 new_plot.group_id = "AnnulusPhi" + self.base.data 2D.name169 new_plot.id = "AnnulusPhi" + self.base.data 2D.name144 new_plot.group_id = "AnnulusPhi" + self.base.data.name 145 new_plot.id = "AnnulusPhi" + self.base.data.name 170 146 new_plot.is_data = True 171 147 new_plot.xtransform = "x" 172 148 new_plot.ytransform = "y" 173 self.base.parent.update_theory(data_id=data.id, theory=new_plot) 174 wx.PostEvent(self.base.parent, NewPlotEvent(plot=new_plot, title="AnnulusPhi")) 149 variant_plot = QtCore.QVariant(new_plot) 150 GuiUtils.updateModelItemWithPlot(self._item, variant_plot, new_plot.id) 151 self.base.manager.communicator.plotUpdateSignal.emit([new_plot]) 152 153 if self.update_model: 154 self.setModelFromParams() 155 self.draw() 156 157 def validate(self, param_name, param_value): 158 """ 159 Test the proposed new value "value" for row "row" of parameters 160 """ 161 MIN_DIFFERENCE = 0.01 162 isValid = True 163 164 if param_name == 'inner_radius': 165 # First, check the closeness 166 if numpy.fabs(param_value - self.getParams()['outer_radius']) < MIN_DIFFERENCE: 167 print("Inner and outer radii too close. Please adjust.") 168 isValid = False 169 elif param_value > self.qmax: 170 print("Inner radius exceeds maximum range. Please adjust.") 171 isValid = False 172 elif param_name == 'outer_radius': 173 # First, check the closeness 174 if numpy.fabs(param_value - self.getParams()['inner_radius']) < MIN_DIFFERENCE: 175 print("Inner and outer radii too close. Please adjust.") 176 isValid = False 177 elif param_value > self.qmax: 178 print("Outer radius exceeds maximum range. Please adjust.") 179 isValid = False 180 elif param_name == 'nbins': 181 # Can't be 0 182 if param_value < 1: 183 print("Number of bins cannot be less than or equal to 0. Please adjust.") 184 isValid = False 185 186 return isValid 175 187 176 188 def moveend(self, ev): 177 189 """ 178 190 Called when any dragging motion ends. 179 Post an event (type =SlicerParameterEvent) 180 to plotter 2D with a copy slicer parameters 181 Call _post_data method 182 """ 183 self.base.thaw_axes() 184 # Post parameters to plotter 2D 185 event = SlicerParameterEvent() 186 event.type = self.__class__.__name__ 187 event.params = self.get_params() 188 wx.PostEvent(self.base, event) 191 Redraw the plot with new parameters. 192 """ 193 self._post_data(self.nbins) 189 194 190 195 def restore(self): … … 204 209 pass 205 210 206 def get _params(self):211 def getParams(self): 207 212 """ 208 213 Store a copy of values of parameters of the slicer into a dictionary. 209 210 214 :return params: the dictionary created 211 212 215 """ 213 216 params = {} 214 params["inner_radius"] = math.fabs(self.inner_circle._inner_mouse_x)215 params["outer_radius"] = math.fabs(self.outer_circle._inner_mouse_x)217 params["inner_radius"] = numpy.fabs(self.inner_circle._inner_mouse_x) 218 params["outer_radius"] = numpy.fabs(self.outer_circle._inner_mouse_x) 216 219 params["nbins"] = self.nbins 217 220 return params 218 221 219 def set _params(self, params):222 def setParams(self, params): 220 223 """ 221 224 Receive a dictionary and reset the slicer with values contained … … 224 227 :param params: a dictionary containing name of slicer parameters and 225 228 values the user assigned to the slicer. 226 227 """ 228 inner = math.fabs(params["inner_radius"]) 229 outer = math.fabs(params["outer_radius"]) 229 """ 230 inner = numpy.fabs(params["inner_radius"]) 231 outer = numpy.fabs(params["outer_radius"]) 230 232 self.nbins = int(params["nbins"]) 231 # #Update the picture233 # Update the picture 232 234 self.inner_circle.set_cursor(inner, self.inner_circle._inner_mouse_y) 233 235 self.outer_circle.set_cursor(outer, self.outer_circle._inner_mouse_y) 234 # #Post the data given the nbins entered by the user236 # Post the data given the nbins entered by the user 235 237 self._post_data(self.nbins) 236 237 def freeze_axes(self):238 """239 """240 self.base.freeze_axes()241 242 def thaw_axes(self):243 """244 """245 self.base.thaw_axes()246 238 247 239 def draw(self): … … 278 270 self.sign = sign 279 271 # # Create a marker 280 try: 281 # Inner circle marker 282 x_value = [self.sign * math.fabs(self._inner_mouse_x)] 283 self.inner_marker = self.axes.plot(x_value, [0], linestyle='', 284 marker='s', markersize=10, 285 color=self.color, alpha=0.6, 286 pickradius=5, label="pick", 287 zorder=zorder, 288 visible=True)[0] 289 except: 290 x_value = [self.sign * math.fabs(self._inner_mouse_x)] 291 self.inner_marker = self.axes.plot(x_value, [0], linestyle='', 292 marker='s', markersize=10, 293 color=self.color, alpha=0.6, 294 label="pick", 295 visible=True)[0] 296 message = "\nTHIS PROTOTYPE NEEDS THE LATEST" 297 message += " VERSION OF MATPLOTLIB\n" 298 message += "Get the SVN version that is at " 299 message += " least as recent as June 1, 2007" 300 301 owner = self.base.base.parent 302 wx.PostEvent(owner, StatusEvent(status="AnnulusSlicer: %s" % message)) 303 272 # Inner circle marker 273 x_value = [self.sign * numpy.fabs(self._inner_mouse_x)] 274 self.inner_marker = self.axes.plot(x_value, [0], linestyle='', 275 marker='s', markersize=10, 276 color=self.color, alpha=0.6, 277 pickradius=5, label="pick", 278 zorder=zorder, 279 visible=True)[0] 304 280 # Draw a circle 305 281 [self.inner_circle] = self.axes.plot([], [], linestyle='-', marker='', color=self.color) 306 # the number of points that make the ring line282 # The number of points that make the ring line 307 283 self.npts = 40 308 284 … … 325 301 """ 326 302 self.clear_markers() 327 try: 328 self.inner_marker.remove() 329 self.inner_circle.remove() 330 except: 331 # Old version of matplotlib 332 for item in range(len(self.axes.lines)): 333 del self.axes.lines[0] 303 self.inner_marker.remove() 304 self.inner_circle.remove() 334 305 335 306 def get_radius(self): … … 347 318 y = [] 348 319 for i in range(self.npts): 349 phi = 2.0 * math.pi / (self.npts - 1) * i350 351 xval = 1.0 * self._inner_mouse_x * math.cos(phi)352 yval = 1.0 * self._inner_mouse_x * math.sin(phi)320 phi = 2.0 * numpy.pi / (self.npts - 1) * i 321 322 xval = 1.0 * self._inner_mouse_x * numpy.cos(phi) 323 yval = 1.0 * self._inner_mouse_x * numpy.sin(phi) 353 324 354 325 x.append(xval) 355 326 y.append(yval) 356 327 357 self.inner_marker.set(xdata=[self.sign * math.fabs(self._inner_mouse_x)],328 self.inner_marker.set(xdata=[self.sign * numpy.fabs(self._inner_mouse_x)], 358 329 ydata=[0]) 359 330 self.inner_circle.set_data(x, y) … … 366 337 self._inner_save_x = self._inner_mouse_x 367 338 self._inner_save_y = self._inner_mouse_y 368 self.base.freeze_axes()369 339 370 340 def moveend(self, ev): … … 396 366 self.update() 397 367 398 399 def get_params(self): 368 def getParams(self): 400 369 """ 401 370 Store a copy of values of parameters of the slicer into a dictionary. 402 403 371 :return params: the dictionary created 404 405 372 """ 406 373 params = {} 407 params["radius"] = math.fabs(self._inner_mouse_x)374 params["radius"] = numpy.fabs(self._inner_mouse_x) 408 375 return params 409 376 410 def set _params(self, params):377 def setParams(self, params): 411 378 """ 412 379 Receive a dictionary and reset the slicer with values contained … … 435 402 self.base = base 436 403 self.is_inside = side 437 self.qmax = min( math.fabs(self.base.data.xmax),438 math.fabs(self.base.data.xmin)) # must be positive404 self.qmax = min(numpy.fabs(self.base.data.xmax), 405 numpy.fabs(self.base.data.xmin)) # must be positive 439 406 self.connect = self.base.connect 440 407 … … 448 415 self.sign = -1 449 416 # Inner circle 450 self.outer_circle = RingInteractor(self, self. base.subplot, 'blue',417 self.outer_circle = RingInteractor(self, self.axes, 'blue', 451 418 zorder=zorder + 1, r=self.qmax / 1.8, 452 419 sign=self.sign) … … 455 422 self._post_data() 456 423 457 # Bind to slice parameter events458 # self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS)459 460 def _onEVT_SLICER_PARS(self, event):461 """462 receive an event containing parameters values to reset the slicer463 464 :param event: event of type SlicerParameterEvent with params as465 attribute466 """467 wx.PostEvent(self.base,468 StatusEvent(status="AnnulusSlicer._onEVT_SLICER_PARS"))469 event.Skip()470 if event.type == self.__class__.__name__:471 self.set_params(event.params)472 self.base.update()473 474 424 def set_layer(self, n): 475 425 """ 476 426 Allow adding plot to the same panel 477 478 427 :param n: the number of layer 479 480 428 """ 481 429 self.layernum = n … … 489 437 self.outer_circle.clear() 490 438 self.base.connect.clearall() 491 # self.base.Unbind(EVT_SLICER_PARS)492 439 493 440 def update(self): … … 498 445 # Update locations 499 446 self.outer_circle.update() 500 # if self.is_inside is not None:447 self._post_data() 501 448 out = self._post_data() 502 449 return out … … 507 454 can restore on Esc. 508 455 """ 509 self.base.freeze_axes()510 456 self.outer_circle.save(ev) 511 457 … … 527 473 528 474 rmin = 0 529 rmax = math.fabs(self.outer_circle.get_radius())530 531 # # create the data1D Q average of data2D475 rmax = numpy.fabs(self.outer_circle.get_radius()) 476 477 # Create the data1D Q average of data2D 532 478 mask = Ringcut(r_min=rmin, r_max=rmax) 533 479 … … 536 482 else: 537 483 out = (mask(data)) 538 # self.base.data.mask=out539 484 return out 540 485 … … 566 511 pass 567 512 568 def get _params(self):513 def getParams(self): 569 514 """ 570 515 Store a copy of values of parameters of the slicer into a dictionary. … … 574 519 """ 575 520 params = {} 576 params["outer_radius"] = math.fabs(self.outer_circle._inner_mouse_x)521 params["outer_radius"] = numpy.fabs(self.outer_circle._inner_mouse_x) 577 522 return params 578 523 579 def set _params(self, params):524 def setParams(self, params): 580 525 """ 581 526 Receive a dictionary and reset the slicer with values contained … … 585 530 values the user assigned to the slicer. 586 531 """ 587 outer = math.fabs(params["outer_radius"])588 # #Update the picture532 outer = numpy.fabs(params["outer_radius"]) 533 # Update the picture 589 534 self.outer_circle.set_cursor(outer, self.outer_circle._inner_mouse_y) 590 # #Post the data given the nbins entered by the user535 # Post the data given the nbins entered by the user 591 536 self._post_data() 592 593 def freeze_axes(self):594 self.base.freeze_axes()595 596 def thaw_axes(self):597 self.base.thaw_axes()598 537 599 538 def draw(self): -
src/sas/sasgui/guiframe/local_perspectives/plotting/AzimutSlicer.py
rd85c194 r161713c 182 182 NewPlotEvent(plot=new_plot, title=str(new_sector.__name__))) 183 183 184 185 def validate(self, param_name, param_value): 186 """ 187 Test the proposed new value "value" for row "row" of parameters 188 """ 189 # Here, always return true 190 return True 191 184 192 def moveend(self, ev): 185 193 #TODO: why is this empty? -
src/sas/sasgui/guiframe/local_perspectives/plotting/Plotter1D.py
r7432acb rc416a17 1 2 1 ################################################################################ 3 2 # This software was developed by the University of Tennessee as part of the -
src/sas/sasgui/guiframe/local_perspectives/plotting/SectorSlicer.py
r8de66b6 rc416a17 2 2 Sector interactor 3 3 """ 4 import math 5 import wx 4 import numpy 5 from PyQt4 import QtGui 6 from PyQt4 import QtCore 7 6 8 from BaseInteractor import _BaseInteractor 7 from sas.sasgui.guiframe.events import NewPlotEvent8 from sas.sasgui.guiframe.events import StatusEvent9 from sas.sasgui.guiframe.events import SlicerParameterEvent10 from sas.sasgui.guiframe.events import EVT_SLICER_PARS11 9 from sas.sasgui.guiframe.dataFitting import Data1D 12 13 14 class SectorInteractor(_BaseInteractor): 10 import sas.qtgui.Utilities.GuiUtils as GuiUtils 11 from sas.qtgui.Plotting.SlicerModel import SlicerModel 12 13 MIN_PHI = 0.05 14 15 class SectorInteractor(_BaseInteractor, SlicerModel): 15 16 """ 16 17 Draw a sector slicer.Allow to performQ averaging on data 2D 17 18 """ 18 def __init__(self, base, axes, color='black', zorder=3):19 def __init__(self, base, axes, item=None, color='black', zorder=3): 19 20 20 21 _BaseInteractor.__init__(self, base, axes, color=color) 21 ## Class initialization 22 SlicerModel.__init__(self) 23 # Class initialization 22 24 self.markers = [] 23 25 self.axes = axes 24 ## connect the plot to event 26 self._item = item 27 # Connect the plot to event 25 28 self.connect = self.base.connect 26 29 27 # # compute qmax limit to reset the graph28 x = math.pow(max(self.base.data2D.xmax,29 math.fabs(self.base.data2D.xmin)), 2)30 y = math.pow(max(self.base.data2D.ymax,31 math.fabs(self.base.data2D.ymin)), 2)32 self.qmax = math.sqrt(x + y)33 # #Number of points on the plot30 # Compute qmax limit to reset the graph 31 x = numpy.power(max(self.base.data.xmax, 32 numpy.fabs(self.base.data.xmin)), 2) 33 y = numpy.power(max(self.base.data.ymax, 34 numpy.fabs(self.base.data.ymin)), 2) 35 self.qmax = numpy.sqrt(x + y) 36 # Number of points on the plot 34 37 self.nbins = 20 35 ## Angle of the middle line 36 self.theta2 = math.pi / 3 37 ## Absolute value of the Angle between the middle line and any side line 38 self.phi = math.pi / 12 39 # Binning base for log/lin binning 40 self.bin_base = 0 41 ## Middle line 42 self.main_line = LineInteractor(self, self.base.subplot, color='blue', 38 # Angle of the middle line 39 self.theta2 = numpy.pi / 3 40 # Absolute value of the Angle between the middle line and any side line 41 self.phi = numpy.pi / 12 42 # Middle line 43 self.main_line = LineInteractor(self, self.axes, color='blue', 43 44 zorder=zorder, r=self.qmax, 44 45 theta=self.theta2) 45 46 self.main_line.qmax = self.qmax 46 # #Right Side line47 self.right_line = SideInteractor(self, self. base.subplot, color='black',47 # Right Side line 48 self.right_line = SideInteractor(self, self.axes, color='black', 48 49 zorder=zorder, r=self.qmax, 49 50 phi=-1 * self.phi, theta2=self.theta2) 50 51 self.right_line.qmax = self.qmax 51 # #Left Side line52 self.left_line = SideInteractor(self, self. base.subplot, color='black',52 # Left Side line 53 self.left_line = SideInteractor(self, self.axes, color='black', 53 54 zorder=zorder, r=self.qmax, 54 55 phi=self.phi, theta2=self.theta2) 55 56 self.left_line.qmax = self.qmax 56 # #draw the sector57 # draw the sector 57 58 self.update() 58 59 self._post_data() 59 ## Bind to slice parameter events 60 self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS) 61 62 def _onEVT_SLICER_PARS(self, event): 63 """ 64 receive an event containing parameters values to reset the slicer 65 66 :param event: event of type SlicerParameterEvent with params as 67 attribute 68 69 """ 70 wx.PostEvent(self.base.parent, 71 StatusEvent(status="SectorSlicer._onEVT_SLICER_PARS")) 72 event.Skip() 73 if event.type == self.__class__.__name__: 74 self.set_params(event.params) 75 self.base.update() 60 self.setModelFromParams() 76 61 77 62 def set_layer(self, n): 78 63 """ 79 64 Allow adding plot to the same panel 80 81 65 :param n: the number of layer 82 83 66 """ 84 67 self.layernum = n … … 94 77 self.right_line.clear() 95 78 self.base.connect.clearall() 96 self.base.Unbind(EVT_SLICER_PARS)97 79 98 80 def update(self): … … 102 84 """ 103 85 # Update locations 104 # #Check if the middle line was dragged and105 # update the picture accordingly86 # Check if the middle line was dragged and 87 # update the picture accordingly 106 88 if self.main_line.has_move: 107 89 self.main_line.update() … … 110 92 self.left_line.update(delta=self.left_line.phi / 2, 111 93 mline=self.main_line.theta) 112 # #Check if the left side has moved and update the slicer accordingly94 # Check if the left side has moved and update the slicer accordingly 113 95 if self.left_line.has_move: 114 96 self.main_line.update() … … 118 100 mline=self.main_line, side=True, 119 101 left=False, right=True) 120 ## Check if the right side line has moved and 121 #update the slicer accordingly 102 # Check if the right side line has moved and update the slicer accordingly 122 103 if self.right_line.has_move: 123 104 self.main_line.update() … … 132 113 can restore on Esc. 133 114 """ 134 self.base.freeze_axes()135 115 self.main_line.save(ev) 136 116 self.right_line.save(ev) … … 143 123 :param nbins: the number of point to plot for the average 1D data 144 124 """ 145 # # get the data2D to average146 data = self.base.data 2D125 # Get the data2D to average 126 data = self.base.data 147 127 # If we have no data, just return 148 if data isNone:128 if data == None: 149 129 return 150 # #Averaging130 # Averaging 151 131 from sas.sascalc.dataloader.manipulations import SectorQ 152 132 radius = self.qmax 153 133 phimin = -self.left_line.phi + self.main_line.theta 154 134 phimax = self.left_line.phi + self.main_line.theta 155 bin_base = self.bin_base 156 if nbins is None: 135 if nbins == None: 157 136 nbins = 20 158 137 sect = SectorQ(r_min=0.0, r_max=radius, 159 phi_min=phimin + math.pi,160 phi_max=phimax + math.pi, nbins=nbins, base=bin_base)161 162 sector = sect(self.base.data 2D)163 # #Create 1D data resulting from average138 phi_min=phimin + numpy.pi, 139 phi_max=phimax + numpy.pi, nbins=nbins) 140 141 sector = sect(self.base.data) 142 # Create 1D data resulting from average 164 143 165 144 if hasattr(sector, "dxl"): … … 174 153 new_plot.dxl = dxl 175 154 new_plot.dxw = dxw 176 new_plot.name = "SectorQ" + "(" + self.base.data 2D.name + ")"177 new_plot. source = self.base.data2D.source178 #new_plot.info=self.base.data2D.info155 new_plot.name = "SectorQ" + "(" + self.base.data.name + ")" 156 new_plot.title = "SectorQ" + "(" + self.base.data.name + ")" 157 new_plot.source = self.base.data.source 179 158 new_plot.interactive = True 180 new_plot.detector = self.base.data 2D.detector181 # # If the data file does not tell us what the axes are, just assume...159 new_plot.detector = self.base.data.detector 160 # If the data file does not tell us what the axes are, just assume them. 182 161 new_plot.xaxis("\\rm{Q}", "A^{-1}") 183 162 new_plot.yaxis("\\rm{Intensity}", "cm^{-1}") 184 163 if hasattr(data, "scale") and data.scale == 'linear' and \ 185 self.base.data 2D.name.count("Residuals") > 0:164 self.base.data.name.count("Residuals") > 0: 186 165 new_plot.ytransform = 'y' 187 166 new_plot.yaxis("\\rm{Residuals} ", "/") 188 167 189 new_plot.group_id = "2daverage" + self.base.data 2D.name190 new_plot.id = "SectorQ" + self.base.data 2D.name168 new_plot.group_id = "2daverage" + self.base.data.name 169 new_plot.id = "SectorQ" + self.base.data.name 191 170 new_plot.is_data = True 192 self.base.parent.update_theory(data_id=data.id, theory=new_plot) 193 wx.PostEvent(self.base.parent, 194 NewPlotEvent(plot=new_plot, title="SectorQ" + self.base.data2D.name)) 171 variant_plot = QtCore.QVariant(new_plot) 172 GuiUtils.updateModelItemWithPlot(self._item, variant_plot, new_plot.id) 173 self.base.manager.communicator.plotUpdateSignal.emit([new_plot]) 174 175 if self.update_model: 176 self.setModelFromParams() 177 self.draw() 178 179 def validate(self, param_name, param_value): 180 """ 181 Test the proposed new value "value" for row "row" of parameters 182 """ 183 MIN_DIFFERENCE = 0.01 184 isValid = True 185 186 if param_name == 'Delta_Phi [deg]': 187 # First, check the closeness 188 if numpy.fabs(param_value) < MIN_DIFFERENCE: 189 print("Sector angles too close. Please adjust.") 190 isValid = False 191 elif param_name == 'nbins': 192 # Can't be 0 193 if param_value < 1: 194 print("Number of bins cannot be less than or equal to 0. Please adjust.") 195 isValid = False 196 return isValid 195 197 196 198 def moveend(self, ev): … … 198 200 Called a dragging motion ends.Get slicer event 199 201 """ 200 self.base.thaw_axes() 201 ## Post parameters 202 event = SlicerParameterEvent() 203 event.type = self.__class__.__name__ 204 event.params = self.get_params() 205 ## Send slicer paramers to plotter2D 206 wx.PostEvent(self.base, event) 202 # Post parameters 203 self._post_data(self.nbins) 207 204 208 205 def restore(self): … … 225 222 pass 226 223 227 def get _params(self):224 def getParams(self): 228 225 """ 229 226 Store a copy of values of parameters of the slicer into a dictionary. 230 231 227 :return params: the dictionary created 232 233 228 """ 234 229 params = {} 235 # #Always make sure that the left and the right line are at phi236 # #angle of the middle line237 if math.fabs(self.left_line.phi) != math.fabs(self.right_line.phi):230 # Always make sure that the left and the right line are at phi 231 # angle of the middle line 232 if numpy.fabs(self.left_line.phi) != numpy.fabs(self.right_line.phi): 238 233 msg = "Phi left and phi right are different" 239 234 msg += " %f, %f" % (self.left_line.phi, self.right_line.phi) 240 235 raise ValueError, msg 241 params["Phi [deg]"] = self.main_line.theta * 180 / math.pi242 params["Delta_Phi [deg]"] = math.fabs(self.left_line.phi * 180 / math.pi)236 params["Phi [deg]"] = self.main_line.theta * 180 / numpy.pi 237 params["Delta_Phi [deg]"] = numpy.fabs(self.left_line.phi * 180 / numpy.pi) 243 238 params["nbins"] = self.nbins 244 params["binning base"] = self.bin_base245 239 return params 246 240 247 def set _params(self, params):241 def setParams(self, params): 248 242 """ 249 243 Receive a dictionary and reset the slicer with values contained … … 253 247 values the user assigned to the slicer. 254 248 """ 255 main = params["Phi [deg]"] * math.pi / 180 256 phi = math.fabs(params["Delta_Phi [deg]"] * math.pi / 180) 249 main = params["Phi [deg]"] * numpy.pi / 180 250 phi = numpy.fabs(params["Delta_Phi [deg]"] * numpy.pi / 180) 251 252 # phi should not be too close. 253 if numpy.fabs(phi) < MIN_PHI: 254 phi = MIN_PHI 255 params["Delta_Phi [deg]"] = MIN_PHI 256 257 257 self.nbins = int(params["nbins"]) 258 self.bin_base = params["binning base"]259 258 self.main_line.theta = main 260 # #Reset the slicer parameters259 # Reset the slicer parameters 261 260 self.main_line.update() 262 261 self.right_line.update(phi=phi, delta=None, mline=self.main_line, … … 264 263 self.left_line.update(phi=phi, delta=None, 265 264 mline=self.main_line, side=True) 266 # # post the new corresponding data265 # Post the new corresponding data 267 266 self._post_data(nbins=self.nbins) 268 267 269 def freeze_axes(self):270 """271 """272 self.base.freeze_axes()273 274 def thaw_axes(self):275 """276 """277 self.base.thaw_axes()278 279 268 def draw(self): 280 269 """ 270 Redraw canvas 281 271 """ 282 272 self.base.draw() … … 292 282 """ 293 283 def __init__(self, base, axes, color='black', zorder=5, r=1.0, 294 phi= math.pi / 4, theta2=math.pi / 3):284 phi=numpy.pi / 4, theta2=numpy.pi / 3): 295 285 """ 296 286 """ 297 287 _BaseInteractor.__init__(self, base, axes, color=color) 298 # #Initialize the class288 # Initialize the class 299 289 self.markers = [] 300 290 self.axes = axes 301 # #compute the value of the angle between the current line and302 # #the x-axis291 # compute the value of the angle between the current line and 292 # the x-axis 303 293 self.save_theta = theta2 + phi 304 294 self.theta = theta2 + phi 305 # #the value of the middle line angle with respect to the x-axis295 # the value of the middle line angle with respect to the x-axis 306 296 self.theta2 = theta2 307 # #Radius to find polar coordinates this line's endpoints297 # Radius to find polar coordinates this line's endpoints 308 298 self.radius = r 309 # #phi is the phase between the current line and the middle line299 # phi is the phase between the current line and the middle line 310 300 self.phi = phi 311 # #End points polar coordinates312 x1 = self.radius * math.cos(self.theta)313 y1 = self.radius * math.sin(self.theta)314 x2 = -1 * self.radius * math.cos(self.theta)315 y2 = -1 * self.radius * math.sin(self.theta)316 # # defining a new marker301 # End points polar coordinates 302 x1 = self.radius * numpy.cos(self.theta) 303 y1 = self.radius * numpy.sin(self.theta) 304 x2 = -1 * self.radius * numpy.cos(self.theta) 305 y2 = -1 * self.radius * numpy.sin(self.theta) 306 # Defining a new marker 317 307 self.inner_marker = self.axes.plot([x1 / 2.5], [y1 / 2.5], linestyle='', 318 308 marker='s', markersize=10, … … 321 311 zorder=zorder, visible=True)[0] 322 312 323 # #Defining the current line313 # Defining the current line 324 314 self.line = self.axes.plot([x1, x2], [y1, y2], 325 315 linestyle='-', marker='', 326 316 color=self.color, visible=True)[0] 327 # #Flag to differentiate the left line from the right line motion317 # Flag to differentiate the left line from the right line motion 328 318 self.left_moving = False 329 # #Flag to define a motion319 # Flag to define a motion 330 320 self.has_move = False 331 # #connecting markers and draw the picture321 # connecting markers and draw the picture 332 322 self.connect_markers([self.inner_marker, self.line]) 333 323 … … 335 325 """ 336 326 Allow adding plot to the same panel 337 338 327 :param n: the number of layer 339 340 328 """ 341 329 self.layernum = n … … 364 352 365 353 """ 366 #print "update left or right ", self.has_move367 354 self.left_moving = left 368 355 theta3 = 0 369 if phi is notNone:356 if phi != None: 370 357 self.phi = phi 371 if delta isNone:358 if delta == None: 372 359 delta = 0 373 360 if right: 374 self.phi = -1 * math.fabs(self.phi)361 self.phi = -1 * numpy.fabs(self.phi) 375 362 #delta=-delta 376 363 else: 377 self.phi = math.fabs(self.phi)364 self.phi = numpy.fabs(self.phi) 378 365 if side: 379 366 self.theta = mline.theta + self.phi 380 367 381 if mline is notNone:368 if mline != None: 382 369 if delta != 0: 383 370 self.theta2 = mline + delta … … 388 375 else: 389 376 theta3 = self.theta2 + delta 390 x1 = self.radius * math.cos(theta3)391 y1 = self.radius * math.sin(theta3)392 x2 = -1 * self.radius * math.cos(theta3)393 y2 = -1 * self.radius * math.sin(theta3)377 x1 = self.radius * numpy.cos(theta3) 378 y1 = self.radius * numpy.sin(theta3) 379 x2 = -1 * self.radius * numpy.cos(theta3) 380 y2 = -1 * self.radius * numpy.sin(theta3) 394 381 self.inner_marker.set(xdata=[x1 / 2.5], ydata=[y1 / 2.5]) 395 382 self.line.set(xdata=[x1, x2], ydata=[y1, y2]) … … 401 388 """ 402 389 self.save_theta = self.theta 403 self.base.freeze_axes()404 390 405 391 def moveend(self, ev): … … 419 405 Process move to a new position, making sure that the move is allowed. 420 406 """ 421 self.theta = math.atan2(y, x)407 self.theta = numpy.arctan2(y, x) 422 408 self.has_move = True 423 #ToDo: Simplify below424 409 if not self.left_moving: 425 410 if self.theta2 - self.theta <= 0 and self.theta2 > 0: … … 431 416 return 432 417 elif self.theta2 < 0 and self.theta > 0 and \ 433 (self.theta2 + 2 * math.pi - self.theta) >= math.pi / 2:418 (self.theta2 + 2 * numpy.pi - self.theta) >= numpy.pi / 2: 434 419 self.restore() 435 420 return 436 421 elif self.theta2 < 0 and self.theta < 0 and \ 437 (self.theta2 - self.theta) >= math.pi / 2:438 self.restore() 439 return 440 elif self.theta2 > 0 and (self.theta2 - self.theta >= math.pi / 2 or \441 (self.theta2 - self.theta >= math.pi / 2)):422 (self.theta2 - self.theta) >= numpy.pi / 2: 423 self.restore() 424 return 425 elif self.theta2 > 0 and (self.theta2 - self.theta >= numpy.pi / 2 or \ 426 (self.theta2 - self.theta >= numpy.pi / 2)): 442 427 self.restore() 443 428 return 444 429 else: 445 if self.theta < 0 and (self.theta + math.pi * 2 - self.theta2) <= 0:430 if self.theta < 0 and (self.theta + numpy.pi * 2 - self.theta2) <= 0: 446 431 self.restore() 447 432 return … … 452 437 self.restore() 453 438 return 454 elif self.theta - self.theta2 >= math.pi / 2 or \455 ((self.theta + math.pi * 2 - self.theta2) >= math.pi / 2 and \439 elif self.theta - self.theta2 >= numpy.pi / 2 or \ 440 ((self.theta + numpy.pi * 2 - self.theta2) >= numpy.pi / 2 and \ 456 441 self.theta < 0 and self.theta2 > 0): 457 442 self.restore() 458 443 return 459 460 self.phi = math.fabs(self.theta2 - self.theta) 461 if self.phi > math.pi: 462 self.phi = 2 * math.pi - math.fabs(self.theta2 - self.theta) 444 self.phi = numpy.fabs(self.theta2 - self.theta) 445 if self.phi > numpy.pi: 446 self.phi = 2 * numpy.pi - numpy.fabs(self.theta2 - self.theta) 463 447 self.base.base.update() 464 448 … … 469 453 self.update() 470 454 471 def get _params(self):455 def getParams(self): 472 456 """ 473 457 """ … … 477 461 return params 478 462 479 def set _params(self, params):463 def setParams(self, params): 480 464 """ 481 465 """ … … 489 473 """ 490 474 def __init__(self, base, axes, color='black', 491 zorder=5, r=1.0, theta= math.pi / 4):475 zorder=5, r=1.0, theta=numpy.pi / 4): 492 476 """ 493 477 """ … … 501 485 self.scale = 10.0 502 486 # Inner circle 503 x1 = self.radius * math.cos(self.theta)504 y1 = self.radius * math.sin(self.theta)505 x2 = -1 * self.radius * math.cos(self.theta)506 y2 = -1 * self.radius * math.sin(self.theta)487 x1 = self.radius * numpy.cos(self.theta) 488 y1 = self.radius * numpy.sin(self.theta) 489 x2 = -1 * self.radius * numpy.cos(self.theta) 490 y2 = -1 * self.radius * numpy.sin(self.theta) 507 491 # Inner circle marker 508 492 self.inner_marker = self.axes.plot([x1 / 2.5], [y1 / 2.5], linestyle='', … … 543 527 """ 544 528 545 if theta is notNone:529 if theta != None: 546 530 self.theta = theta 547 x1 = self.radius * math.cos(self.theta)548 y1 = self.radius * math.sin(self.theta)549 x2 = -1 * self.radius * math.cos(self.theta)550 y2 = -1 * self.radius * math.sin(self.theta)531 x1 = self.radius * numpy.cos(self.theta) 532 y1 = self.radius * numpy.sin(self.theta) 533 x2 = -1 * self.radius * numpy.cos(self.theta) 534 y2 = -1 * self.radius * numpy.sin(self.theta) 551 535 552 536 self.inner_marker.set(xdata=[x1 / 2.5], ydata=[y1 / 2.5]) … … 559 543 """ 560 544 self.save_theta = self.theta 561 self.base.freeze_axes()562 545 563 546 def moveend(self, ev): … … 577 560 Process move to a new position, making sure that the move is allowed. 578 561 """ 579 self.theta = math.atan2(y, x)562 self.theta = numpy.arctan2(y, x) 580 563 self.has_move = True 581 564 self.base.base.update() … … 587 570 self.update() 588 571 589 def get _params(self):572 def getParams(self): 590 573 """ 591 574 """ … … 595 578 return params 596 579 597 def set _params(self, params):580 def setParams(self, params): 598 581 """ 599 582 """ -
src/sas/sasgui/guiframe/local_perspectives/plotting/boxSlicer.py
r7432acb r83eb5208 1 import wx 2 import math 3 import numpy as np 4 from sas.sasgui.guiframe.events import NewPlotEvent 5 from sas.sasgui.guiframe.events import StatusEvent 6 from sas.sasgui.guiframe.events import SlicerParameterEvent 7 from sas.sasgui.guiframe.events import EVT_SLICER_PARS 1 import numpy 2 from PyQt4 import QtGui 3 from PyQt4 import QtCore 4 8 5 from BaseInteractor import _BaseInteractor 9 6 from sas.sasgui.guiframe.dataFitting import Data1D 10 11 12 class BoxInteractor(_BaseInteractor): 7 import sas.qtgui.Utilities.GuiUtils as GuiUtils 8 from sas.qtgui.Plotting.SlicerModel import SlicerModel 9 10 11 class BoxInteractor(_BaseInteractor, SlicerModel): 13 12 """ 14 13 BoxInteractor define a rectangle that return data1D average of Data2D 15 14 in a rectangle area defined by -x, x ,y, -y 16 15 """ 17 def __init__(self, base, axes, color='black', zorder=3):16 def __init__(self, base, axes, item=None, color='black', zorder=3): 18 17 _BaseInteractor.__init__(self, base, axes, color=color) 19 # # Class initialization 18 SlicerModel.__init__(self) 19 # Class initialization 20 20 self.markers = [] 21 21 self.axes = axes 22 # #connecting artist 22 self._item = item 23 #connecting artist 23 24 self.connect = self.base.connect 24 # #which direction is the preferred interaction direction25 # which direction is the preferred interaction direction 25 26 self.direction = None 26 # #determine x y values27 self.x = 0.5 * min( math.fabs(self.base.data2D.xmax),28 math.fabs(self.base.data2D.xmin))29 self.y = 0.5 * min( math.fabs(self.base.data2D.xmax),30 math.fabs(self.base.data2D.xmin))31 # #when reach qmax reset the graph32 self.qmax = max(self.base.data 2D.xmax, self.base.data2D.xmin,33 self.base.data 2D.ymax, self.base.data2D.ymin)34 # #Number of points on the plot27 # determine x y values 28 self.x = 0.5 * min(numpy.fabs(self.base.data.xmax), 29 numpy.fabs(self.base.data.xmin)) 30 self.y = 0.5 * min(numpy.fabs(self.base.data.xmax), 31 numpy.fabs(self.base.data.xmin)) 32 # when reach qmax reset the graph 33 self.qmax = max(self.base.data.xmax, self.base.data.xmin, 34 self.base.data.ymax, self.base.data.ymin) 35 # Number of points on the plot 35 36 self.nbins = 30 36 # #If True, I(|Q|) will be return, otherwise,37 # If True, I(|Q|) will be return, otherwise, 37 38 # negative q-values are allowed 38 39 self.fold = True 39 # #reference of the current Slab averaging40 # reference of the current Slab averaging 40 41 self.averager = None 41 # #Create vertical and horizaontal lines for the rectangle42 # Create vertical and horizaontal lines for the rectangle 42 43 self.vertical_lines = VerticalLines(self, 43 self. base.subplot,44 self.axes, 44 45 color='blue', 45 46 zorder=zorder, … … 49 50 50 51 self.horizontal_lines = HorizontalLines(self, 51 self. base.subplot,52 self.axes, 52 53 color='green', 53 54 zorder=zorder, … … 55 56 y=self.y) 56 57 self.horizontal_lines.qmax = self.qmax 57 # #draw the rectangle and plost the data 1D resulting58 # #of averaging data2D58 # draw the rectangle and plost the data 1D resulting 59 # of averaging data2D 59 60 self.update() 60 61 self._post_data() 61 # # Bind to slice parameter events 62 self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS) 63 64 def _onEVT_SLICER_PARS(self, event): 65 """ 66 receive an event containing parameters values to reset the slicer 67 68 :param event: event of type SlicerParameterEvent with params as 69 attribute 70 """ 71 wx.PostEvent(self.base.parent, 72 StatusEvent(status="BoxSlicer._onEVT_SLICER_PARS")) 73 event.Skip() 74 if event.type == self.__class__.__name__: 75 self.set_params(event.params) 76 self.base.update() 62 self.setModelFromParams() 77 63 78 64 def update_and_post(self): … … 102 88 self.vertical_lines.clear() 103 89 self.base.connect.clearall() 104 self.base.Unbind(EVT_SLICER_PARS)105 90 106 91 def update(self): … … 123 108 can restore on Esc. 124 109 """ 125 self.base.freeze_axes()126 110 self.vertical_lines.save(ev) 127 111 self.horizontal_lines.save(ev) … … 142 126 self.direction = direction 143 127 144 x_min = -1 * math.fabs(self.vertical_lines.x)145 x_max = math.fabs(self.vertical_lines.x)146 y_min = -1 * math.fabs(self.horizontal_lines.y)147 y_max = math.fabs(self.horizontal_lines.y)128 x_min = -1 * numpy.fabs(self.vertical_lines.x) 129 x_max = numpy.fabs(self.vertical_lines.x) 130 y_min = -1 * numpy.fabs(self.horizontal_lines.y) 131 y_max = numpy.fabs(self.horizontal_lines.y) 148 132 149 133 if nbins is not None: … … 158 142 x_low = 0 159 143 else: 160 x_low = math.fabs(x_min)144 x_low = numpy.fabs(x_min) 161 145 bin_width = (x_max + x_low) / self.nbins 162 146 elif self.direction == "Y": … … 164 148 y_low = 0 165 149 else: 166 y_low = math.fabs(y_min)150 y_low = numpy.fabs(y_min) 167 151 bin_width = (y_max + y_low) / self.nbins 168 152 else: … … 173 157 bin_width=bin_width) 174 158 box.fold = self.fold 175 boxavg = box(self.base.data 2D)159 boxavg = box(self.base.data) 176 160 # 3 Create Data1D to plot 177 161 if hasattr(boxavg, "dxl"): … … 187 171 new_plot.dxw = dxw 188 172 new_plot.name = str(self.averager.__name__) + \ 189 "(" + self.base.data2D.name + ")" 190 new_plot.source = self.base.data2D.source 173 "(" + self.base.data.name + ")" 174 new_plot.title = str(self.averager.__name__) + \ 175 "(" + self.base.data.name + ")" 176 new_plot.source = self.base.data.source 191 177 new_plot.interactive = True 192 new_plot.detector = self.base.data 2D.detector178 new_plot.detector = self.base.data.detector 193 179 # # If the data file does not tell us what the axes are, just assume... 194 180 new_plot.xaxis("\\rm{Q}", "A^{-1}") 195 181 new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}") 196 182 197 data = self.base.data 2D183 data = self.base.data 198 184 if hasattr(data, "scale") and data.scale == 'linear' and \ 199 self.base.data 2D.name.count("Residuals") > 0:185 self.base.data.name.count("Residuals") > 0: 200 186 new_plot.ytransform = 'y' 201 187 new_plot.yaxis("\\rm{Residuals} ", "/") 202 188 203 new_plot.group_id = "2daverage" + self.base.data 2D.name204 new_plot.id = (self.averager.__name__) + self.base.data 2D.name189 new_plot.group_id = "2daverage" + self.base.data.name 190 new_plot.id = (self.averager.__name__) + self.base.data.name 205 191 new_plot.is_data = True 206 self.base.parent.update_theory(data_id=self.base.data2D.id, \ 207 theory=new_plot) 208 wx.PostEvent(self.base.parent, 209 NewPlotEvent(plot=new_plot, title=str(self.averager.__name__))) 192 variant_plot = QtCore.QVariant(new_plot) 193 GuiUtils.updateModelItemWithPlot(self._item, variant_plot, new_plot.id) 194 195 if self.update_model: 196 self.setModelFromParams() 197 self.draw() 210 198 211 199 def moveend(self, ev): … … 215 203 corresponding to the new average 216 204 """ 217 self.base.thaw_axes()218 # Post paramters219 event = SlicerParameterEvent()220 event.type = self.__class__.__name__221 event.params = self.get_params()222 wx.PostEvent(self.base.parent, event)223 # create the new data1D224 205 self._post_data() 225 206 … … 240 221 pass 241 222 242 def get _params(self):223 def getParams(self): 243 224 """ 244 225 Store a copy of values of parameters of the slicer into a dictionary. … … 248 229 """ 249 230 params = {} 250 params["x_max"] = math.fabs(self.vertical_lines.x)251 params["y_max"] = math.fabs(self.horizontal_lines.y)231 params["x_max"] = numpy.fabs(self.vertical_lines.x) 232 params["y_max"] = numpy.fabs(self.horizontal_lines.y) 252 233 params["nbins"] = self.nbins 253 234 return params 254 235 255 def set _params(self, params):236 def setParams(self, params): 256 237 """ 257 238 Receive a dictionary and reset the slicer with values contained … … 261 242 values the user assigned to the slicer. 262 243 """ 263 self.x = float( math.fabs(params["x_max"]))264 self.y = float( math.fabs(params["y_max"]))244 self.x = float(numpy.fabs(params["x_max"])) 245 self.y = float(numpy.fabs(params["y_max"])) 265 246 self.nbins = params["nbins"] 266 247 … … 269 250 self.post_data(nbins=None) 270 251 271 def freeze_axes(self):272 """273 """274 self.base.freeze_axes()275 276 def thaw_axes(self):277 """278 """279 self.base.thaw_axes()280 281 252 def draw(self): 282 253 """ … … 294 265 """ 295 266 _BaseInteractor.__init__(self, base, axes, color=color) 296 # #Class initialization267 # Class initialization 297 268 self.markers = [] 298 269 self.axes = axes 299 # #Saving the end points of two lines270 # Saving the end points of two lines 300 271 self.x = x 301 272 self.save_x = x … … 303 274 self.y = y 304 275 self.save_y = y 305 # #Creating a marker276 # Creating a marker 306 277 # Inner circle marker 307 278 self.inner_marker = self.axes.plot([0], [self.y], linestyle='', … … 311 282 zorder=zorder, 312 283 visible=True)[0] 313 # #Define 2 horizontal lines284 # Define 2 horizontal lines 314 285 self.top_line = self.axes.plot([self.x, -self.x], [self.y, self.y], 315 286 linestyle='-', marker='', … … 318 289 linestyle='-', marker='', 319 290 color=self.color, visible=True)[0] 320 # #Flag to check the motion of the lines291 # Flag to check the motion of the lines 321 292 self.has_move = False 322 # #Connecting markers to mouse events and draw293 # Connecting markers to mouse events and draw 323 294 self.connect_markers([self.top_line, self.inner_marker]) 324 295 self.update() … … 339 310 """ 340 311 self.clear_markers() 341 try: 342 self.inner_marker.remove() 343 self.top_line.remove() 344 self.bottom_line.remove() 345 except: 346 # Old version of matplotlib 347 for item in range(len(self.axes.lines)): 348 del self.axes.lines[0] 312 self.inner_marker.remove() 313 self.top_line.remove() 314 self.bottom_line.remove() 349 315 350 316 def update(self, x=None, y=None): … … 356 322 357 323 """ 358 # #Reset x, y- coordinates if send as parameters324 # Reset x, y- coordinates if send as parameters 359 325 if x is not None: 360 self.x = n p.sign(self.x) * math.fabs(x)326 self.x = numpy.sign(self.x) * numpy.fabs(x) 361 327 if y is not None: 362 self.y = n p.sign(self.y) * math.fabs(y)363 # #Draw lines and markers328 self.y = numpy.sign(self.y) * numpy.fabs(y) 329 # Draw lines and markers 364 330 self.inner_marker.set(xdata=[0], ydata=[self.y]) 365 331 self.top_line.set(xdata=[self.x, -self.x], ydata=[self.y, self.y]) … … 373 339 self.save_x = self.x 374 340 self.save_y = self.y 375 self.base.freeze_axes()376 341 377 342 def moveend(self, ev): … … 409 374 self.markers = [] 410 375 self.axes = axes 411 self.x = math.fabs(x)376 self.x = numpy.fabs(x) 412 377 self.save_x = self.x 413 self.y = math.fabs(y)378 self.y = numpy.fabs(y) 414 379 self.save_y = y 415 380 # Inner circle marker … … 446 411 """ 447 412 self.clear_markers() 448 try: 449 self.inner_marker.remove() 450 self.left_line.remove() 451 self.right_line.remove() 452 except: 453 # Old version of matplotlib 454 for item in range(len(self.axes.lines)): 455 del self.axes.lines[0] 413 self.inner_marker.remove() 414 self.left_line.remove() 415 self.right_line.remove() 456 416 457 417 def update(self, x=None, y=None): … … 463 423 464 424 """ 465 # # reset x, y -coordinates if given as parameters425 # Reset x, y -coordinates if given as parameters 466 426 if x is not None: 467 self.x = n p.sign(self.x) * math.fabs(x)427 self.x = numpy.sign(self.x) * numpy.fabs(x) 468 428 if y is not None: 469 self.y = n p.sign(self.y) * math.fabs(y)470 # # draw lines and markers429 self.y = numpy.sign(self.y) * numpy.fabs(y) 430 # Draw lines and markers 471 431 self.inner_marker.set(xdata=[self.x], ydata=[0]) 472 432 self.left_line.set(xdata=[-self.x, -self.x], ydata=[self.y, -self.y]) … … 480 440 self.save_x = self.x 481 441 self.save_y = self.y 482 self.base.freeze_axes()483 442 484 443 def moveend(self, ev): … … 510 469 Average in Qx direction 511 470 """ 512 def __init__(self, base, axes, color='black', zorder=3):513 BoxInteractor.__init__(self, base, axes, color=color)471 def __init__(self, base, axes, item=None, color='black', zorder=3): 472 BoxInteractor.__init__(self, base, axes, item=item, color=color) 514 473 self.base = base 515 474 self._post_data() … … 527 486 Average in Qy direction 528 487 """ 529 def __init__(self, base, axes, color='black', zorder=3):530 BoxInteractor.__init__(self, base, axes, color=color)488 def __init__(self, base, axes, item=None, color='black', zorder=3): 489 BoxInteractor.__init__(self, base, axes, item=item, color=color) 531 490 self.base = base 532 491 self._post_data() -
src/sas/sasgui/guiframe/local_perspectives/plotting/boxSum.py
r7432acb rc416a17 1 1 """ 2 Boxsum Class: determine 2 rectangular area to compute 3 the sum of pixel of a Data. 4 """ 5 import numpy 6 from PyQt4 import QtGui 7 from PyQt4 import QtCore 8 from sas.qtgui.Utilities.GuiUtils import formatNumber 9 10 from BaseInteractor import _BaseInteractor 11 from sas.sascalc.dataloader.manipulations import Boxavg 12 from sas.sascalc.dataloader.manipulations import Boxsum 13 14 from sas.qtgui.Plotting.SlicerModel import SlicerModel 15 16 17 class BoxSumCalculator(_BaseInteractor): 18 """ 2 19 Boxsum Class: determine 2 rectangular area to compute 3 20 the sum of pixel of a Data. 4 """ 5 import math 6 import wx 7 from BaseInteractor import _BaseInteractor 8 from sas.sasgui.guiframe.events import SlicerParamUpdateEvent 9 from sas.sasgui.guiframe.events import EVT_SLICER_PARS 10 from sas.sasgui.guiframe.events import StatusEvent 11 12 13 class BoxSum(_BaseInteractor): 21 Uses PointerInteractor , VerticalDoubleLine,HorizontalDoubleLine. 22 @param zorder: Artists with lower zorder values are drawn first. 23 @param x_min: the minimum value of the x coordinate 24 @param x_max: the maximum value of the x coordinate 25 @param y_min: the minimum value of the y coordinate 26 @param y_max: the maximum value of the y coordinate 27 14 28 """ 15 Boxsum Class: determine 2 rectangular area to compute 16 the sum of pixel of a Data. 17 Uses PointerInteractor , VerticalDoubleLine,HorizontalDoubleLine. 18 @param zorder: Artists with lower zorder values are drawn first. 19 @param x_min: the minimum value of the x coordinate 20 @param x_max: the maximum value of the x coordinate 21 @param y_min: the minimum value of the y coordinate 22 @param y_max: the maximum value of the y coordinate 23 24 """ 25 def __init__(self, base, axes, color='black', zorder=3, x_min=0.008, 26 x_max=0.008, y_min=0.0025, y_max=0.0025): 27 """ 28 """ 29 def __init__(self, base, axes, color='black', zorder=3): 29 30 _BaseInteractor.__init__(self, base, axes, color=color) 30 # # class initialization 31 # #list of Boxsmun markers31 32 # list of Boxsmun markers 32 33 self.markers = [] 33 34 self.axes = axes 34 # # connect the artist for the motion 35 self._model = None 36 self.update_model = False 37 38 # connect the artist for the motion 35 39 self.connect = self.base.connect 36 # # when qmax is reached the selected line is reset the its previous value 37 self.qmax = min(self.base.data2D.xmax, self.base.data2D.xmin) 38 # # Define the boxsum limits 39 self.xmin = -1 * 0.5 * min(math.fabs(self.base.data2D.xmax), 40 math.fabs(self.base.data2D.xmin)) 41 self.ymin = -1 * 0.5 * min(math.fabs(self.base.data2D.xmax), 42 math.fabs(self.base.data2D.xmin)) 43 self.xmax = 0.5 * min(math.fabs(self.base.data2D.xmax), 44 math.fabs(self.base.data2D.xmin)) 45 self.ymax = 0.5 * min(math.fabs(self.base.data2D.xmax), 46 math.fabs(self.base.data2D.xmin)) 47 # # center of the boxSum 40 41 # when qmax is reached the selected line is reset the its previous value 42 self.qmax = min(self.base.data.xmax, self.base.data.xmin) 43 44 # Define the boxsum limits 45 self.xmin = -1 * 0.5 * min(numpy.fabs(self.base.data.xmax), 46 numpy.fabs(self.base.data.xmin)) 47 self.ymin = -1 * 0.5 * min(numpy.fabs(self.base.data.xmax), 48 numpy.fabs(self.base.data.xmin)) 49 self.xmax = 0.5 * min(numpy.fabs(self.base.data.xmax), 50 numpy.fabs(self.base.data.xmin)) 51 self.ymax = 0.5 * min(numpy.fabs(self.base.data.xmax), 52 numpy.fabs(self.base.data.xmin)) 53 # center of the boxSum 48 54 self.center_x = 0.0002 49 55 self.center_y = 0.0003 50 # #Number of points on the plot56 # Number of points on the plot 51 57 self.nbins = 20 52 # #Define initial result the summation58 # Define initial result the summation 53 59 self.count = 0 54 60 self.error = 0 … … 56 62 self.totalerror = 0 57 63 self.points = 0 58 # #Flag to determine if the current figure has moved59 # #set to False == no motion , set to True== motion64 # Flag to determine if the current figure has moved 65 # set to False == no motion , set to True== motion 60 66 self.has_move = False 61 # #Create Boxsum edges67 # Create Boxsum edges 62 68 self.horizontal_lines = HorizontalDoubleLine(self, 63 self. base.subplot,69 self.axes, 64 70 color='blue', 65 71 zorder=zorder, … … 71 77 72 78 self.vertical_lines = VerticalDoubleLine(self, 73 self. base.subplot,79 self.axes, 74 80 color='black', 75 81 zorder=zorder, … … 81 87 82 88 self.center = PointInteractor(self, 83 self. base.subplot, color='grey',89 self.axes, color='grey', 84 90 zorder=zorder, 85 91 center_x=self.center_x, 86 92 center_y=self.center_y) 87 # #Save the name of the slicer panel associate with this slicer93 # Save the name of the slicer panel associate with this slicer 88 94 self.panel_name = "" 89 # # Update and post slicer parameters 90 self.update() 91 self._post_data() 92 # # Bind to slice parameter events 93 self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS) 94 95 def set_panel_name(self, name): 96 """ 97 Store the name of the panel associated to this slicer 98 @param name: the name of this panel 95 # Update and post slicer parameters 96 self.update_model = False 97 self.update() 98 self.postData() 99 100 # set up the model 101 self._model = QtGui.QStandardItemModel(1, 9) 102 self.setModelFromParams() 103 self.update_model = True 104 self._model.itemChanged.connect(self.setParamsFromModel) 105 106 def setModelFromParams(self): 107 """ 108 Set up the Qt model for data handling between controls 109 """ 110 parameters = self.getParams() 111 # Crete/overwrite model items 112 self._model.setData(self._model.index(0, 0), 113 QtCore.QVariant(formatNumber(parameters['Height']))) 114 self._model.setData(self._model.index(0, 1), 115 QtCore.QVariant(formatNumber(parameters['Width']))) 116 self._model.setData(self._model.index(0, 2), 117 QtCore.QVariant(formatNumber(parameters['center_x']))) 118 self._model.setData(self._model.index(0, 3), 119 QtCore.QVariant(formatNumber(parameters['center_y']))) 120 121 self.setReadOnlyParametersFromModel() 122 123 def model(self): 124 ''' model accessor ''' 125 return self._model 126 127 def setReadOnlyParametersFromModel(self): 128 """ 129 Cast model content onto "read-only" subset of parameters 130 """ 131 parameters = self.getParams() 132 self._model.setData(self._model.index(0, 4), 133 QtCore.QVariant(formatNumber(parameters['avg']))) 134 self._model.setData(self._model.index(0, 5), 135 QtCore.QVariant(formatNumber(parameters['avg_error']))) 136 self._model.setData(self._model.index(0, 6), 137 QtCore.QVariant(formatNumber(parameters['sum']))) 138 self._model.setData(self._model.index(0, 7), 139 QtCore.QVariant(formatNumber(parameters['sum_error']))) 140 self._model.setData(self._model.index(0, 8), 141 QtCore.QVariant(formatNumber(parameters['num_points']))) 142 143 def setParamsFromModel(self): 144 """ 145 Cast model content onto params dict 146 """ 147 params = {} 148 params["Height"] = float(self.model().item(0, 0).text()) 149 params["Width"] = float(self.model().item(0, 1).text()) 150 params["center_x"] = float(self.model().item(0, 2).text()) 151 params["center_y"] = float(self.model().item(0, 3).text()) 152 self.update_model = False 153 self.setParams(params) 154 self.setReadOnlyParametersFromModel() 155 self.update_model = True 156 157 def setPanelName(self, name): 158 """ 159 Store the name of the panel associated to this slicer 160 @param name: the name of this panel 99 161 """ 100 162 self.panel_name = name 101 163 102 def _onEVT_SLICER_PARS(self, event): 103 """ 104 receive an event containing parameters values to reset the slicer 105 @param event: event of type SlicerParameterEvent with params as 106 attribute 107 """ 108 # # Post e message to declare what kind of event has being received 109 wx.PostEvent(self.base.parent, 110 StatusEvent(status="Boxsum._onEVT_SLICER_PARS")) 111 event.Skip() 112 # # reset the slicer with the values contains the event.params dictionary 113 if event.type == self.__class__.__name__: 114 self.set_params(event.params) 115 self.base.update() 116 117 def set_layer(self, n): 164 def setLayer(self, n): 118 165 """ 119 166 Allow adding plot to the same panel … … 132 179 self.center.clear() 133 180 self.base.connect.clearall() 134 self.base.Unbind(EVT_SLICER_PARS)135 181 136 182 def update(self): … … 139 185 resetting the widgets. 140 186 """ 141 # #check if the center point has moved and update the figure accordingly187 # check if the center point has moved and update the figure accordingly 142 188 if self.center.has_move: 143 189 self.center.update() 144 190 self.horizontal_lines.update(center=self.center) 145 191 self.vertical_lines.update(center=self.center) 146 # #check if the horizontal lines have moved and192 # check if the horizontal lines have moved and 147 193 # update the figure accordingly 148 194 if self.horizontal_lines.has_move: … … 151 197 y2=self.horizontal_lines.y2, 152 198 height=self.horizontal_lines.half_height) 153 # #check if the vertical lines have moved and199 # check if the vertical lines have moved and 154 200 # update the figure accordingly 155 201 if self.vertical_lines.has_move: … … 164 210 can restore on Esc. 165 211 """ 166 self.base.freeze_axes()167 212 self.horizontal_lines.save(ev) 168 213 self.vertical_lines.save(ev) 169 214 self.center.save(ev) 170 215 171 def _post_data(self):216 def postData(self): 172 217 """ 173 218 Get the limits of the boxsum and compute the sum of the pixel 174 219 contained in that region and the error on that sum 175 220 """ 176 # #the region of the summation221 # the region of the summation 177 222 x_min = self.horizontal_lines.x2 178 223 x_max = self.horizontal_lines.x1 179 224 y_min = self.vertical_lines.y2 180 225 y_max = self.vertical_lines.y1 181 # #computation of the sum and its error 182 from sas.sascalc.dataloader.manipulations import Boxavg 226 #computation of the sum and its error 183 227 box = Boxavg(x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max) 184 self.count, self.error = box(self.base.data 2D)228 self.count, self.error = box(self.base.data) 185 229 # Dig out number of points summed, SMK & PDB, 04/03/2013 186 from sas.sascalc.dataloader.manipulations import Boxsum187 230 boxtotal = Boxsum(x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max) 188 self.total, self.totalerror, self.points = boxtotal(self.base.data2D) 231 self.total, self.totalerror, self.points = boxtotal(self.base.data) 232 if self.update_model: 233 self.setModelFromParams() 234 self.draw() 189 235 190 236 def moveend(self, ev): 191 237 """ 192 After a dragging motion this function is called to compute 193 the error and the sum of pixel of a given data 2D 194 """ 195 self.base.thaw_axes() 196 # # compute error an d sum of data's pixel 197 self._post_data() 198 # # Create and event ( posted to guiframe)that set the 199 # #current slicer parameter to a panel of name self.panel_name 200 self.type = self.__class__.__name__ 201 params = self.get_params() 202 event = SlicerParamUpdateEvent(type=self.type, 203 params=params, 204 panel_name=self.panel_name) 205 wx.PostEvent(self.base.parent, event) 238 After a dragging motion this function is called to compute 239 the error and the sum of pixel of a given data 2D 240 """ 241 # compute error an d sum of data's pixel 242 self.postData() 206 243 207 244 def restore(self): … … 213 250 self.center.restore() 214 251 215 def move(self, x, y, ev): 216 """ 217 Process move to a new position, making sure that the move is allowed. 218 """ 219 pass 220 221 def set_cursor(self, x, y): 222 """ 223 """ 224 pass 225 226 def get_params(self): 252 def getParams(self): 227 253 """ 228 254 Store a copy of values of parameters of the slicer into a dictionary. … … 230 256 """ 231 257 params = {} 232 params["Width"] = math.fabs(self.vertical_lines.half_width) * 2233 params["Height"] = math.fabs(self.horizontal_lines.half_height) * 2258 params["Width"] = numpy.fabs(self.vertical_lines.half_width) * 2 259 params["Height"] = numpy.fabs(self.horizontal_lines.half_height) * 2 234 260 params["center_x"] = self.center.x 235 261 params["center_y"] = self.center.y … … 241 267 return params 242 268 243 def get _result(self):244 """ 245 return the result of box summation269 def getResult(self): 270 """ 271 Return the result of box summation 246 272 """ 247 273 result = {} … … 253 279 return result 254 280 255 def set _params(self, params):281 def setParams(self, params): 256 282 """ 257 283 Receive a dictionary and reset the slicer with values contained 258 284 in the values of the dictionary. 259 :param params: a dictionary containing name of slicer parameters and values the user assigned to the slicer. 260 """ 261 x_max = math.fabs(params["Width"]) / 2 262 y_max = math.fabs(params["Height"]) / 2 285 :param params: a dictionary containing name of slicer parameters 286 and values the user assigned to the slicer. 287 """ 288 x_max = numpy.fabs(params["Width"]) / 2 289 y_max = numpy.fabs(params["Height"]) / 2 263 290 264 291 self.center_x = params["center_x"] … … 271 298 width=x_max, height=y_max) 272 299 # compute the new error and sum given values of params 273 self._post_data() 274 275 def freeze_axes(self): 276 """ 277 """ 278 self.base.freeze_axes() 279 280 def thaw_axes(self): 281 """ 282 """ 283 self.base.thaw_axes() 300 self.postData() 284 301 285 302 def draw(self): 286 """ 287 """ 303 """ Redraw canvas""" 288 304 self.base.draw() 289 305 … … 297 313 def __init__(self, base, axes, color='black', zorder=5, center_x=0.0, 298 314 center_y=0.0): 299 """300 """301 315 _BaseInteractor.__init__(self, base, axes, color=color) 302 # #Initialization the class316 # Initialization the class 303 317 self.markers = [] 304 318 self.axes = axes … … 306 320 self.x = center_x 307 321 self.y = center_y 308 # #saved value of the center coordinates322 # saved value of the center coordinates 309 323 self.save_x = center_x 310 324 self.save_y = center_y 311 # #Create a marker325 # Create a marker 312 326 self.center_marker = self.axes.plot([self.x], [self.y], linestyle='', 313 327 marker='s', markersize=10, … … 316 330 zorder=zorder, 317 331 visible=True)[0] 318 # #Draw a point332 # Draw a point 319 333 self.center = self.axes.plot([self.x], [self.y], 320 334 linestyle='-', marker='', 321 335 color=self.color, 322 336 visible=True)[0] 323 # #Flag to determine the motion this point337 # Flag to determine the motion this point 324 338 self.has_move = False 325 # #connecting the marker to allow them to move339 # connecting the marker to allow them to move 326 340 self.connect_markers([self.center_marker]) 327 # #Update the figure328 self.update() 329 330 def set _layer(self, n):331 """ 332 333 341 # Update the figure 342 self.update() 343 344 def setLayer(self, n): 345 """ 346 Allow adding plot to the same panel 347 @param n: the number of layer 334 348 """ 335 349 self.layernum = n … … 338 352 def clear(self): 339 353 """ 340 354 Clear this figure and its markers 341 355 """ 342 356 self.clear_markers() 343 try: 344 self.center.remove() 345 self.center_marker.remove() 346 except: 347 # Old version of matplotlib 348 for item in range(len(self.axes.lines)): 349 del self.axes.lines[0] 357 self.center.remove() 358 self.center_marker.remove() 350 359 351 360 def update(self, center_x=None, center_y=None): 352 361 """ 353 362 Draw the new roughness on the graph. 354 363 """ 355 364 if center_x is not None: … … 367 376 self.save_x = self.x 368 377 self.save_y = self.y 369 self.base.freeze_axes()370 378 371 379 def moveend(self, ev): … … 391 399 self.base.base.update() 392 400 393 def set _cursor(self, x, y):401 def setCursor(self, x, y): 394 402 """ 395 403 """ … … 399 407 class VerticalDoubleLine(_BaseInteractor): 400 408 """ 401 402 409 Draw 2 vertical lines moving in opposite direction and centered on 410 a point (PointInteractor) 403 411 """ 404 412 def __init__(self, base, axes, color='black', zorder=5, x=0.5, y=0.5, 405 413 center_x=0.0, center_y=0.0): 406 """407 """408 414 _BaseInteractor.__init__(self, base, axes, color=color) 409 # #Initialization the class415 # Initialization the class 410 416 self.markers = [] 411 417 self.axes = axes 412 # #Center coordinates418 # Center coordinates 413 419 self.center_x = center_x 414 420 self.center_y = center_y 415 # #defined end points vertical lignes and their saved values421 # defined end points vertical lignes and their saved values 416 422 self.y1 = y + self.center_y 417 423 self.save_y1 = self.y1 … … 429 435 # # save the color of the line 430 436 self.color = color 431 # #the height of the rectangle432 self.half_height = math.fabs(y)433 self.save_half_height = math.fabs(y)434 # #the with of the rectangle435 self.half_width = math.fabs(self.x1 - self.x2) / 2436 self.save_half_width = math.fabs(self.x1 - self.x2) / 2437 # #Create marker437 # the height of the rectangle 438 self.half_height = numpy.fabs(y) 439 self.save_half_height = numpy.fabs(y) 440 # the with of the rectangle 441 self.half_width = numpy.fabs(self.x1 - self.x2) / 2 442 self.save_half_width = numpy.fabs(self.x1 - self.x2) / 2 443 # Create marker 438 444 self.right_marker = self.axes.plot([self.x1], [0], linestyle='', 439 445 marker='s', markersize=10, … … 442 448 zorder=zorder, visible=True)[0] 443 449 444 # # define the left and right lines of the rectangle450 # Define the left and right lines of the rectangle 445 451 self.right_line = self.axes.plot([self.x1, self.x1], [self.y1, self.y2], 446 452 linestyle='-', marker='', … … 449 455 linestyle='-', marker='', 450 456 color=self.color, visible=True)[0] 451 # #Flag to determine if the lines have moved457 # Flag to determine if the lines have moved 452 458 self.has_move = False 453 # # connection the marker and draw the pictures459 # Connection the marker and draw the pictures 454 460 self.connect_markers([self.right_marker]) 455 461 self.update() 456 462 457 def set _layer(self, n):463 def setLayer(self, n): 458 464 """ 459 465 Allow adding plot to the same panel … … 468 474 """ 469 475 self.clear_markers() 470 try: 471 self.right_marker.remove() 472 self.right_line.remove() 473 self.left_line.remove() 474 except: 475 # Old version of matplotlib 476 for item in range(len(self.axes.lines)): 477 del self.axes.lines[0] 476 self.right_marker.remove() 477 self.right_line.remove() 478 self.left_line.remove() 478 479 479 480 def update(self, x1=None, x2=None, y1=None, y2=None, width=None, … … 489 490 :param center: provided x, y coordinates of the center point 490 491 """ 491 # # save the new height, witdh of the rectangle if given as a param492 # Save the new height, witdh of the rectangle if given as a param 492 493 if width is not None: 493 494 self.half_width = width 494 495 if height is not None: 495 496 self.half_height = height 496 # #If new center coordinates are given draw the rectangle497 # #given these value497 # If new center coordinates are given draw the rectangle 498 # given these value 498 499 if center is not None: 499 500 self.center_x = center.x … … 510 511 ydata=[self.y1, self.y2]) 511 512 return 512 # #if x1, y1, y2, y3 are given draw the rectangle with this value513 # if x1, y1, y2, y3 are given draw the rectangle with this value 513 514 if x1 is not None: 514 515 self.x1 = x1 … … 519 520 if y2 is not None: 520 521 self.y2 = y2 521 # #Draw 2 vertical lines and a marker522 # Draw 2 vertical lines and a marker 522 523 self.right_marker.set(xdata=[self.x1], ydata=[self.center_y]) 523 524 self.right_line.set(xdata=[self.x1, self.x1], ydata=[self.y1, self.y2]) … … 535 536 self.save_half_height = self.half_height 536 537 self.save_half_width = self.half_width 537 self.base.freeze_axes()538 538 539 539 def moveend(self, ev): 540 540 """ 541 541 After a dragging motion reset the flag self.has_move to False 542 542 """ 543 543 self.has_move = False … … 562 562 delta = self.x1 - self.center_x 563 563 self.x2 = self.center_x - delta 564 self.half_width = math.fabs(self.x1 - self.x2) / 2564 self.half_width = numpy.fabs(self.x1 - self.x2) / 2 565 565 self.has_move = True 566 566 self.base.base.update() 567 567 568 def set _cursor(self, x, y):569 """ 570 568 def setCursor(self, x, y): 569 """ 570 Update the figure given x and y 571 571 """ 572 572 self.move(x, y, None) … … 575 575 class HorizontalDoubleLine(_BaseInteractor): 576 576 """ 577 577 Select an annulus through a 2D plot 578 578 """ 579 579 def __init__(self, base, axes, color='black', zorder=5, x=0.5, y=0.5, … … 581 581 582 582 _BaseInteractor.__init__(self, base, axes, color=color) 583 # #Initialization the class583 # Initialization the class 584 584 self.markers = [] 585 585 self.axes = axes 586 # #Center coordinates586 # Center coordinates 587 587 self.center_x = center_x 588 588 self.center_y = center_y … … 598 598 self.save_x2 = self.x2 599 599 self.color = color 600 self.half_height = math.fabs(y)601 self.save_half_height = math.fabs(y)602 self.half_width = math.fabs(x)603 self.save_half_width = math.fabs(x)600 self.half_height = numpy.fabs(y) 601 self.save_half_height = numpy.fabs(y) 602 self.half_width = numpy.fabs(x) 603 self.save_half_width = numpy.fabs(x) 604 604 self.top_marker = self.axes.plot([0], [self.y1], linestyle='', 605 605 marker='s', markersize=10, … … 616 616 linestyle='-', marker='', 617 617 color=self.color, visible=True)[0] 618 # #Flag to determine if the lines have moved618 # Flag to determine if the lines have moved 619 619 self.has_move = False 620 # #connection the marker and draw the pictures620 # connection the marker and draw the pictures 621 621 self.connect_markers([self.top_marker]) 622 622 self.update() 623 623 624 def set _layer(self, n):625 """ 626 627 624 def setLayer(self, n): 625 """ 626 Allow adding plot to the same panel 627 @param n: the number of layer 628 628 """ 629 629 self.layernum = n … … 632 632 def clear(self): 633 633 """ 634 634 Clear this figure and its markers 635 635 """ 636 636 self.clear_markers() 637 try: 638 self.top_marker.remove() 639 self.bottom_line.remove() 640 self.top_line.remove() 641 except: 642 # Old version of matplotlib 643 for item in range(len(self.axes.lines)): 644 del self.axes.lines[0] 637 self.top_marker.remove() 638 self.bottom_line.remove() 639 self.top_line.remove() 645 640 646 641 def update(self, x1=None, x2=None, y1=None, y2=None, … … 656 651 :param center: provided x, y coordinates of the center point 657 652 """ 658 # # save the new height, witdh of the rectangle if given as a param653 # Save the new height, witdh of the rectangle if given as a param 659 654 if width is not None: 660 655 self.half_width = width 661 656 if height is not None: 662 657 self.half_height = height 663 # #If new center coordinates are given draw the rectangle664 # #given these value658 # If new center coordinates are given draw the rectangle 659 # given these value 665 660 if center is not None: 666 661 self.center_x = center.x … … 678 673 ydata=[self.y2, self.y2]) 679 674 return 680 # #if x1, y1, y2, y3 are given draw the rectangle with this value675 # if x1, y1, y2, y3 are given draw the rectangle with this value 681 676 if x1 is not None: 682 677 self.x1 = x1 … … 687 682 if y2 is not None: 688 683 self.y2 = y2 689 # #Draw 2 vertical lines and a marker684 # Draw 2 vertical lines and a marker 690 685 self.top_marker.set(xdata=[self.center_x], ydata=[self.y1]) 691 686 self.top_line.set(xdata=[self.x1, self.x2], ydata=[self.y1, self.y1]) … … 703 698 self.save_half_height = self.half_height 704 699 self.save_half_width = self.half_width 705 self.base.freeze_axes()706 700 707 701 def moveend(self, ev): … … 730 724 delta = self.y1 - self.center_y 731 725 self.y2 = self.center_y - delta 732 self.half_height = math.fabs(self.y1) - self.center_y726 self.half_height = numpy.fabs(self.y1) - self.center_y 733 727 self.has_move = True 734 728 self.base.base.update() 735 729 736 def set _cursor(self, x, y):737 """ 738 730 def setCursor(self, x, y): 731 """ 732 Update the figure given x and y 739 733 """ 740 734 self.move(x, y, None)
Note: See TracChangeset
for help on using the changeset viewer.