Changeset 57b7ee2 in sasview


Ignore:
Timestamp:
Feb 9, 2017 8:07:05 AM (2 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:
9a05a8d5
Parents:
bda1faa7
Message:

Code review changes for Slicer Parameter Editor

Location:
src/sas
Files:
7 edited

Legend:

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

    r3bdbfcc r57b7ee2  
    2626from UnitTesting import BoxSumTest 
    2727from UnitTesting import SlicerModelTest 
     28from UnitTesting import SlicerParametersTest 
    2829 
    2930def suite(): 
     
    5455        unittest.makeSuite(BoxSumTest.BoxSumTest, 'test'), 
    5556        unittest.makeSuite(SlicerModelTest.SlicerModelTest, 'test'), 
     57        unittest.makeSuite(SlicerParametersTest.SlicerParametersTest, 'test'), 
    5658    ) 
    5759    return unittest.TestSuite(suites) 
  • src/sas/qtgui/Plotter2D.py

    rb789967 r57b7ee2  
    4545        # Reference to the current slicer 
    4646        self.slicer = None 
     47        self.slicer_widget = None 
    4748        # Create Artist and bind it 
    4849        self.connect = BindArtist(self.figure) 
     
    160161            self.actionClearSlicer = self.contextMenu.addAction("&Clear Slicer") 
    161162            self.actionClearSlicer.triggered.connect(self.onClearSlicer) 
    162             self.actionEditSlicer = self.contextMenu.addAction("&Edit Slicer Parameters") 
    163             self.actionEditSlicer.triggered.connect(self.onEditSlicer) 
     163            if self.slicer.__class__.__name__ != "BoxSumCalculator": 
     164                self.actionEditSlicer = self.contextMenu.addAction("&Edit Slicer Parameters") 
     165                self.actionEditSlicer.triggered.connect(self.onEditSlicer) 
    164166        self.contextMenu.addSeparator() 
    165167        self.actionColorMap = self.contextMenu.addAction("&2D Color Map") 
     
    213215        """ 
    214216        assert self.slicer 
     217        # Only show the dialog if not currently shown 
     218        if self.slicer_widget: 
     219            return 
     220        def slicer_closed(): 
     221            # Need to disconnect the signal!! 
     222            self.slicer_widget.close_signal.disconnect() 
     223            # reset slicer_widget on "Edit Slicer Parameters" window close 
     224            self.slicer_widget = None 
    215225 
    216226        self.param_model = self.slicer.model() 
    217          # Pass the model to the Slicer Parameters widget 
     227        # Pass the model to the Slicer Parameters widget 
    218228        self.slicer_widget = SlicerParameters(self, model=self.param_model) 
    219         self.manager.parent.workspace().addWindow(self.slicer_widget) 
     229        self.slicer_widget.close_signal.connect(slicer_closed) 
    220230 
    221231        self.slicer_widget.show() 
     
    283293        self.slicer.update() 
    284294 
     295        # Reset the model on the Edit slicer parameters widget 
     296        self.param_model = self.slicer.model() 
     297        if self.slicer_widget: 
     298            self.slicer_widget.setModel(self.param_model) 
     299 
     300 
    285301    def onSectorView(self): 
    286302        """ 
     
    288304        """ 
    289305        self.setSlicer(slicer=SectorInteractor) 
     306 
    290307 
    291308    def onAnnulusView(self): 
  • src/sas/qtgui/SlicerParameters.py

    rb789967 r57b7ee2  
    22Allows users to modify the box slicer parameters. 
    33""" 
     4import functools 
    45from PyQt4 import QtGui 
    56from PyQt4 import QtCore 
     7from PyQt4 import QtWebKit 
    68 
    79# Local UI 
     
    1315    passed from a slicer instance. 
    1416    """ 
     17    close_signal = QtCore.pyqtSignal() 
    1518    def __init__(self, parent=None, model=None): 
    1619        super(SlicerParameters, self).__init__() 
     
    3134        self.lstParams.model().setColumnReadOnly(0, True) 
    3235 
     36        # Specify the validator on the parameter value column. 
     37        self.lstParams.setItemDelegate(ValidatedItemDelegate()) 
     38 
     39        # Display Help on clicking the button 
     40        self.buttonBox.button(QtGui.QDialogButtonBox.Help).clicked.connect(self.onHelp) 
     41 
     42        # Close doesn't trigger closeEvent automatically, so force it 
     43        self.buttonBox.button(QtGui.QDialogButtonBox.Close).clicked.connect(functools.partial(self.closeEvent,None)) 
     44 
    3345        # Disable row number display 
    3446        self.lstParams.verticalHeader().setVisible(False) 
     47        self.lstParams.setAlternatingRowColors(True) 
     48        self.lstParams.setSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Expanding) 
    3549 
    36         # Specify the validator on the parameter value column. 
    37         self.lstParams.setItemDelegate(ValidatedItemDelegate()) 
     50        # Header properties for nicer display 
     51        header = self.lstParams.horizontalHeader() 
     52        header.setResizeMode(QtGui.QHeaderView.Stretch) 
     53        header.setStretchLastSection(True) 
     54 
     55 
     56    def setModel(self, model): 
     57        """ Model setter """ 
     58        self.model = model 
     59        self.proxy.setSourceModel(self.model) 
     60 
     61    def closeEvent(self, event): 
     62        """ 
     63        Overwritten close widget method in order to send the close 
     64        signal to the parent. 
     65        """ 
     66        self.close_signal.emit() 
     67        if event: 
     68            event.accept() 
     69 
     70    def onHelp(self): 
     71        """ 
     72        Display generic data averaging help 
     73        """ 
     74        location = "docs/sphinx-docs/build/html" + \ 
     75            "/user/sasgui/guiframe/graph_help.html#d-data-averaging" 
     76        self._helpView = QtWebKit.QWebView() 
     77        self._helpView.load(QtCore.QUrl(location)) 
     78        self._helpView.show() 
     79 
    3880 
    3981class ProxyModel(QtGui.QIdentityProxyModel): 
  • src/sas/qtgui/UI/SlicerParametersUI.ui

    r3bdbfcc r57b7ee2  
    2828    <widget class="QTableView" name="lstParams"/> 
    2929   </item> 
    30    <item row="1" column="0"> 
    31     <spacer name="verticalSpacer"> 
    32      <property name="orientation"> 
    33       <enum>Qt::Vertical</enum> 
    34      </property> 
    35      <property name="sizeHint" stdset="0"> 
    36       <size> 
    37        <width>20</width> 
    38        <height>21</height> 
    39       </size> 
    40      </property> 
    41     </spacer> 
    42    </item> 
    43    <item row="2" column="1"> 
     30   <item row="1" column="1"> 
    4431    <widget class="QDialogButtonBox" name="buttonBox"> 
    4532     <property name="orientation"> 
     
    4734     </property> 
    4835     <property name="standardButtons"> 
    49       <set>QDialogButtonBox::Ok</set> 
     36      <set>QDialogButtonBox::Close|QDialogButtonBox::Help</set> 
    5037     </property> 
    5138    </widget> 
  • src/sas/qtgui/run_tests.bat

    • Property mode changed from 100755 to 100644
    r965fbd8 r57b7ee2  
    2525python -m UnitTesting.BoxSumTest 
    2626python -m UnitTesting.SlicerModelTest 
     27python -m UnitTesting.SlicerParametersTest 
  • src/sas/qtgui/run_tests.sh

    r3bdbfcc r57b7ee2  
    2424python -m UnitTesting.BoxSumTest 
    2525python -m UnitTesting.SlicerModelTest 
     26python -m UnitTesting.SlicerParametersTest 
  • src/sas/sasgui/guiframe/local_perspectives/plotting/SectorSlicer.py

    r3bdbfcc r57b7ee2  
    22    Sector interactor 
    33""" 
    4 import math 
     4import numpy 
    55from PyQt4 import QtGui 
    66from PyQt4 import QtCore 
     
    1111from sas.qtgui.SlicerModel import SlicerModel 
    1212 
     13MIN_PHI = 0.05 
    1314 
    1415class SectorInteractor(_BaseInteractor, SlicerModel): 
     
    2829 
    2930        # 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) 
    34         self.qmax = math.sqrt(x + y) 
     31        x = numpy.power(max(self.base.data.xmax, 
     32                         numpy.fabs(self.base.data.xmin)), 2) 
     33        y = numpy.power(max(self.base.data.ymax, 
     34                         numpy.fabs(self.base.data.ymin)), 2) 
     35        self.qmax = numpy.sqrt(x + y) 
    3536        # Number of points on the plot 
    3637        self.nbins = 20 
    3738        # Angle of the middle line 
    38         self.theta2 = math.pi / 3 
     39        self.theta2 = numpy.pi / 3 
    3940        # Absolute value of the Angle between the middle line and any side line 
    40         self.phi = math.pi / 12 
     41        self.phi = numpy.pi / 12 
    4142        # Middle line 
    4243        self.main_line = LineInteractor(self, self.axes, color='blue', 
     
    135136            nbins = 20 
    136137        sect = SectorQ(r_min=0.0, r_max=radius, 
    137                        phi_min=phimin + math.pi, 
    138                        phi_max=phimax + math.pi, nbins=nbins) 
     138                       phi_min=phimin + numpy.pi, 
     139                       phi_max=phimax + numpy.pi, nbins=nbins) 
    139140 
    140141        sector = sect(self.base.data) 
     
    209210        # Always make sure that the left and the right line are at phi 
    210211        # angle of the middle line 
    211         if math.fabs(self.left_line.phi) != math.fabs(self.right_line.phi): 
     212        if numpy.fabs(self.left_line.phi) != numpy.fabs(self.right_line.phi): 
    212213            msg = "Phi left and phi right are different" 
    213214            msg += " %f, %f" % (self.left_line.phi, self.right_line.phi) 
    214215            raise ValueError, msg 
    215         params["Phi [deg]"] = self.main_line.theta * 180 / math.pi 
    216         params["Delta_Phi [deg]"] = math.fabs(self.left_line.phi * 180 / math.pi) 
     216        params["Phi [deg]"] = self.main_line.theta * 180 / numpy.pi 
     217        params["Delta_Phi [deg]"] = numpy.fabs(self.left_line.phi * 180 / numpy.pi) 
    217218        params["nbins"] = self.nbins 
    218219        return params 
     
    226227            values the user assigned to the slicer. 
    227228        """ 
    228         main = params["Phi [deg]"] * math.pi / 180 
    229         phi = math.fabs(params["Delta_Phi [deg]"] * math.pi / 180) 
     229        main = params["Phi [deg]"] * numpy.pi / 180 
     230        phi = numpy.fabs(params["Delta_Phi [deg]"] * numpy.pi / 180) 
     231 
     232        # phi should not be too close. 
     233        if numpy.fabs(phi) < MIN_PHI: 
     234            phi = MIN_PHI 
     235            params["Delta_Phi [deg]"] = MIN_PHI 
     236 
    230237        self.nbins = int(params["nbins"]) 
    231238        self.main_line.theta = main 
     
    241248    def draw(self): 
    242249        """ 
     250        Redraw canvas 
    243251        """ 
    244252        self.base.draw() 
     
    254262    """ 
    255263    def __init__(self, base, axes, color='black', zorder=5, r=1.0, 
    256                  phi=math.pi / 4, theta2=math.pi / 3): 
     264                 phi=numpy.pi / 4, theta2=numpy.pi / 3): 
    257265        """ 
    258266        """ 
     
    272280        self.phi = phi 
    273281        # End points polar coordinates 
    274         x1 = self.radius * math.cos(self.theta) 
    275         y1 = self.radius * math.sin(self.theta) 
    276         x2 = -1 * self.radius * math.cos(self.theta) 
    277         y2 = -1 * self.radius * math.sin(self.theta) 
     282        x1 = self.radius * numpy.cos(self.theta) 
     283        y1 = self.radius * numpy.sin(self.theta) 
     284        x2 = -1 * self.radius * numpy.cos(self.theta) 
     285        y2 = -1 * self.radius * numpy.sin(self.theta) 
    278286        # Defining a new marker 
    279287        self.inner_marker = self.axes.plot([x1 / 2.5], [y1 / 2.5], linestyle='', 
     
    331339            delta = 0 
    332340        if  right: 
    333             self.phi = -1 * math.fabs(self.phi) 
     341            self.phi = -1 * numpy.fabs(self.phi) 
    334342            #delta=-delta 
    335343        else: 
    336             self.phi = math.fabs(self.phi) 
     344            self.phi = numpy.fabs(self.phi) 
    337345        if side: 
    338346            self.theta = mline.theta + self.phi 
     
    347355        else: 
    348356            theta3 = self.theta2 + delta 
    349         x1 = self.radius * math.cos(theta3) 
    350         y1 = self.radius * math.sin(theta3) 
    351         x2 = -1 * self.radius * math.cos(theta3) 
    352         y2 = -1 * self.radius * math.sin(theta3) 
     357        x1 = self.radius * numpy.cos(theta3) 
     358        y1 = self.radius * numpy.sin(theta3) 
     359        x2 = -1 * self.radius * numpy.cos(theta3) 
     360        y2 = -1 * self.radius * numpy.sin(theta3) 
    353361        self.inner_marker.set(xdata=[x1 / 2.5], ydata=[y1 / 2.5]) 
    354362        self.line.set(xdata=[x1, x2], ydata=[y1, y2]) 
     
    377385        Process move to a new position, making sure that the move is allowed. 
    378386        """ 
    379         self.theta = math.atan2(y, x) 
     387        self.theta = numpy.arctan2(y, x) 
    380388        self.has_move = True 
    381389        if not self.left_moving: 
     
    388396                return 
    389397            elif  self.theta2 < 0 and self.theta > 0 and \ 
    390                 (self.theta2 + 2 * math.pi - self.theta) >= math.pi / 2: 
     398                (self.theta2 + 2 * numpy.pi - self.theta) >= numpy.pi / 2: 
    391399                self.restore() 
    392400                return 
    393401            elif  self.theta2 < 0 and self.theta < 0 and \ 
    394                 (self.theta2 - self.theta) >= math.pi / 2: 
    395                 self.restore() 
    396                 return 
    397             elif self.theta2 > 0 and (self.theta2 - self.theta >= math.pi / 2 or \ 
    398                 (self.theta2 - self.theta >= math.pi / 2)): 
     402                (self.theta2 - self.theta) >= numpy.pi / 2: 
     403                self.restore() 
     404                return 
     405            elif self.theta2 > 0 and (self.theta2 - self.theta >= numpy.pi / 2 or \ 
     406                (self.theta2 - self.theta >= numpy.pi / 2)): 
    399407                self.restore() 
    400408                return 
    401409        else: 
    402             if  self.theta < 0 and (self.theta + math.pi * 2 - self.theta2) <= 0: 
     410            if  self.theta < 0 and (self.theta + numpy.pi * 2 - self.theta2) <= 0: 
    403411                self.restore() 
    404412                return 
     
    409417                self.restore() 
    410418                return 
    411             elif self.theta - self.theta2 >= math.pi / 2 or  \ 
    412                 ((self.theta + math.pi * 2 - self.theta2) >= math.pi / 2 and \ 
     419            elif self.theta - self.theta2 >= numpy.pi / 2 or  \ 
     420                ((self.theta + numpy.pi * 2 - self.theta2) >= numpy.pi / 2 and \ 
    413421                 self.theta < 0 and self.theta2 > 0): 
    414422                self.restore() 
    415423                return 
    416424 
    417         self.phi = math.fabs(self.theta2 - self.theta) 
    418         if self.phi > math.pi: 
    419             self.phi = 2 * math.pi - math.fabs(self.theta2 - self.theta) 
     425        self.phi = numpy.fabs(self.theta2 - self.theta) 
     426        if self.phi > numpy.pi: 
     427            self.phi = 2 * numpy.pi - numpy.fabs(self.theta2 - self.theta) 
    420428        self.base.base.update() 
    421429 
     
    446454    """ 
    447455    def __init__(self, base, axes, color='black', 
    448                  zorder=5, r=1.0, theta=math.pi / 4): 
     456                 zorder=5, r=1.0, theta=numpy.pi / 4): 
    449457        """ 
    450458        """ 
     
    458466        self.scale = 10.0 
    459467        # Inner circle 
    460         x1 = self.radius * math.cos(self.theta) 
    461         y1 = self.radius * math.sin(self.theta) 
    462         x2 = -1 * self.radius * math.cos(self.theta) 
    463         y2 = -1 * self.radius * math.sin(self.theta) 
     468        x1 = self.radius * numpy.cos(self.theta) 
     469        y1 = self.radius * numpy.sin(self.theta) 
     470        x2 = -1 * self.radius * numpy.cos(self.theta) 
     471        y2 = -1 * self.radius * numpy.sin(self.theta) 
    464472        # Inner circle marker 
    465473        self.inner_marker = self.axes.plot([x1 / 2.5], [y1 / 2.5], linestyle='', 
     
    502510        if theta != None: 
    503511            self.theta = theta 
    504         x1 = self.radius * math.cos(self.theta) 
    505         y1 = self.radius * math.sin(self.theta) 
    506         x2 = -1 * self.radius * math.cos(self.theta) 
    507         y2 = -1 * self.radius * math.sin(self.theta) 
     512        x1 = self.radius * numpy.cos(self.theta) 
     513        y1 = self.radius * numpy.sin(self.theta) 
     514        x2 = -1 * self.radius * numpy.cos(self.theta) 
     515        y2 = -1 * self.radius * numpy.sin(self.theta) 
    508516 
    509517        self.inner_marker.set(xdata=[x1 / 2.5], ydata=[y1 / 2.5]) 
     
    533541        Process move to a new position, making sure that the move is allowed. 
    534542        """ 
    535         self.theta = math.atan2(y, x) 
     543        self.theta = numpy.arctan2(y, x) 
    536544        self.has_move = True 
    537545        self.base.base.update() 
Note: See TracChangeset for help on using the changeset viewer.