Changeset 3bdbfcc in sasview for src/sas


Ignore:
Timestamp:
Feb 2, 2017 8:29:07 AM (8 years ago)
Author:
Piotr Rozyczko <rozyczko@…>
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:
965fbd8
Parents:
5d89f43
git-author:
Piotr Rozyczko <rozyczko@…> (01/23/17 09:21:03)
git-committer:
Piotr Rozyczko <rozyczko@…> (02/02/17 08:29:07)
Message:

Reimplementation of the slicer functionality

Location:
src/sas
Files:
7 added
14 edited

Legend:

Unmodified
Added
Removed
  • src/sas/qtgui/ColorMap.py

    r5d89f43 r3bdbfcc  
    111111        self.canvas.draw() 
    112112 
    113     def onApply(self): 
    114         """ 
    115         Respond to the Apply button click. 
    116         Send a signal to the plotter with vmin/vmax/cmap for chart update 
    117         """ 
    118         self.apply_signal.emit(self.norm(), self.cmap()) 
    119  
    120113    def initDetectorData(self): 
    121114        """ 
     
    214207                                            norm=self._norm, 
    215208                                            orientation='horizontal') 
    216         self.cb.set_label('Color map range') 
     209        self.cb.set_label('Detector Colors') 
    217210 
    218211    def onColorMapReversed(self, isChecked): 
  • src/sas/qtgui/DataExplorer.py

    r87cc73a r3bdbfcc  
    399399        new_plot = Plotter(self) 
    400400 
    401         def addDataPlot2D(plot_set): 
     401        def addDataPlot2D(plot_set, item): 
    402402            plot2D = Plotter2D(self) 
     403            plot2D.item = item 
    403404            plot2D.plot(plot_set) 
    404405            self.plotAdd(plot2D) 
    405406 
    406         for plot_set in plots: 
     407        for item, plot_set in plots: 
    407408            if isinstance(plot_set, Data1D): 
    408409                new_plot.plot(plot_set) 
    409410            elif isinstance(plot_set, Data2D): 
    410                 addDataPlot2D(plot_set) 
     411                addDataPlot2D(plot_set, item) 
    411412            else: 
    412413                msg = "Incorrect data type passed to Plotting" 
     
    450451 
    451452        # Add new data to the old plot, if data type is the same. 
    452         for plot_set in new_plots: 
     453        for _, plot_set in new_plots: 
    453454            if type(plot_set) is type(old_plot._data): 
    454455                old_plot.data = plot_set 
  • src/sas/qtgui/GUITests.py

    r092a3d9 r3bdbfcc  
    2424from UnitTesting import PlotUtilitiesTest 
    2525from UnitTesting import ColorMapTest 
     26from UnitTesting import BoxSumTest 
     27from UnitTesting import SlicerModelTest 
    2628 
    2729def suite(): 
     
    5052        unittest.makeSuite(PlotUtilitiesTest.PlotUtilitiesTest, 'test'), 
    5153        unittest.makeSuite(ColorMapTest.ColorMapTest, 'test'), 
     54        unittest.makeSuite(BoxSumTest.BoxSumTest, 'test'), 
     55        unittest.makeSuite(SlicerModelTest.SlicerModelTest, 'test'), 
    5256    ) 
    5357    return unittest.TestSuite(suites) 
  • src/sas/qtgui/GuiUtils.py

    ra66ff280 r3bdbfcc  
    242242    assert isinstance(item, QtGui.QStandardItem) 
    243243    assert isinstance(update_data, QtCore.QVariant) 
     244    py_update_data = update_data.toPyObject() 
     245 
     246    # Check if data with the same ID is already present 
     247    for index in range(item.rowCount()): 
     248        plot_item = item.child(index) 
     249        if plot_item.isCheckable(): 
     250            plot_data = plot_item.child(0).data().toPyObject() 
     251            if plot_data.id == py_update_data.id: 
     252                item.removeRow(index) 
     253                break 
    244254 
    245255    checkbox_item = QtGui.QStandardItem(True) 
     
    249259 
    250260    # Add "Info" item 
    251     py_update_data = update_data.toPyObject() 
    252261    if isinstance(py_update_data, (Data1D or Data2D)): 
    253262        # If Data1/2D added - extract Info from it 
     
    298307        if item.isCheckable() and item.checkState() == QtCore.Qt.Checked: 
    299308            # TODO: assure item type is correct (either data1/2D or Plotter) 
    300             plot_data.append(item.child(0).data().toPyObject()) 
     309            plot_data.append((item, item.child(0).data().toPyObject())) 
    301310        # Going 1 level deeper only 
    302311        for index_2 in range(item.rowCount()): 
     
    304313            if item_2 and item_2.isCheckable() and item_2.checkState() == QtCore.Qt.Checked: 
    305314                # TODO: assure item type is correct (either data1/2D or Plotter) 
    306                 plot_data.append(item_2.child(0).data().toPyObject()) 
     315                plot_data.append((item_2, item_2.child(0).data().toPyObject())) 
    307316 
    308317    return plot_data 
  • src/sas/qtgui/Plotter.py

    r092a3d9 r3bdbfcc  
    516516        self.plot(data=self.fit_result, marker='-', hide_error=True) 
    517517 
     518    def onMplMouseDown(self, event): 
     519        """ 
     520        Left button down and ready to drag 
     521        """ 
     522        # Check that the LEFT button was pressed 
     523        if event.button == 1: 
     524            self.leftdown = True 
     525            ax = event.inaxes 
     526            for text in self.textList: 
     527                if text.contains(event)[0]: # If user has clicked on text 
     528                    self.selectedText = text 
     529                    return 
     530 
     531            if ax != None: 
     532                self.xInit, self.yInit = event.xdata, event.ydata 
     533                try: 
     534                    self.x_click = float(event.xdata)  # / size_x 
     535                    self.y_click = float(event.ydata)  # / size_y 
     536                except: 
     537                    self.position = None 
     538 
     539    def onMplMouseUp(self, event): 
     540        """ 
     541        Set the data coordinates of the click 
     542        """ 
     543        self.x_click = event.xdata 
     544        self.y_click = event.ydata 
     545 
     546        # Check that the LEFT button was released 
     547        if event.button == 1: 
     548            self.leftdown = False 
     549            #self.leftup = True 
     550            self.selectedText = None 
     551 
     552        #release the legend 
     553        if self.gotLegend == 1: 
     554            self.gotLegend = 0 
     555 
     556    def onMplMouseMotion(self, event): 
     557        """ 
     558        Check if the left button is press and the mouse in moving. 
     559        Compute delta for x and y coordinates and then perform the drag 
     560        """ 
     561        if self.gotLegend == 1 and self.leftdown: 
     562            self.onLegendMotion(event) 
     563            return 
     564 
     565        if self.leftdown and self.selectedText is not None: 
     566            # User has clicked on text and is dragging 
     567            ax = event.inaxes 
     568            if ax != None: 
     569                # Only move text if mouse is within axes 
     570                self.selectedText.set_position((event.xdata, event.ydata)) 
     571                self.canvas.draw_idle() 
     572            else: 
     573                # User has dragged outside of axes 
     574                self.selectedText = None 
     575            return 
     576 
     577    def onMplPick(self, event): 
     578        """ 
     579        On pick legend 
     580        """ 
     581        legend = self.legend 
     582        if event.artist == legend: 
     583            # Get the box of the legend. 
     584            bbox = self.legend.get_window_extent() 
     585            # Get mouse coordinates at time of pick. 
     586            self.mouse_x = event.mouseevent.x 
     587            self.mouse_y = event.mouseevent.y 
     588            # Get legend coordinates at time of pick. 
     589            self.legend_x = bbox.xmin 
     590            self.legend_y = bbox.ymin 
     591            # Indicate we picked up the legend. 
     592            self.gotLegend = 1 
     593 
     594            #self.legend.legendPatch.set_alpha(0.5) 
     595 
     596    def onLegendMotion(self, event): 
     597        """ 
     598        On legend in motion 
     599        """ 
     600        ax = event.inaxes 
     601        if ax == None: 
     602            return 
     603        # Event occurred inside a plotting area 
     604        lo_x, hi_x = ax.get_xlim() 
     605        lo_y, hi_y = ax.get_ylim() 
     606        # How much the mouse moved. 
     607        x = mouse_diff_x = self.mouse_x - event.x 
     608        y = mouse_diff_y = self.mouse_y - event.y 
     609        # Put back inside 
     610        if x < lo_x: 
     611            x = lo_x 
     612        if x > hi_x: 
     613            x = hi_x 
     614        if y < lo_y: 
     615            y = lo_y 
     616        if y > hi_y: 
     617            y = hi_y 
     618        # Move the legend from its previous location by that same amount 
     619        loc_in_canvas = self.legend_x - mouse_diff_x, \ 
     620                        self.legend_y - mouse_diff_y 
     621        # Transform into legend coordinate system 
     622        trans_axes = self.legend.parent.transAxes.inverted() 
     623        loc_in_norm_axes = trans_axes.transform_point(loc_in_canvas) 
     624        self.legend_pos_loc = tuple(loc_in_norm_axes) 
     625        self.legend._loc = self.legend_pos_loc 
     626        # self.canvas.draw() 
     627        self.canvas.draw_idle() 
     628 
     629    def onMplWheel(self, event): 
     630        """ 
     631        Process mouse wheel as zoom events 
     632        """ 
     633        ax = event.inaxes 
     634        step = event.step 
     635 
     636        if ax != None: 
     637            # Event occurred inside a plotting area 
     638            lo, hi = ax.get_xlim() 
     639            lo, hi = PlotUtilities.rescale(lo, hi, step, 
     640                              pt=event.xdata, scale=ax.get_xscale()) 
     641            if not self.xscale == 'log' or lo > 0: 
     642                self._scale_xlo = lo 
     643                self._scale_xhi = hi 
     644                ax.set_xlim((lo, hi)) 
     645 
     646            lo, hi = ax.get_ylim() 
     647            lo, hi = PlotUtilities.rescale(lo, hi, step, pt=event.ydata, 
     648                              scale=ax.get_yscale()) 
     649            if not self.yscale == 'log' or lo > 0: 
     650                self._scale_ylo = lo 
     651                self._scale_yhi = hi 
     652                ax.set_ylim((lo, hi)) 
     653        else: 
     654            # Check if zoom happens in the axes 
     655            xdata, ydata = None, None 
     656            x, y = event.x, event.y 
     657 
     658            for ax in self.axes: 
     659                insidex, _ = ax.xaxis.contains(event) 
     660                if insidex: 
     661                    xdata, _ = ax.transAxes.inverted().transform_point((x, y)) 
     662                insidey, _ = ax.yaxis.contains(event) 
     663                if insidey: 
     664                    _, ydata = ax.transAxes.inverted().transform_point((x, y)) 
     665            if xdata is not None: 
     666                lo, hi = ax.get_xlim() 
     667                lo, hi = PlotUtilities.rescale(lo, hi, step, 
     668                                  bal=xdata, scale=ax.get_xscale()) 
     669                if not self.xscale == 'log' or lo > 0: 
     670                    self._scale_xlo = lo 
     671                    self._scale_xhi = hi 
     672                    ax.set_xlim((lo, hi)) 
     673            if ydata is not None: 
     674                lo, hi = ax.get_ylim() 
     675                lo, hi = PlotUtilities.rescale(lo, hi, step, bal=ydata, 
     676                                  scale=ax.get_yscale()) 
     677                if not self.yscale == 'log' or lo > 0: 
     678                    self._scale_ylo = lo 
     679                    self._scale_yhi = hi 
     680                    ax.set_ylim((lo, hi)) 
     681        self.canvas.draw_idle() 
     682 
    518683 
    519684class Plotter(QtGui.QDialog, PlotterWidget): 
  • src/sas/qtgui/Plotter2D.py

    r5d89f43 r3bdbfcc  
    1111 
    1212import sas.qtgui.PlotUtilities as PlotUtilities 
     13import sas.qtgui.GuiUtils as GuiUtils 
    1314from sas.qtgui.PlotterBase import PlotterBase 
    1415from sas.qtgui.ColorMap import ColorMap 
     16from sas.sasgui.guiframe.dataFitting import Data1D 
    1517from sas.sasgui.guiframe.dataFitting import Data2D 
     18from sas.sascalc.dataloader.manipulations import CircularAverage 
     19from sas.sasgui.guiframe.local_perspectives.plotting.binder import BindArtist 
     20from sas.qtgui.BoxSum import BoxSum 
     21from sas.qtgui.GuiUtils import formatNumber 
     22from sas.qtgui.SlicerParameters import SlicerParameters 
     23from sas.sasgui.guiframe.local_perspectives.plotting.boxSlicer import BoxInteractorX 
     24from sas.sasgui.guiframe.local_perspectives.plotting.AnnulusSlicer import AnnulusInteractor 
     25from sas.sasgui.guiframe.local_perspectives.plotting.SectorSlicer import SectorInteractor 
     26from sas.sasgui.guiframe.local_perspectives.plotting.boxSum import BoxSumCalculator 
     27from sas.sasgui.guiframe.local_perspectives.plotting.boxSlicer import BoxInteractorY 
    1628 
    1729# Minimum value of Z for which we will present data. 
    18 MIN_Z=-32 
     30MIN_Z = -32 
    1931 
    2032class Plotter2DWidget(PlotterBase): 
     
    2941        # Default scale 
    3042        self.scale = 'log_{10}' 
     43        # to set the order of lines drawn first. 
     44        self.slicer_z = 5 
     45        # Reference to the current slicer 
     46        self.slicer = None 
     47        # Create Artist and bind it 
     48        self.connect = BindArtist(self.figure) 
    3149        self.vmin = None 
    3250        self.vmax = None 
     
    5371        self.title(title=data.title) 
    5472 
    55     def plot(self, data=None, marker=None, linestyle=None): 
     73    @property 
     74    def item(self): 
     75        ''' getter for this plot's QStandardItem ''' 
     76        return self._item 
     77 
     78    @item.setter 
     79    def item(self, item=None): 
     80        ''' setter for this plot's QStandardItem ''' 
     81        self._item = item 
     82 
     83    def plot(self, data=None): 
    5684        """ 
    5785        Plot 2D self._data 
     
    6189            self.data = data 
    6290 
    63         assert(self._data) 
     91        assert self._data 
    6492 
    6593        # Toggle the scale 
     
    128156        self.actionBoxAveragingY = self.contextMenu.addAction("&Box Averaging in Qy") 
    129157        self.actionBoxAveragingY.triggered.connect(self.onBoxAveragingY) 
    130         self.contextMenu.addSeparator() 
    131         self.actionEditGraphLabel = self.contextMenu.addAction("&Edit Graph Label") 
    132         self.actionEditGraphLabel.triggered.connect(self.onEditgraphLabel) 
     158        # Additional items for slicer interaction 
     159        if self.slicer: 
     160            self.actionClearSlicer = self.contextMenu.addAction("&Clear Slicer") 
     161            self.actionClearSlicer.triggered.connect(self.onClearSlicer) 
     162            self.actionEditSlicer = self.contextMenu.addAction("&Edit Slicer Parameters") 
     163            self.actionEditSlicer.triggered.connect(self.onEditSlicer) 
    133164        self.contextMenu.addSeparator() 
    134165        self.actionColorMap = self.contextMenu.addAction("&2D Color Map") 
     
    166197        self.plot() 
    167198 
     199    def onClearSlicer(self): 
     200        """ 
     201        Remove all sclicers from the chart 
     202        """ 
     203        if self.slicer: 
     204            self.slicer.clear() 
     205            self.canvas.draw() 
     206            self.slicer = None 
     207 
     208    def onEditSlicer(self): 
     209        """ 
     210        Present a small dialog for manipulating the current slicer 
     211        """ 
     212        assert self.slicer 
     213 
     214        self.param_model = self.slicer.model() 
     215         # Pass the model to the Slicer Parameters widget 
     216        self.slicer_widget = SlicerParameters(self, model=self.param_model) 
     217        self.slicer_widget.show() 
     218 
    168219    def onCircularAverage(self): 
    169220        """ 
    170         """ 
    171         pass 
     221        Perform circular averaging on Data2D 
     222        """ 
     223        # Find the best number of bins 
     224        npt = numpy.sqrt(len(self.data.data[numpy.isfinite(self.data.data)])) 
     225        npt = numpy.floor(npt) 
     226        # compute the maximum radius of data2D 
     227        self.qmax = max(numpy.fabs(self.data.xmax), 
     228                        numpy.fabs(self.data.xmin)) 
     229        self.ymax = max(numpy.fabs(self.data.ymax), 
     230                        numpy.fabs(self.data.ymin)) 
     231        self.radius = numpy.sqrt(numpy.power(self.qmax, 2) + numpy.power(self.ymax, 2)) 
     232        #Compute beam width 
     233        bin_width = (self.qmax + self.qmax) / npt 
     234        # Create data1D circular average of data2D 
     235        circle = CircularAverage(r_min=0, r_max=self.radius, bin_width=bin_width) 
     236        circ = circle(self.data) 
     237        dxl = circ.dxl if hasattr(circ, "dxl") else None 
     238        dxw = circ.dxw if hasattr(circ, "dxw") else None 
     239 
     240        new_plot = Data1D(x=circ.x, y=circ.y, dy=circ.dy, dx=circ.dx) 
     241        new_plot.dxl = dxl 
     242        new_plot.dxw = dxw 
     243        new_plot.name = new_plot.title = "Circ avg " + self.data.name 
     244        new_plot.source = self.data.source 
     245        new_plot.interactive = True 
     246        new_plot.detector = self.data.detector 
     247 
     248        # Define axes if not done yet. 
     249        new_plot.xaxis("\\rm{Q}", "A^{-1}") 
     250        if hasattr(self.data, "scale") and \ 
     251                    self.data.scale == 'linear': 
     252            new_plot.ytransform = 'y' 
     253            new_plot.yaxis("\\rm{Residuals} ", "normalized") 
     254        else: 
     255            new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}") 
     256 
     257        new_plot.group_id = "2daverage" + self.data.name 
     258        new_plot.id = "Circ avg " + self.data.name 
     259        new_plot.is_data = True 
     260        variant_plot = QtCore.QVariant(new_plot) 
     261        GuiUtils.updateModelItemWithPlot(self._item, variant_plot, new_plot.id) 
     262        # TODO: force immediate display (?) 
     263 
     264    def setSlicer(self, slicer): 
     265        """ 
     266        Clear the previous slicer and create a new one. 
     267        slicer: slicer class to create 
     268        """ 
     269        # Clear current slicer 
     270        if self.slicer is not None: 
     271            self.slicer.clear() 
     272        # Create a new slicer 
     273        self.slicer_z += 1 
     274        self.slicer = slicer(self, self.ax, item=self._item, zorder=self.slicer_z) 
     275        self.ax.set_ylim(self.data.ymin, self.data.ymax) 
     276        self.ax.set_xlim(self.data.xmin, self.data.xmax) 
     277        # Draw slicer 
     278        self.figure.canvas.draw() 
     279        self.slicer.update() 
    172280 
    173281    def onSectorView(self): 
    174282        """ 
    175         """ 
    176         pass 
     283        Perform sector averaging on Q and draw sector slicer 
     284        """ 
     285        self.setSlicer(slicer=SectorInteractor) 
    177286 
    178287    def onAnnulusView(self): 
    179288        """ 
    180         """ 
    181         pass 
     289        Perform sector averaging on Phi and draw annulus slicer 
     290        """ 
     291        self.setSlicer(slicer=AnnulusInteractor) 
    182292 
    183293    def onBoxSum(self): 
    184294        """ 
    185         """ 
    186         pass 
     295        Perform 2D Data averaging Qx and Qy. 
     296        Display box slicer details. 
     297        """ 
     298        self.onClearSlicer() 
     299        self.slicer_z += 1 
     300        self.slicer = BoxSumCalculator(self, self.ax, zorder=self.slicer_z) 
     301 
     302        self.ax.set_ylim(self.data.ymin, self.data.ymax) 
     303        self.ax.set_xlim(self.data.xmin, self.data.xmax) 
     304        self.figure.canvas.draw() 
     305        self.slicer.update() 
     306 
     307        # Get the BoxSumCalculator model. 
     308        self.box_sum_model = self.slicer.model() 
     309        # Pass the BoxSumCalculator model to the BoxSum widget 
     310        self.boxwidget = BoxSum(self, model=self.box_sum_model) 
     311        # Add the plot to the workspace 
     312        self.manager.parent.workspace().addWindow(self.boxwidget) 
     313        self.boxwidget.show() 
    187314 
    188315    def onBoxAveragingX(self): 
    189316        """ 
    190         """ 
    191         pass 
     317        Perform 2D data averaging on Qx 
     318        Create a new slicer. 
     319        """ 
     320        self.setSlicer(slicer=BoxInteractorX) 
    192321 
    193322    def onBoxAveragingY(self): 
    194323        """ 
    195         """ 
    196         pass 
    197  
    198     def onEditgraphLabel(self): 
    199         """ 
    200         """ 
    201         pass 
     324        Perform 2D data averaging on Qy 
     325        Create a new slicer . 
     326        """ 
     327        self.setSlicer(slicer=BoxInteractorY) 
    202328 
    203329    def onColorMap(self): 
     
    225351 
    226352    def showPlot(self, data, qx_data, qy_data, xmin, xmax, ymin, ymax, 
    227                  zmin, zmax, color=0, symbol=0, markersize=0, 
    228                  label='data2D', cmap=DEFAULT_CMAP): 
     353                 zmin, zmax, label='data2D', cmap=DEFAULT_CMAP): 
    229354        """ 
    230355        Render and show the current data 
     
    310435            self.figure.subplots_adjust(left=0.1, right=.8, bottom=.1) 
    311436 
    312             X = self._data.x_bins[0:-1] 
    313             Y = self._data.y_bins[0:-1] 
    314             X, Y = numpy.meshgrid(X, Y) 
     437            data_x, data_y = numpy.meshgrid(self._data.x_bins[0:-1], 
     438                                            self._data.y_bins[0:-1]) 
    315439 
    316440            ax = Axes3D(self.figure) 
     
    319443            # TODO: Define "large" for a dataset 
    320444            SET_TOO_LARGE = 500 
    321             if len(X) > SET_TOO_LARGE: 
     445            if len(data_x) > SET_TOO_LARGE: 
    322446                ax.disable_mouse_rotation() 
    323447 
    324448            self.figure.canvas.resizing = False 
    325             im = ax.plot_surface(X, Y, output, rstride=1, cstride=1, cmap=cmap, 
     449            im = ax.plot_surface(data_x, data_y, output, rstride=1, 
     450                                 cstride=1, cmap=cmap, 
    326451                                 linewidth=0, antialiased=False) 
    327452            self.ax.set_axis_off() 
     
    332457            self.figure.canvas.draw() 
    333458 
     459    def update(self): 
     460        self.figure.canvas.draw() 
     461 
     462    def draw(self): 
     463        self.figure.canvas.draw() 
     464 
     465 
    334466class Plotter2D(QtGui.QDialog, Plotter2DWidget): 
     467    """ 
     468    Plotter widget implementation 
     469    """ 
    335470    def __init__(self, parent=None, quickplot=False, dimension=2): 
    336  
    337471        QtGui.QDialog.__init__(self) 
    338472        Plotter2DWidget.__init__(self, manager=parent, quickplot=quickplot, dimension=dimension) 
  • src/sas/qtgui/PlotterBase.py

    r092a3d9 r3bdbfcc  
    220220        self.contextMenu.exec_(self.canvas.mapToGlobal(event_pos)) 
    221221 
     222    def onMplMouseUp(self, event): 
     223        """ 
     224        Mouse button up callback 
     225        """ 
     226        pass 
     227 
    222228    def onMplMouseDown(self, event): 
    223229        """ 
    224         Left button down and ready to drag 
    225         """ 
    226         # Check that the LEFT button was pressed 
    227         if event.button == 1: 
    228             self.leftdown = True 
    229             ax = event.inaxes 
    230             for text in self.textList: 
    231                 if text.contains(event)[0]: # If user has clicked on text 
    232                     self.selectedText = text 
    233                     return 
    234  
    235             if ax != None: 
    236                 self.xInit, self.yInit = event.xdata, event.ydata 
    237                 try: 
    238                     self.x_click = float(event.xdata)  # / size_x 
    239                     self.y_click = float(event.ydata)  # / size_y 
    240                 except: 
    241                     self.position = None 
    242  
    243     def onMplMouseUp(self, event): 
    244         """ 
    245         Set the data coordinates of the click 
    246         """ 
    247         self.x_click = event.xdata 
    248         self.y_click = event.ydata 
    249  
    250         # Check that the LEFT button was released 
    251         if event.button == 1: 
    252             self.leftdown = False 
    253             #self.leftup = True 
    254             self.selectedText = None 
    255  
    256         #release the legend 
    257         if self.gotLegend == 1: 
    258             self.gotLegend = 0 
     230        Mouse button down callback 
     231        """ 
     232        pass 
    259233 
    260234    def onMplMouseMotion(self, event): 
    261235        """ 
    262         Check if the left button is press and the mouse in moving. 
    263         Compute delta for x and y coordinates and then perform the drag 
    264         """ 
    265         if self.gotLegend == 1 and self.leftdown: 
    266             self.onLegendMotion(event) 
    267             return 
    268  
    269         if self.leftdown and self.selectedText is not None: 
    270             # User has clicked on text and is dragging 
    271             ax = event.inaxes 
    272             if ax != None: 
    273                 # Only move text if mouse is within axes 
    274                 self.selectedText.set_position((event.xdata, event.ydata)) 
    275                 self.canvas.draw_idle() 
    276             else: 
    277                 # User has dragged outside of axes 
    278                 self.selectedText = None 
    279             return 
     236        Mouse motion callback 
     237        """ 
     238        pass 
    280239 
    281240    def onMplPick(self, event): 
    282241        """ 
    283         On pick legend 
    284         """ 
    285         legend = self.legend 
    286         if event.artist == legend: 
    287             # Get the box of the legend. 
    288             bbox = self.legend.get_window_extent() 
    289             # Get mouse coordinates at time of pick. 
    290             self.mouse_x = event.mouseevent.x 
    291             self.mouse_y = event.mouseevent.y 
    292             # Get legend coordinates at time of pick. 
    293             self.legend_x = bbox.xmin 
    294             self.legend_y = bbox.ymin 
    295             # Indicate we picked up the legend. 
    296             self.gotLegend = 1 
    297  
    298             #self.legend.legendPatch.set_alpha(0.5) 
    299  
    300     def onLegendMotion(self, event): 
    301         """ 
    302         On legend in motion 
    303         """ 
    304         ax = event.inaxes 
    305         if ax == None: 
    306             return 
    307         # Event occurred inside a plotting area 
    308         lo_x, hi_x = ax.get_xlim() 
    309         lo_y, hi_y = ax.get_ylim() 
    310         # How much the mouse moved. 
    311         x = mouse_diff_x = self.mouse_x - event.x 
    312         y = mouse_diff_y = self.mouse_y - event.y 
    313         # Put back inside 
    314         if x < lo_x: 
    315             x = lo_x 
    316         if x > hi_x: 
    317             x = hi_x 
    318         if y < lo_y: 
    319             y = lo_y 
    320         if y > hi_y: 
    321             y = hi_y 
    322         # Move the legend from its previous location by that same amount 
    323         loc_in_canvas = self.legend_x - mouse_diff_x, \ 
    324                         self.legend_y - mouse_diff_y 
    325         # Transform into legend coordinate system 
    326         trans_axes = self.legend.parent.transAxes.inverted() 
    327         loc_in_norm_axes = trans_axes.transform_point(loc_in_canvas) 
    328         self.legend_pos_loc = tuple(loc_in_norm_axes) 
    329         self.legend._loc = self.legend_pos_loc 
    330         # self.canvas.draw() 
    331         self.canvas.draw_idle() 
     242        Mouse pick callback 
     243        """ 
     244        pass 
    332245 
    333246    def onMplWheel(self, event): 
    334247        """ 
    335         Process mouse wheel as zoom events 
    336         """ 
    337         ax = event.inaxes 
    338         step = event.step 
    339  
    340         if ax != None: 
    341             # Event occurred inside a plotting area 
    342             lo, hi = ax.get_xlim() 
    343             lo, hi = PlotUtilities.rescale(lo, hi, step, 
    344                               pt=event.xdata, scale=ax.get_xscale()) 
    345             if not self.xscale == 'log' or lo > 0: 
    346                 self._scale_xlo = lo 
    347                 self._scale_xhi = hi 
    348                 ax.set_xlim((lo, hi)) 
    349  
    350             lo, hi = ax.get_ylim() 
    351             lo, hi = PlotUtilities.rescale(lo, hi, step, pt=event.ydata, 
    352                               scale=ax.get_yscale()) 
    353             if not self.yscale == 'log' or lo > 0: 
    354                 self._scale_ylo = lo 
    355                 self._scale_yhi = hi 
    356                 ax.set_ylim((lo, hi)) 
    357         else: 
    358             # Check if zoom happens in the axes 
    359             xdata, ydata = None, None 
    360             x, y = event.x, event.y 
    361  
    362             for ax in self.axes: 
    363                 insidex, _ = ax.xaxis.contains(event) 
    364                 if insidex: 
    365                     xdata, _ = ax.transAxes.inverted().transform_point((x, y)) 
    366                 insidey, _ = ax.yaxis.contains(event) 
    367                 if insidey: 
    368                     _, ydata = ax.transAxes.inverted().transform_point((x, y)) 
    369             if xdata is not None: 
    370                 lo, hi = ax.get_xlim() 
    371                 lo, hi = PlotUtilities.rescale(lo, hi, step, 
    372                                   bal=xdata, scale=ax.get_xscale()) 
    373                 if not self.xscale == 'log' or lo > 0: 
    374                     self._scale_xlo = lo 
    375                     self._scale_xhi = hi 
    376                     ax.set_xlim((lo, hi)) 
    377             if ydata is not None: 
    378                 lo, hi = ax.get_ylim() 
    379                 lo, hi = PlotUtilities.rescale(lo, hi, step, bal=ydata, 
    380                                   scale=ax.get_yscale()) 
    381                 if not self.yscale == 'log' or lo > 0: 
    382                     self._scale_ylo = lo 
    383                     self._scale_yhi = hi 
    384                     ax.set_ylim((lo, hi)) 
    385         self.canvas.draw_idle() 
     248        Mouse wheel scroll callback 
     249        """ 
     250        pass 
    386251 
    387252    def clean(self): 
  • src/sas/qtgui/UnitTesting/Plotter2DTest.py

    r03c372d r3bdbfcc  
    11import sys 
    22import unittest 
     3import numpy 
    34 
    45from PyQt4 import QtGui 
     
    2425    def setUp(self): 
    2526        '''create''' 
    26         self.plotter = Plotter2D.Plotter2D(None, quickplot=True) 
     27        class dummy_manager(object): 
     28            def communicator(self): 
     29                return Communicate() 
     30            def perspective(self): 
     31                return MyPerspective() 
     32            def workspace(self): 
     33                return None 
     34 
     35        self.plotter = Plotter2D.Plotter2D(parent=dummy_manager(), quickplot=True) 
    2736 
    2837        self.data = Data2D(image=[0.1]*4, 
     
    103112 
    104113        self.assertTrue(FigureCanvas.draw_idle.called) 
     114 
     115    def testOnBoxSum(self): 
     116        """ Test the box sum display and functionality """ 
     117 
     118        # hacky way to make things work in manipulations._sum 
     119        self.data.detector = [1] 
     120        self.data.err_data = numpy.array([0.0, 0.0, 0.1, 0.0]) 
     121        self.plotter.data = self.data 
     122        self.plotter.show() 
     123 
     124        # Mock the main window 
     125        self.plotter.manager.parent = MagicMock() 
     126 
     127        # Call the main tested method 
     128        self.plotter.onBoxSum() 
     129 
     130        # Test various properties 
     131        self.assertIsInstance(self.plotter.slicer.model(), QtGui.QStandardItemModel) 
     132        self.assertTrue(self.plotter.boxwidget.isVisible()) 
     133        self.assertIsInstance(self.plotter.boxwidget.model, QtGui.QStandardItemModel) 
    105134 
    106135    def testContextMenuQuickPlot(self): 
  • src/sas/qtgui/run_tests.bat

    r092a3d9 r3bdbfcc  
    2323python -m UnitTesting.PlotUtilitiesTest 
    2424python -m UnitTesting.ColorMapTest 
     25python -m UnitTesting.BoxSumTest 
     26python -m UnitTesting.SlicerModelTest 
  • src/sas/qtgui/run_tests.sh

    r092a3d9 r3bdbfcc  
    2222python -m UnitTesting.PlotUtilitiesTest 
    2323python -m UnitTesting.ColorMapTest 
     24python -m UnitTesting.BoxSumTest 
     25python -m UnitTesting.SlicerModelTest 
  • src/sas/sasgui/guiframe/local_perspectives/plotting/AnnulusSlicer.py

    rd85c194 r3bdbfcc  
    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 
     1import numpy 
     2from PyQt4 import QtGui 
     3from PyQt4 import QtCore 
     4 
    165from BaseInteractor import _BaseInteractor 
    176from sas.sasgui.guiframe.dataFitting import Data1D 
    18  
    19 class AnnulusInteractor(_BaseInteractor): 
     7import sas.qtgui.GuiUtils as GuiUtils 
     8from sas.qtgui.GuiUtils import formatNumber 
     9from sas.qtgui.SlicerModel import SlicerModel 
     10 
     11class AnnulusInteractor(_BaseInteractor, SlicerModel): 
    2012    """ 
    2113    Select an annulus through a 2D plot. 
     
    2416    this class is defined by 2 Ringinterators. 
    2517    """ 
    26     def __init__(self, base, axes, color='black', zorder=3): 
     18    def __init__(self, base, axes, item=None, color='black', zorder=3): 
    2719 
    2820        _BaseInteractor.__init__(self, base, axes, color=color) 
     21        SlicerModel.__init__(self) 
     22 
    2923        self.markers = [] 
    3024        self.axes = axes 
    3125        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 
    3429        self.connect = self.base.connect 
    3530 
    36         # # Number of points on the plot 
     31        # Number of points on the plot 
    3732        self.nbins = 36 
    3833        # Cursor position of Rings (Left(-1) or Right(1)) 
    39         self.xmaxd = self.base.data2D.xmax 
    40         self.xmind = self.base.data2D.xmin 
     34        self.xmaxd = self.base.data.xmax 
     35        self.xmind = self.base.data.xmin 
    4136 
    4237        if (self.xmaxd + self.xmind) > 0: 
     
    4540            self.sign = -1 
    4641        # Inner circle 
    47         self.inner_circle = RingInteractor(self, self.base.subplot, 
     42        self.inner_circle = RingInteractor(self, self.axes, 
    4843                                           zorder=zorder, 
    4944                                           r=self.qmax / 2.0, sign=self.sign) 
    5045        self.inner_circle.qmax = self.qmax 
    51         self.outer_circle = RingInteractor(self, self.base.subplot, 
     46        self.outer_circle = RingInteractor(self, self.axes, 
    5247                                           zorder=zorder + 1, r=self.qmax / 1.8, 
    5348                                           sign=self.sign) 
     
    5651        self._post_data() 
    5752 
    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() 
    7554 
    7655    def set_layer(self, n): 
     
    9271        self.inner_circle.clear() 
    9372        self.base.connect.clearall() 
    94         self.base.Unbind(EVT_SLICER_PARS) 
    9573 
    9674    def update(self): 
     
    10886        can restore on Esc. 
    10987        """ 
    110         self.base.freeze_axes() 
    11188        self.inner_circle.save(ev) 
    11289        self.outer_circle.save(ev) 
     
    12097        """ 
    12198        # Data to average 
    122         data = self.base.data2D 
    123         # If we have no data, just return 
    124         if data == None: 
     99        data = self.base.data 
     100        if data is None: 
    125101            return 
    126102 
    127103        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 plot 
     104        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 
    133109        # the default number will be nbins= 36 
    134         if nbins == None: 
     110        if nbins is None: 
    135111            self.nbins = 36 
    136112        else: 
    137113            self.nbins = nbins 
    138         # # create the data1D Q average of data2D 
     114        # Create the data1D Q average of data2D 
    139115        sect = Ring(r_min=rmin, r_max=rmax, nbins=self.nbins) 
    140         sector = sect(self.base.data2D) 
     116        sector = sect(self.base.data) 
    141117 
    142118        if hasattr(sector, "dxl"): 
     
    148124        else: 
    149125            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, 
    151127                          y=sector.y, dy=sector.dy) 
    152128        new_plot.dxl = dxl 
    153129        new_plot.dxw = dxw 
    154         new_plot.name = "AnnulusPhi" + "(" + self.base.data2D.name + ")" 
    155  
    156         new_plot.source = self.base.data2D.source 
    157         # new_plot.info=self.base.data2D.info 
     130        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 
    158134        new_plot.interactive = True 
    159         new_plot.detector = self.base.data2D.detector 
     135        new_plot.detector = self.base.data.detector 
    160136        # If the data file does not tell us what the axes are, just assume... 
    161137        new_plot.xaxis("\\rm{\phi}", 'degrees') 
    162138        new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}") 
    163139        if hasattr(data, "scale") and data.scale == 'linear' and \ 
    164                 self.base.data2D.name.count("Residuals") > 0: 
     140                self.base.data.name.count("Residuals") > 0: 
    165141            new_plot.ytransform = 'y' 
    166142            new_plot.yaxis("\\rm{Residuals} ", "/") 
    167143 
    168         new_plot.group_id = "AnnulusPhi" + self.base.data2D.name 
    169         new_plot.id = "AnnulusPhi" + self.base.data2D.name 
     144        new_plot.group_id = "AnnulusPhi" + self.base.data.name 
     145        new_plot.id = "AnnulusPhi" + self.base.data.name 
    170146        new_plot.is_data = True 
    171147        new_plot.xtransform = "x" 
    172148        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 
     152        if self.update_model: 
     153            self.setModelFromParams() 
     154        self.draw() 
     155 
    175156 
    176157    def moveend(self, ev): 
    177158        """ 
    178159        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) 
     160        Redraw the plot with new parameters. 
     161        """ 
     162        self._post_data(self.nbins) 
    189163 
    190164    def restore(self): 
     
    204178        pass 
    205179 
    206     def get_params(self): 
     180    def getParams(self): 
    207181        """ 
    208182        Store a copy of values of parameters of the slicer into a dictionary. 
    209  
    210183        :return params: the dictionary created 
    211  
    212184        """ 
    213185        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) 
     186        params["inner_radius"] = numpy.fabs(self.inner_circle._inner_mouse_x) 
     187        params["outer_radius"] = numpy.fabs(self.outer_circle._inner_mouse_x) 
    216188        params["nbins"] = self.nbins 
    217189        return params 
    218190 
    219     def set_params(self, params): 
     191    def setParams(self, params): 
    220192        """ 
    221193        Receive a dictionary and reset the slicer with values contained 
     
    224196        :param params: a dictionary containing name of slicer parameters and 
    225197            values the user assigned to the slicer. 
    226  
    227         """ 
    228         inner = math.fabs(params["inner_radius"]) 
    229         outer = math.fabs(params["outer_radius"]) 
     198        """ 
     199        inner = numpy.fabs(params["inner_radius"]) 
     200        outer = numpy.fabs(params["outer_radius"]) 
    230201        self.nbins = int(params["nbins"]) 
    231         # # Update the picture 
     202        # Update the picture 
    232203        self.inner_circle.set_cursor(inner, self.inner_circle._inner_mouse_y) 
    233204        self.outer_circle.set_cursor(outer, self.outer_circle._inner_mouse_y) 
    234         # # Post the data given the nbins entered by the user 
     205        # Post the data given the nbins entered by the user 
    235206        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() 
    246207 
    247208    def draw(self): 
     
    278239        self.sign = sign 
    279240        # # 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  
     241        # Inner circle marker 
     242        x_value = [self.sign * numpy.fabs(self._inner_mouse_x)] 
     243        self.inner_marker = self.axes.plot(x_value, [0], linestyle='', 
     244                                           marker='s', markersize=10, 
     245                                           color=self.color, alpha=0.6, 
     246                                           pickradius=5, label="pick", 
     247                                           zorder=zorder, 
     248                                           visible=True)[0] 
    304249        # Draw a circle 
    305250        [self.inner_circle] = self.axes.plot([], [], linestyle='-', marker='', color=self.color) 
    306         # the number of points that make the ring line 
     251        # The number of points that make the ring line 
    307252        self.npts = 40 
    308253 
     
    325270        """ 
    326271        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] 
     272        self.inner_marker.remove() 
     273        self.inner_circle.remove() 
    334274 
    335275    def get_radius(self): 
     
    347287        y = [] 
    348288        for i in range(self.npts): 
    349             phi = 2.0 * math.pi / (self.npts - 1) * i 
    350  
    351             xval = 1.0 * self._inner_mouse_x * math.cos(phi) 
    352             yval = 1.0 * self._inner_mouse_x * math.sin(phi) 
     289            phi = 2.0 * numpy.pi / (self.npts - 1) * i 
     290 
     291            xval = 1.0 * self._inner_mouse_x * numpy.cos(phi) 
     292            yval = 1.0 * self._inner_mouse_x * numpy.sin(phi) 
    353293 
    354294            x.append(xval) 
    355295            y.append(yval) 
    356296 
    357         self.inner_marker.set(xdata=[self.sign * math.fabs(self._inner_mouse_x)], 
     297        self.inner_marker.set(xdata=[self.sign * numpy.fabs(self._inner_mouse_x)], 
    358298                              ydata=[0]) 
    359299        self.inner_circle.set_data(x, y) 
     
    366306        self._inner_save_x = self._inner_mouse_x 
    367307        self._inner_save_y = self._inner_mouse_y 
    368         self.base.freeze_axes() 
    369308 
    370309    def moveend(self, ev): 
     
    396335        self.update() 
    397336 
    398  
    399     def get_params(self): 
     337    def getParams(self): 
    400338        """ 
    401339        Store a copy of values of parameters of the slicer into a dictionary. 
    402  
    403340        :return params: the dictionary created 
    404  
    405341        """ 
    406342        params = {} 
    407         params["radius"] = math.fabs(self._inner_mouse_x) 
     343        params["radius"] = numpy.fabs(self._inner_mouse_x) 
    408344        return params 
    409345 
    410     def set_params(self, params): 
     346    def setParams(self, params): 
    411347        """ 
    412348        Receive a dictionary and reset the slicer with values contained 
     
    435371        self.base = base 
    436372        self.is_inside = side 
    437         self.qmax = min(math.fabs(self.base.data.xmax), 
    438                         math.fabs(self.base.data.xmin))  # must be positive 
     373        self.qmax = min(numpy.fabs(self.base.data.xmax), 
     374                        numpy.fabs(self.base.data.xmin))  # must be positive 
    439375        self.connect = self.base.connect 
    440376 
     
    448384            self.sign = -1 
    449385        # Inner circle 
    450         self.outer_circle = RingInteractor(self, self.base.subplot, 'blue', 
     386        self.outer_circle = RingInteractor(self, self.axes, 'blue', 
    451387                                           zorder=zorder + 1, r=self.qmax / 1.8, 
    452388                                           sign=self.sign) 
     
    455391        self._post_data() 
    456392 
    457         # Bind to slice parameter events 
    458         # 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 slicer 
    463  
    464         :param event: event of type SlicerParameterEvent with params as 
    465             attribute 
    466         """ 
    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  
    474393    def set_layer(self, n): 
    475394        """ 
    476395        Allow adding plot to the same panel 
    477  
    478396        :param n: the number of layer 
    479  
    480397        """ 
    481398        self.layernum = n 
     
    489406        self.outer_circle.clear() 
    490407        self.base.connect.clearall() 
    491         # self.base.Unbind(EVT_SLICER_PARS) 
    492408 
    493409    def update(self): 
     
    498414        # Update locations 
    499415        self.outer_circle.update() 
    500         # if self.is_inside != None: 
     416        self._post_data() 
    501417        out = self._post_data() 
    502418        return out 
     
    507423        can restore on Esc. 
    508424        """ 
    509         self.base.freeze_axes() 
    510425        self.outer_circle.save(ev) 
    511426 
     
    521436 
    522437        # If we have no data, just return 
    523         if data == None: 
     438        if data is None: 
    524439            return 
    525440        mask = data.mask 
     
    527442 
    528443        rmin = 0 
    529         rmax = math.fabs(self.outer_circle.get_radius()) 
    530  
    531         # # create the data1D Q average of data2D 
     444        rmax = numpy.fabs(self.outer_circle.get_radius()) 
     445 
     446        # Create the data1D Q average of data2D 
    532447        mask = Ringcut(r_min=rmin, r_max=rmax) 
    533448 
     
    536451        else: 
    537452            out = (mask(data)) 
    538         # self.base.data.mask=out 
    539453        return out 
    540454 
     
    566480        pass 
    567481 
    568     def get_params(self): 
     482    def getParams(self): 
    569483        """ 
    570484        Store a copy of values of parameters of the slicer into a dictionary. 
     
    574488        """ 
    575489        params = {} 
    576         params["outer_radius"] = math.fabs(self.outer_circle._inner_mouse_x) 
     490        params["outer_radius"] = numpy.fabs(self.outer_circle._inner_mouse_x) 
    577491        return params 
    578492 
    579     def set_params(self, params): 
     493    def setParams(self, params): 
    580494        """ 
    581495        Receive a dictionary and reset the slicer with values contained 
     
    585499            values the user assigned to the slicer. 
    586500        """ 
    587         outer = math.fabs(params["outer_radius"]) 
    588         # # Update the picture 
     501        outer = numpy.fabs(params["outer_radius"]) 
     502        # Update the picture 
    589503        self.outer_circle.set_cursor(outer, self.outer_circle._inner_mouse_y) 
    590         # # Post the data given the nbins entered by the user 
     504        # Post the data given the nbins entered by the user 
    591505        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() 
    598506 
    599507    def draw(self): 
  • src/sas/sasgui/guiframe/local_perspectives/plotting/SectorSlicer.py

    rd85c194 r3bdbfcc  
    33""" 
    44import math 
    5 import wx 
     5from PyQt4 import QtGui 
     6from PyQt4 import QtCore 
     7 
    68from BaseInteractor import _BaseInteractor 
    7 from sas.sasgui.guiframe.events import NewPlotEvent 
    8 from sas.sasgui.guiframe.events import StatusEvent 
    9 from sas.sasgui.guiframe.events import SlicerParameterEvent 
    10 from sas.sasgui.guiframe.events import EVT_SLICER_PARS 
    119from sas.sasgui.guiframe.dataFitting import Data1D 
    12  
    13  
    14 class SectorInteractor(_BaseInteractor): 
     10import sas.qtgui.GuiUtils as GuiUtils 
     11from sas.qtgui.SlicerModel import SlicerModel 
     12 
     13 
     14class SectorInteractor(_BaseInteractor, SlicerModel): 
    1515    """ 
    1616    Draw a sector slicer.Allow to performQ averaging on data 2D 
    1717    """ 
    18     def __init__(self, base, axes, color='black', zorder=3): 
     18    def __init__(self, base, axes, item=None, color='black', zorder=3): 
    1919 
    2020        _BaseInteractor.__init__(self, base, axes, color=color) 
    21         ## Class initialization 
     21        SlicerModel.__init__(self) 
     22        # Class initialization 
    2223        self.markers = [] 
    2324        self.axes = axes 
    24         ## connect the plot to event 
     25        self._item = item 
     26        # Connect the plot to event 
    2527        self.connect = self.base.connect 
    2628 
    27         ## compute qmax limit to reset the graph 
    28         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) 
     29        # Compute qmax limit to reset the graph 
     30        x = math.pow(max(self.base.data.xmax, 
     31                         math.fabs(self.base.data.xmin)), 2) 
     32        y = math.pow(max(self.base.data.ymax, 
     33                         math.fabs(self.base.data.ymin)), 2) 
    3234        self.qmax = math.sqrt(x + y) 
    33         ## Number of points on the plot 
     35        # Number of points on the plot 
    3436        self.nbins = 20 
    35         ## Angle of the middle line 
     37        # Angle of the middle line 
    3638        self.theta2 = math.pi / 3 
    37         ## Absolute value of the Angle between the middle line and any side line 
     39        # Absolute value of the Angle between the middle line and any side line 
    3840        self.phi = math.pi / 12 
    39         ## Middle line 
    40         self.main_line = LineInteractor(self, self.base.subplot, color='blue', 
     41        # Middle line 
     42        self.main_line = LineInteractor(self, self.axes, color='blue', 
    4143                                        zorder=zorder, r=self.qmax, 
    4244                                        theta=self.theta2) 
    4345        self.main_line.qmax = self.qmax 
    44         ## Right Side line 
    45         self.right_line = SideInteractor(self, self.base.subplot, color='black', 
     46        # Right Side line 
     47        self.right_line = SideInteractor(self, self.axes, color='black', 
    4648                                         zorder=zorder, r=self.qmax, 
    4749                                         phi=-1 * self.phi, theta2=self.theta2) 
    4850        self.right_line.qmax = self.qmax 
    49         ## Left Side line 
    50         self.left_line = SideInteractor(self, self.base.subplot, color='black', 
     51        # Left Side line 
     52        self.left_line = SideInteractor(self, self.axes, color='black', 
    5153                                        zorder=zorder, r=self.qmax, 
    5254                                        phi=self.phi, theta2=self.theta2) 
    5355        self.left_line.qmax = self.qmax 
    54         ## draw the sector 
     56        # draw the sector 
    5557        self.update() 
    5658        self._post_data() 
    57         ## Bind to slice parameter events 
    58         self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS) 
    59  
    60     def _onEVT_SLICER_PARS(self, event): 
    61         """ 
    62         receive an event containing parameters values to reset the slicer 
    63  
    64         :param event: event of type SlicerParameterEvent with params as 
    65         attribute 
    66  
    67         """ 
    68         wx.PostEvent(self.base.parent, 
    69                      StatusEvent(status="SectorSlicer._onEVT_SLICER_PARS")) 
    70         event.Skip() 
    71         if event.type == self.__class__.__name__: 
    72             self.set_params(event.params) 
    73             self.base.update() 
     59        self.setModelFromParams() 
    7460 
    7561    def set_layer(self, n): 
    7662        """ 
    7763         Allow adding plot to the same panel 
    78  
    7964        :param n: the number of layer 
    80  
    8165        """ 
    8266        self.layernum = n 
     
    9276        self.right_line.clear() 
    9377        self.base.connect.clearall() 
    94         self.base.Unbind(EVT_SLICER_PARS) 
    9578 
    9679    def update(self): 
     
    10083        """ 
    10184        # Update locations 
    102         ## Check if the middle line was dragged and 
    103         #update the picture accordingly 
     85        # Check if the middle line was dragged and 
     86        # update the picture accordingly 
    10487        if self.main_line.has_move: 
    10588            self.main_line.update() 
     
    10891            self.left_line.update(delta=self.left_line.phi / 2, 
    10992                                  mline=self.main_line.theta) 
    110         ## Check if the left side has moved and update the slicer accordingly 
     93        # Check if the left side has moved and update the slicer accordingly 
    11194        if self.left_line.has_move: 
    11295            self.main_line.update() 
     
    11699                                   mline=self.main_line, side=True, 
    117100                                   left=False, right=True) 
    118         ## Check if the right side line has moved and 
    119         #update the slicer accordingly 
     101        # Check if the right side line has moved and update the slicer accordingly 
    120102        if self.right_line.has_move: 
    121103            self.main_line.update() 
     
    130112        can restore on Esc. 
    131113        """ 
    132         self.base.freeze_axes() 
    133114        self.main_line.save(ev) 
    134115        self.right_line.save(ev) 
     
    141122        :param nbins: the number of point to plot for the average 1D data 
    142123        """ 
    143         ## get the data2D to average 
    144         data = self.base.data2D 
     124        # Get the data2D to average 
     125        data = self.base.data 
    145126        # If we have no data, just return 
    146127        if data == None: 
    147128            return 
    148         ## Averaging 
     129        # Averaging 
    149130        from sas.sascalc.dataloader.manipulations import SectorQ 
    150131        radius = self.qmax 
     
    157138                       phi_max=phimax + math.pi, nbins=nbins) 
    158139 
    159         sector = sect(self.base.data2D) 
    160         ##Create 1D data resulting from average 
     140        sector = sect(self.base.data) 
     141        # Create 1D data resulting from average 
    161142 
    162143        if hasattr(sector, "dxl"): 
     
    171152        new_plot.dxl = dxl 
    172153        new_plot.dxw = dxw 
    173         new_plot.name = "SectorQ" + "(" + self.base.data2D.name + ")" 
    174         new_plot.source = self.base.data2D.source 
    175         #new_plot.info=self.base.data2D.info 
     154        new_plot.name = "SectorQ" + "(" + self.base.data.name + ")" 
     155        new_plot.title = "SectorQ" + "(" + self.base.data.name + ")" 
     156        new_plot.source = self.base.data.source 
    176157        new_plot.interactive = True 
    177         new_plot.detector = self.base.data2D.detector 
    178         ## If the data file does not tell us what the axes are, just assume... 
     158        new_plot.detector = self.base.data.detector 
     159        # If the data file does not tell us what the axes are, just assume them. 
    179160        new_plot.xaxis("\\rm{Q}", "A^{-1}") 
    180161        new_plot.yaxis("\\rm{Intensity}", "cm^{-1}") 
    181162        if hasattr(data, "scale") and data.scale == 'linear' and \ 
    182                 self.base.data2D.name.count("Residuals") > 0: 
     163                self.base.data.name.count("Residuals") > 0: 
    183164            new_plot.ytransform = 'y' 
    184165            new_plot.yaxis("\\rm{Residuals} ", "/") 
    185166 
    186         new_plot.group_id = "2daverage" + self.base.data2D.name 
    187         new_plot.id = "SectorQ" + self.base.data2D.name 
     167        new_plot.group_id = "2daverage" + self.base.data.name 
     168        new_plot.id = "SectorQ" + self.base.data.name 
    188169        new_plot.is_data = True 
    189         self.base.parent.update_theory(data_id=data.id, theory=new_plot) 
    190         wx.PostEvent(self.base.parent, 
    191                      NewPlotEvent(plot=new_plot, title="SectorQ" + self.base.data2D.name)) 
     170        variant_plot = QtCore.QVariant(new_plot) 
     171        GuiUtils.updateModelItemWithPlot(self._item, variant_plot, new_plot.id) 
     172 
     173        if self.update_model: 
     174            self.setModelFromParams() 
     175        self.draw() 
    192176 
    193177    def moveend(self, ev): 
     
    195179        Called a dragging motion ends.Get slicer event 
    196180        """ 
    197         self.base.thaw_axes() 
    198         ## Post parameters 
    199         event = SlicerParameterEvent() 
    200         event.type = self.__class__.__name__ 
    201         event.params = self.get_params() 
    202         ## Send slicer paramers to plotter2D 
    203         wx.PostEvent(self.base, event) 
     181        # Post parameters 
     182        self._post_data(self.nbins) 
    204183 
    205184    def restore(self): 
     
    222201        pass 
    223202 
    224     def get_params(self): 
     203    def getParams(self): 
    225204        """ 
    226205        Store a copy of values of parameters of the slicer into a dictionary. 
    227  
    228206        :return params: the dictionary created 
    229  
    230207        """ 
    231208        params = {} 
    232         ## Always make sure that the left and the right line are at phi 
    233         ## angle of the middle line 
     209        # Always make sure that the left and the right line are at phi 
     210        # angle of the middle line 
    234211        if math.fabs(self.left_line.phi) != math.fabs(self.right_line.phi): 
    235212            msg = "Phi left and phi right are different" 
     
    241218        return params 
    242219 
    243     def set_params(self, params): 
     220    def setParams(self, params): 
    244221        """ 
    245222        Receive a dictionary and reset the slicer with values contained 
     
    253230        self.nbins = int(params["nbins"]) 
    254231        self.main_line.theta = main 
    255         ## Reset the slicer parameters 
     232        # Reset the slicer parameters 
    256233        self.main_line.update() 
    257234        self.right_line.update(phi=phi, delta=None, mline=self.main_line, 
     
    259236        self.left_line.update(phi=phi, delta=None, 
    260237                              mline=self.main_line, side=True) 
    261         ## post the new corresponding data 
     238        # Post the new corresponding data 
    262239        self._post_data(nbins=self.nbins) 
    263  
    264     def freeze_axes(self): 
    265         """ 
    266         """ 
    267         self.base.freeze_axes() 
    268  
    269     def thaw_axes(self): 
    270         """ 
    271         """ 
    272         self.base.thaw_axes() 
    273240 
    274241    def draw(self): 
     
    291258        """ 
    292259        _BaseInteractor.__init__(self, base, axes, color=color) 
    293         ## Initialize the class 
     260        # Initialize the class 
    294261        self.markers = [] 
    295262        self.axes = axes 
    296         ## compute the value of the angle between the current line and 
    297         ## the x-axis 
     263        # compute the value of the angle between the current line and 
     264        # the x-axis 
    298265        self.save_theta = theta2 + phi 
    299266        self.theta = theta2 + phi 
    300         ## the value of the middle line angle with respect to the x-axis 
     267        # the value of the middle line angle with respect to the x-axis 
    301268        self.theta2 = theta2 
    302         ## Radius to find polar coordinates this line's endpoints 
     269        # Radius to find polar coordinates this line's endpoints 
    303270        self.radius = r 
    304         ## phi is the phase between the current line and the middle line 
     271        # phi is the phase between the current line and the middle line 
    305272        self.phi = phi 
    306         ## End points polar coordinates 
     273        # End points polar coordinates 
    307274        x1 = self.radius * math.cos(self.theta) 
    308275        y1 = self.radius * math.sin(self.theta) 
    309276        x2 = -1 * self.radius * math.cos(self.theta) 
    310277        y2 = -1 * self.radius * math.sin(self.theta) 
    311         ## defining a new marker 
     278        # Defining a new marker 
    312279        self.inner_marker = self.axes.plot([x1 / 2.5], [y1 / 2.5], linestyle='', 
    313280                                           marker='s', markersize=10, 
     
    316283                                           zorder=zorder, visible=True)[0] 
    317284 
    318         ## Defining the current line 
     285        # Defining the current line 
    319286        self.line = self.axes.plot([x1, x2], [y1, y2], 
    320287                                   linestyle='-', marker='', 
    321288                                   color=self.color, visible=True)[0] 
    322         ## Flag to differentiate the left line from the right line motion 
     289        # Flag to differentiate the left line from the right line motion 
    323290        self.left_moving = False 
    324         ## Flag to define a motion 
     291        # Flag to define a motion 
    325292        self.has_move = False 
    326         ## connecting markers and draw the picture 
     293        # connecting markers and draw the picture 
    327294        self.connect_markers([self.inner_marker, self.line]) 
    328295 
     
    330297        """ 
    331298        Allow adding plot to the same panel 
    332  
    333299        :param n: the number of layer 
    334  
    335300        """ 
    336301        self.layernum = n 
     
    359324 
    360325        """ 
    361         #print "update left or right ", self.has_move 
    362326        self.left_moving = left 
    363327        theta3 = 0 
     
    396360        """ 
    397361        self.save_theta = self.theta 
    398         self.base.freeze_axes() 
    399362 
    400363    def moveend(self, ev): 
     
    416379        self.theta = math.atan2(y, x) 
    417380        self.has_move = True 
    418         #ToDo: Simplify below 
    419381        if not self.left_moving: 
    420382            if  self.theta2 - self.theta <= 0 and self.theta2 > 0: 
     
    464426        self.update() 
    465427 
    466     def get_params(self): 
     428    def getParams(self): 
    467429        """ 
    468430        """ 
     
    472434        return params 
    473435 
    474     def set_params(self, params): 
     436    def setParams(self, params): 
    475437        """ 
    476438        """ 
     
    554516        """ 
    555517        self.save_theta = self.theta 
    556         self.base.freeze_axes() 
    557518 
    558519    def moveend(self, ev): 
     
    582543        self.update() 
    583544 
    584     def get_params(self): 
     545    def getParams(self): 
    585546        """ 
    586547        """ 
     
    590551        return params 
    591552 
    592     def set_params(self, params): 
     553    def setParams(self, params): 
    593554        """ 
    594555        """ 
  • src/sas/sasgui/guiframe/local_perspectives/plotting/boxSlicer.py

    rd85c194 r3bdbfcc  
    1 import wx 
    2 import math 
    31import numpy 
    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 
     2from PyQt4 import QtGui 
     3from PyQt4 import QtCore 
     4 
    85from BaseInteractor import _BaseInteractor 
    96from sas.sasgui.guiframe.dataFitting import Data1D 
    10  
    11  
    12 class BoxInteractor(_BaseInteractor): 
     7import sas.qtgui.GuiUtils as GuiUtils 
     8from sas.qtgui.SlicerModel import SlicerModel 
     9 
     10 
     11class BoxInteractor(_BaseInteractor, SlicerModel): 
    1312    """ 
    1413    BoxInteractor define a rectangle that return data1D average of Data2D 
    1514    in a rectangle area defined by -x, x ,y, -y 
    1615    """ 
    17     def __init__(self, base, axes, color='black', zorder=3): 
     16    def __init__(self, base, axes, item=None, color='black', zorder=3): 
    1817        _BaseInteractor.__init__(self, base, axes, color=color) 
    19         # # Class initialization 
     18        SlicerModel.__init__(self) 
     19        # Class initialization 
    2020        self.markers = [] 
    2121        self.axes = axes 
    22         # #connecting artist 
     22        self._item = item 
     23        #connecting artist 
    2324        self.connect = self.base.connect 
    24         # # which direction is the preferred interaction direction 
     25        # which direction is the preferred interaction direction 
    2526        self.direction = None 
    26         # # determine x y  values 
    27         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 graph 
    32         self.qmax = max(self.base.data2D.xmax, self.base.data2D.xmin, 
    33                         self.base.data2D.ymax, self.base.data2D.ymin) 
    34         # # Number of points on the plot 
     27        # 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 
    3536        self.nbins = 30 
    36         # # If True, I(|Q|) will be return, otherwise, 
     37        # If True, I(|Q|) will be return, otherwise, 
    3738        # negative q-values are allowed 
    3839        self.fold = True 
    39         # # reference of the current  Slab averaging 
     40        # reference of the current  Slab averaging 
    4041        self.averager = None 
    41         # # Create vertical and horizaontal lines for the rectangle 
     42        # Create vertical and horizaontal lines for the rectangle 
    4243        self.vertical_lines = VerticalLines(self, 
    43                                             self.base.subplot, 
     44                                            self.axes, 
    4445                                            color='blue', 
    4546                                            zorder=zorder, 
     
    4950 
    5051        self.horizontal_lines = HorizontalLines(self, 
    51                                                 self.base.subplot, 
     52                                                self.axes, 
    5253                                                color='green', 
    5354                                                zorder=zorder, 
     
    5556                                                y=self.y) 
    5657        self.horizontal_lines.qmax = self.qmax 
    57         # # draw the rectangle and plost the data 1D resulting 
    58         # # of averaging data2D 
     58        # draw the rectangle and plost the data 1D resulting 
     59        # of averaging data2D 
    5960        self.update() 
    6061        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() 
    7763 
    7864    def update_and_post(self): 
     
    10288        self.vertical_lines.clear() 
    10389        self.base.connect.clearall() 
    104         self.base.Unbind(EVT_SLICER_PARS) 
    10590 
    10691    def update(self): 
     
    123108        can restore on Esc. 
    124109        """ 
    125         self.base.freeze_axes() 
    126110        self.vertical_lines.save(ev) 
    127111        self.horizontal_lines.save(ev) 
     
    139123 
    140124        """ 
    141         if self.direction == None: 
     125        if self.direction is None: 
    142126            self.direction = direction 
    143127 
    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) 
    148  
    149         if nbins != None: 
     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) 
     132 
     133        if nbins is not None: 
    150134            self.nbins = nbins 
    151         if self.averager == None: 
    152             if new_slab == None: 
     135        if self.averager is None: 
     136            if new_slab is None: 
    153137                msg = "post data:cannot average , averager is empty" 
    154138                raise ValueError, msg 
     
    158142                x_low = 0 
    159143            else: 
    160                 x_low = math.fabs(x_min) 
     144                x_low = numpy.fabs(x_min) 
    161145            bin_width = (x_max + x_low) / self.nbins 
    162146        elif self.direction == "Y": 
     
    164148                y_low = 0 
    165149            else: 
    166                 y_low = math.fabs(y_min) 
     150                y_low = numpy.fabs(y_min) 
    167151            bin_width = (y_max + y_low) / self.nbins 
    168152        else: 
     
    173157                            bin_width=bin_width) 
    174158        box.fold = self.fold 
    175         boxavg = box(self.base.data2D) 
     159        boxavg = box(self.base.data) 
    176160        # 3 Create Data1D to plot 
    177161        if hasattr(boxavg, "dxl"): 
     
    187171        new_plot.dxw = dxw 
    188172        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 
    191177        new_plot.interactive = True 
    192         new_plot.detector = self.base.data2D.detector 
     178        new_plot.detector = self.base.data.detector 
    193179        # # If the data file does not tell us what the axes are, just assume... 
    194180        new_plot.xaxis("\\rm{Q}", "A^{-1}") 
    195181        new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}") 
    196182 
    197         data = self.base.data2D 
     183        data = self.base.data 
    198184        if hasattr(data, "scale") and data.scale == 'linear' and \ 
    199                 self.base.data2D.name.count("Residuals") > 0: 
     185                self.base.data.name.count("Residuals") > 0: 
    200186            new_plot.ytransform = 'y' 
    201187            new_plot.yaxis("\\rm{Residuals} ", "/") 
    202188 
    203         new_plot.group_id = "2daverage" + self.base.data2D.name 
    204         new_plot.id = (self.averager.__name__) + self.base.data2D.name 
     189        new_plot.group_id = "2daverage" + self.base.data.name 
     190        new_plot.id = (self.averager.__name__) + self.base.data.name 
    205191        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() 
    210198 
    211199    def moveend(self, ev): 
     
    215203        corresponding to the new average 
    216204        """ 
    217         self.base.thaw_axes() 
    218         # Post paramters 
    219         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 data1D 
    224205        self._post_data() 
    225206 
     
    240221        pass 
    241222 
    242     def get_params(self): 
     223    def getParams(self): 
    243224        """ 
    244225        Store a copy of values of parameters of the slicer into a dictionary. 
     
    248229        """ 
    249230        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) 
    252233        params["nbins"] = self.nbins 
    253234        return params 
    254235 
    255     def set_params(self, params): 
     236    def setParams(self, params): 
    256237        """ 
    257238        Receive a dictionary and reset the slicer with values contained 
     
    261242            values the user assigned to the slicer. 
    262243        """ 
    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"])) 
    265246        self.nbins = params["nbins"] 
    266247 
     
    269250        self.post_data(nbins=None) 
    270251 
    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  
    281252    def draw(self): 
    282253        """ 
     
    294265        """ 
    295266        _BaseInteractor.__init__(self, base, axes, color=color) 
    296         # #Class initialization 
     267        # Class initialization 
    297268        self.markers = [] 
    298269        self.axes = axes 
    299         # # Saving the end points of two lines 
     270        # Saving the end points of two lines 
    300271        self.x = x 
    301272        self.save_x = x 
     
    303274        self.y = y 
    304275        self.save_y = y 
    305         # # Creating a marker 
     276        # Creating a marker 
    306277        # Inner circle marker 
    307278        self.inner_marker = self.axes.plot([0], [self.y], linestyle='', 
     
    311282                                           zorder=zorder, 
    312283                                           visible=True)[0] 
    313         # # Define 2 horizontal lines 
     284        # Define 2 horizontal lines 
    314285        self.top_line = self.axes.plot([self.x, -self.x], [self.y, self.y], 
    315286                                       linestyle='-', marker='', 
     
    318289                                          linestyle='-', marker='', 
    319290                                          color=self.color, visible=True)[0] 
    320         # # Flag to check the motion of the lines 
     291        # Flag to check the motion of the lines 
    321292        self.has_move = False 
    322         # # Connecting markers to mouse events and draw 
     293        # Connecting markers to mouse events and draw 
    323294        self.connect_markers([self.top_line, self.inner_marker]) 
    324295        self.update() 
     
    339310        """ 
    340311        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() 
    349315 
    350316    def update(self, x=None, y=None): 
     
    356322 
    357323        """ 
    358         # # Reset x, y- coordinates if send as parameters 
    359         if x != None: 
    360             self.x = numpy.sign(self.x) * math.fabs(x) 
    361         if y != None: 
    362             self.y = numpy.sign(self.y) * math.fabs(y) 
    363         # # Draw lines and markers 
     324        # Reset x, y- coordinates if send as parameters 
     325        if x is not None: 
     326            self.x = numpy.sign(self.x) * numpy.fabs(x) 
     327        if y is not None: 
     328            self.y = numpy.sign(self.y) * numpy.fabs(y) 
     329        # Draw lines and markers 
    364330        self.inner_marker.set(xdata=[0], ydata=[self.y]) 
    365331        self.top_line.set(xdata=[self.x, -self.x], ydata=[self.y, self.y]) 
     
    373339        self.save_x = self.x 
    374340        self.save_y = self.y 
    375         self.base.freeze_axes() 
    376341 
    377342    def moveend(self, ev): 
     
    409374        self.markers = [] 
    410375        self.axes = axes 
    411         self.x = math.fabs(x) 
     376        self.x = numpy.fabs(x) 
    412377        self.save_x = self.x 
    413         self.y = math.fabs(y) 
     378        self.y = numpy.fabs(y) 
    414379        self.save_y = y 
    415380        # Inner circle marker 
     
    446411        """ 
    447412        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() 
    456416 
    457417    def update(self, x=None, y=None): 
     
    463423 
    464424        """ 
    465         # # reset x, y -coordinates if given as parameters 
    466         if x != None: 
    467             self.x = numpy.sign(self.x) * math.fabs(x) 
    468         if y != None: 
    469             self.y = numpy.sign(self.y) * math.fabs(y) 
    470         # # draw lines and markers 
     425        # Reset x, y -coordinates if given as parameters 
     426        if x is not None: 
     427            self.x = numpy.sign(self.x) * numpy.fabs(x) 
     428        if y is not None: 
     429            self.y = numpy.sign(self.y) * numpy.fabs(y) 
     430        # Draw lines and markers 
    471431        self.inner_marker.set(xdata=[self.x], ydata=[0]) 
    472432        self.left_line.set(xdata=[-self.x, -self.x], ydata=[self.y, -self.y]) 
     
    480440        self.save_x = self.x 
    481441        self.save_y = self.y 
    482         self.base.freeze_axes() 
    483442 
    484443    def moveend(self, ev): 
     
    510469    Average in Qx direction 
    511470    """ 
    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) 
    514473        self.base = base 
    515474        self._post_data() 
     
    527486    Average in Qy direction 
    528487    """ 
    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) 
    531490        self.base = base 
    532491        self._post_data() 
  • src/sas/sasgui/guiframe/local_perspectives/plotting/boxSum.py

    rd85c194 r3bdbfcc  
    11""" 
     2Boxsum Class: determine 2 rectangular area to compute 
     3the sum of pixel of a Data. 
     4""" 
     5import numpy 
     6from PyQt4 import QtGui 
     7from PyQt4 import QtCore 
     8from sas.qtgui.GuiUtils import formatNumber 
     9 
     10from BaseInteractor import _BaseInteractor 
     11from sas.sascalc.dataloader.manipulations import Boxavg 
     12from sas.sascalc.dataloader.manipulations import Boxsum 
     13 
     14from sas.qtgui.SlicerModel import SlicerModel 
     15 
     16 
     17class BoxSumCalculator(_BaseInteractor): 
     18    """ 
    219    Boxsum Class: determine 2 rectangular area to compute 
    320    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 
    1428    """ 
    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): 
    2930        _BaseInteractor.__init__(self, base, axes, color=color) 
    30         # # class initialization 
    31         # # list of Boxsmun markers 
     31 
     32        # list of Boxsmun markers 
    3233        self.markers = [] 
    3334        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 
    3539        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 
    4854        self.center_x = 0.0002 
    4955        self.center_y = 0.0003 
    50         # # Number of points on the plot 
     56        # Number of points on the plot 
    5157        self.nbins = 20 
    52         # # Define initial result the summation 
     58        # Define initial result the summation 
    5359        self.count = 0 
    5460        self.error = 0 
     
    5662        self.totalerror = 0 
    5763        self.points = 0 
    58         # # Flag to determine if the current figure has moved 
    59         # # set to False == no motion , set to True== motion 
     64        # Flag to determine if the current figure has moved 
     65        # set to False == no motion , set to True== motion 
    6066        self.has_move = False 
    61         # # Create Boxsum edges 
     67        # Create Boxsum edges 
    6268        self.horizontal_lines = HorizontalDoubleLine(self, 
    63                                                      self.base.subplot, 
     69                                                     self.axes, 
    6470                                                     color='blue', 
    6571                                                     zorder=zorder, 
     
    7177 
    7278        self.vertical_lines = VerticalDoubleLine(self, 
    73                                                  self.base.subplot, 
     79                                                 self.axes, 
    7480                                                 color='black', 
    7581                                                 zorder=zorder, 
     
    8187 
    8288        self.center = PointInteractor(self, 
    83                                       self.base.subplot, color='grey', 
     89                                      self.axes, color='grey', 
    8490                                      zorder=zorder, 
    8591                                      center_x=self.center_x, 
    8692                                      center_y=self.center_y) 
    87         # # Save the name of the slicer panel associate with this slicer 
     93        # Save the name of the slicer panel associate with this slicer 
    8894        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 
    99161        """ 
    100162        self.panel_name = name 
    101163 
    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): 
    118165        """ 
    119166        Allow adding plot to the same panel 
     
    132179        self.center.clear() 
    133180        self.base.connect.clearall() 
    134         self.base.Unbind(EVT_SLICER_PARS) 
    135181 
    136182    def update(self): 
     
    139185        resetting the widgets. 
    140186        """ 
    141         # # check if the center point has moved and update the figure accordingly 
     187        # check if the center point has moved and update the figure accordingly 
    142188        if self.center.has_move: 
    143189            self.center.update() 
    144190            self.horizontal_lines.update(center=self.center) 
    145191            self.vertical_lines.update(center=self.center) 
    146         # # check if the horizontal lines have moved and 
     192        # check if the horizontal lines have moved and 
    147193        # update the figure accordingly 
    148194        if self.horizontal_lines.has_move: 
     
    151197                                       y2=self.horizontal_lines.y2, 
    152198                                       height=self.horizontal_lines.half_height) 
    153         # # check if the vertical lines have moved and 
     199        # check if the vertical lines have moved and 
    154200        # update the figure accordingly 
    155201        if self.vertical_lines.has_move: 
     
    164210        can restore on Esc. 
    165211        """ 
    166         self.base.freeze_axes() 
    167212        self.horizontal_lines.save(ev) 
    168213        self.vertical_lines.save(ev) 
    169214        self.center.save(ev) 
    170215 
    171     def _post_data(self): 
     216    def postData(self): 
    172217        """ 
    173218        Get the limits of the boxsum and compute the sum of the pixel 
    174219        contained in that region and the error on that sum 
    175220        """ 
    176         # # the region of the summation 
     221        # the region of the summation 
    177222        x_min = self.horizontal_lines.x2 
    178223        x_max = self.horizontal_lines.x1 
    179224        y_min = self.vertical_lines.y2 
    180225        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 
    183227        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.data2D) 
     228        self.count, self.error = box(self.base.data) 
    185229        # Dig out number of points summed, SMK & PDB, 04/03/2013 
    186         from sas.sascalc.dataloader.manipulations import Boxsum 
    187230        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() 
    189235 
    190236    def moveend(self, ev): 
    191237        """ 
    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() 
    206243 
    207244    def restore(self): 
     
    213250        self.center.restore() 
    214251 
    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): 
    227253        """ 
    228254        Store a copy of values of parameters of the slicer into a dictionary. 
     
    230256        """ 
    231257        params = {} 
    232         params["Width"] = math.fabs(self.vertical_lines.half_width) * 2 
    233         params["Height"] = math.fabs(self.horizontal_lines.half_height) * 2 
     258        params["Width"] = numpy.fabs(self.vertical_lines.half_width) * 2 
     259        params["Height"] = numpy.fabs(self.horizontal_lines.half_height) * 2 
    234260        params["center_x"] = self.center.x 
    235261        params["center_y"] = self.center.y 
     
    241267        return params 
    242268 
    243     def get_result(self): 
    244         """ 
    245             return the result of box summation 
     269    def getResult(self): 
     270        """ 
     271        Return the result of box summation 
    246272        """ 
    247273        result = {} 
     
    253279        return result 
    254280 
    255     def set_params(self, params): 
     281    def setParams(self, params): 
    256282        """ 
    257283        Receive a dictionary and reset the slicer with values contained 
    258284        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 
    263290 
    264291        self.center_x = params["center_x"] 
     
    271298                                   width=x_max, height=y_max) 
    272299        # 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() 
    284301 
    285302    def draw(self): 
    286         """ 
    287         """ 
     303        """ Redraw canvas""" 
    288304        self.base.draw() 
    289305 
     
    297313    def __init__(self, base, axes, color='black', zorder=5, center_x=0.0, 
    298314                 center_y=0.0): 
    299         """ 
    300         """ 
    301315        _BaseInteractor.__init__(self, base, axes, color=color) 
    302         # # Initialization the class 
     316        # Initialization the class 
    303317        self.markers = [] 
    304318        self.axes = axes 
     
    306320        self.x = center_x 
    307321        self.y = center_y 
    308         # # saved value of the center coordinates 
     322        # saved value of the center coordinates 
    309323        self.save_x = center_x 
    310324        self.save_y = center_y 
    311         # # Create a marker 
     325        # Create a marker 
    312326        self.center_marker = self.axes.plot([self.x], [self.y], linestyle='', 
    313327                                            marker='s', markersize=10, 
     
    316330                                            zorder=zorder, 
    317331                                            visible=True)[0] 
    318         # # Draw a point 
     332        # Draw a point 
    319333        self.center = self.axes.plot([self.x], [self.y], 
    320334                                     linestyle='-', marker='', 
    321335                                     color=self.color, 
    322336                                     visible=True)[0] 
    323         # # Flag to determine the motion this point 
     337        # Flag to determine the motion this point 
    324338        self.has_move = False 
    325         # # connecting the marker to allow them to move 
     339        # connecting the marker to allow them to move 
    326340        self.connect_markers([self.center_marker]) 
    327         # # Update the figure 
    328         self.update() 
    329  
    330     def set_layer(self, n): 
    331         """ 
    332             Allow adding plot to the same panel 
    333             @param n: the number of layer 
     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 
    334348        """ 
    335349        self.layernum = n 
     
    338352    def clear(self): 
    339353        """ 
    340             Clear this figure and its markers 
     354        Clear this figure and its markers 
    341355        """ 
    342356        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() 
    350359 
    351360    def update(self, center_x=None, center_y=None): 
    352361        """ 
    353             Draw the new roughness on the graph. 
     362        Draw the new roughness on the graph. 
    354363        """ 
    355364        if center_x != None: 
     
    367376        self.save_x = self.x 
    368377        self.save_y = self.y 
    369         self.base.freeze_axes() 
    370378 
    371379    def moveend(self, ev): 
     
    391399        self.base.base.update() 
    392400 
    393     def set_cursor(self, x, y): 
     401    def setCursor(self, x, y): 
    394402        """ 
    395403        """ 
     
    399407class VerticalDoubleLine(_BaseInteractor): 
    400408    """ 
    401          Draw 2 vertical lines moving in opposite direction and centered on 
    402          a point (PointInteractor) 
     409    Draw 2 vertical lines moving in opposite direction and centered on 
     410    a point (PointInteractor) 
    403411    """ 
    404412    def __init__(self, base, axes, color='black', zorder=5, x=0.5, y=0.5, 
    405413                 center_x=0.0, center_y=0.0): 
    406         """ 
    407         """ 
    408414        _BaseInteractor.__init__(self, base, axes, color=color) 
    409         # # Initialization the class 
     415        # Initialization the class 
    410416        self.markers = [] 
    411417        self.axes = axes 
    412         # # Center coordinates 
     418        # Center coordinates 
    413419        self.center_x = center_x 
    414420        self.center_y = center_y 
    415         # # defined end points vertical lignes and their saved values 
     421        # defined end points vertical lignes and their saved values 
    416422        self.y1 = y + self.center_y 
    417423        self.save_y1 = self.y1 
     
    429435        # # save the color of the line 
    430436        self.color = color 
    431         # # the height of the rectangle 
    432         self.half_height = math.fabs(y) 
    433         self.save_half_height = math.fabs(y) 
    434         # # the with of the rectangle 
    435         self.half_width = math.fabs(self.x1 - self.x2) / 2 
    436         self.save_half_width = math.fabs(self.x1 - self.x2) / 2 
    437         # # Create marker 
     437        # 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 
    438444        self.right_marker = self.axes.plot([self.x1], [0], linestyle='', 
    439445                                           marker='s', markersize=10, 
     
    442448                                           zorder=zorder, visible=True)[0] 
    443449 
    444         # # define the left and right lines of the rectangle 
     450        # Define the left and right lines of the rectangle 
    445451        self.right_line = self.axes.plot([self.x1, self.x1], [self.y1, self.y2], 
    446452                                         linestyle='-', marker='', 
     
    449455                                        linestyle='-', marker='', 
    450456                                        color=self.color, visible=True)[0] 
    451         # # Flag to determine if the lines have moved 
     457        # Flag to determine if the lines have moved 
    452458        self.has_move = False 
    453         # # connection the marker and draw the pictures 
     459        # Connection the marker and draw the pictures 
    454460        self.connect_markers([self.right_marker]) 
    455461        self.update() 
    456462 
    457     def set_layer(self, n): 
     463    def setLayer(self, n): 
    458464        """ 
    459465        Allow adding plot to the same panel 
     
    468474        """ 
    469475        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() 
    478479 
    479480    def update(self, x1=None, x2=None, y1=None, y2=None, width=None, 
     
    489490        :param center: provided x, y  coordinates of the center point 
    490491        """ 
    491         # # save the new height, witdh of the rectangle if given as a param 
    492         if width != None: 
     492        # Save the new height, witdh of the rectangle if given as a param 
     493        if width is not None: 
    493494            self.half_width = width 
    494         if height != None: 
     495        if height is not None: 
    495496            self.half_height = height 
    496         # # If new  center coordinates are given draw the rectangle 
    497         # #given these value 
    498         if center != None: 
     497        # If new  center coordinates are given draw the rectangle 
     498        # given these value 
     499        if center is not None: 
    499500            self.center_x = center.x 
    500501            self.center_y = center.y 
     
    510511                               ydata=[self.y1, self.y2]) 
    511512            return 
    512         # # if x1, y1, y2, y3 are given draw the rectangle with this value 
    513         if x1 != None: 
     513        # if x1, y1, y2, y3 are given draw the rectangle with this value 
     514        if x1 is not None: 
    514515            self.x1 = x1 
    515         if x2 != None: 
     516        if x2 is not None: 
    516517            self.x2 = x2 
    517         if y1 != None: 
     518        if y1 is not None: 
    518519            self.y1 = y1 
    519         if y2 != None: 
     520        if y2 is not None: 
    520521            self.y2 = y2 
    521         # # Draw 2 vertical lines and a marker 
     522        # Draw 2 vertical lines and a marker 
    522523        self.right_marker.set(xdata=[self.x1], ydata=[self.center_y]) 
    523524        self.right_line.set(xdata=[self.x1, self.x1], ydata=[self.y1, self.y2]) 
     
    535536        self.save_half_height = self.half_height 
    536537        self.save_half_width = self.half_width 
    537         self.base.freeze_axes() 
    538538 
    539539    def moveend(self, ev): 
    540540        """ 
    541             After a dragging motion reset the flag self.has_move to False 
     541        After a dragging motion reset the flag self.has_move to False 
    542542        """ 
    543543        self.has_move = False 
     
    562562        delta = self.x1 - self.center_x 
    563563        self.x2 = self.center_x - delta 
    564         self.half_width = math.fabs(self.x1 - self.x2) / 2 
     564        self.half_width = numpy.fabs(self.x1 - self.x2) / 2 
    565565        self.has_move = True 
    566566        self.base.base.update() 
    567567 
    568     def set_cursor(self, x, y): 
    569         """ 
    570             Update the figure given x and y 
     568    def setCursor(self, x, y): 
     569        """ 
     570        Update the figure given x and y 
    571571        """ 
    572572        self.move(x, y, None) 
     
    575575class HorizontalDoubleLine(_BaseInteractor): 
    576576    """ 
    577          Select an annulus through a 2D plot 
     577    Select an annulus through a 2D plot 
    578578    """ 
    579579    def __init__(self, base, axes, color='black', zorder=5, x=0.5, y=0.5, 
     
    581581 
    582582        _BaseInteractor.__init__(self, base, axes, color=color) 
    583         # # Initialization the class 
     583        # Initialization the class 
    584584        self.markers = [] 
    585585        self.axes = axes 
    586         # # Center coordinates 
     586        # Center coordinates 
    587587        self.center_x = center_x 
    588588        self.center_y = center_y 
     
    598598        self.save_x2 = self.x2 
    599599        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) 
    604604        self.top_marker = self.axes.plot([0], [self.y1], linestyle='', 
    605605                                         marker='s', markersize=10, 
     
    616616                                          linestyle='-', marker='', 
    617617                                          color=self.color, visible=True)[0] 
    618         # # Flag to determine if the lines have moved 
     618        # Flag to determine if the lines have moved 
    619619        self.has_move = False 
    620         # # connection the marker and draw the pictures 
     620        # connection the marker and draw the pictures 
    621621        self.connect_markers([self.top_marker]) 
    622622        self.update() 
    623623 
    624     def set_layer(self, n): 
    625         """ 
    626             Allow adding plot to the same panel 
    627             @param n: the number of layer 
     624    def setLayer(self, n): 
     625        """ 
     626        Allow adding plot to the same panel 
     627        @param n: the number of layer 
    628628        """ 
    629629        self.layernum = n 
     
    632632    def clear(self): 
    633633        """ 
    634             Clear this figure and its markers 
     634        Clear this figure and its markers 
    635635        """ 
    636636        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() 
    645640 
    646641    def update(self, x1=None, x2=None, y1=None, y2=None, 
     
    656651        :param center: provided x, y  coordinates of the center point 
    657652        """ 
    658         # # save the new height, witdh of the rectangle if given as a param 
    659         if width != None: 
     653        # Save the new height, witdh of the rectangle if given as a param 
     654        if width is not None: 
    660655            self.half_width = width 
    661         if height != None: 
     656        if height is not None: 
    662657            self.half_height = height 
    663         # # If new  center coordinates are given draw the rectangle 
    664         # #given these value 
    665         if center != None: 
     658        # If new  center coordinates are given draw the rectangle 
     659        # given these value 
     660        if center is not None: 
    666661            self.center_x = center.x 
    667662            self.center_y = center.y 
     
    678673                                 ydata=[self.y2, self.y2]) 
    679674            return 
    680         # # if x1, y1, y2, y3 are given draw the rectangle with this value 
    681         if x1 != None: 
     675        # if x1, y1, y2, y3 are given draw the rectangle with this value 
     676        if x1 is not None: 
    682677            self.x1 = x1 
    683         if x2 != None: 
     678        if x2 is not None: 
    684679            self.x2 = x2 
    685         if y1 != None: 
     680        if y1 is not None: 
    686681            self.y1 = y1 
    687         if y2 != None: 
     682        if y2 is not None: 
    688683            self.y2 = y2 
    689         # # Draw 2 vertical lines and a marker 
     684        # Draw 2 vertical lines and a marker 
    690685        self.top_marker.set(xdata=[self.center_x], ydata=[self.y1]) 
    691686        self.top_line.set(xdata=[self.x1, self.x2], ydata=[self.y1, self.y1]) 
     
    703698        self.save_half_height = self.half_height 
    704699        self.save_half_width = self.half_width 
    705         self.base.freeze_axes() 
    706700 
    707701    def moveend(self, ev): 
     
    730724        delta = self.y1 - self.center_y 
    731725        self.y2 = self.center_y - delta 
    732         self.half_height = math.fabs(self.y1) - self.center_y 
     726        self.half_height = numpy.fabs(self.y1) - self.center_y 
    733727        self.has_move = True 
    734728        self.base.base.update() 
    735729 
    736     def set_cursor(self, x, y): 
    737         """ 
    738             Update the figure given x and y 
     730    def setCursor(self, x, y): 
     731        """ 
     732        Update the figure given x and y 
    739733        """ 
    740734        self.move(x, y, None) 
Note: See TracChangeset for help on using the changeset viewer.