Changeset e2451f2 in sasview


Ignore:
Timestamp:
Sep 14, 2018 5:21:00 AM (6 years ago)
Author:
wojciech
Branches:
ESS_GUI, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc
Children:
14ec7dfd
Parents:
3c4f02e (diff), 86d3207 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'ESS_GUI' of https://github.com/SasView/sasview into ESS_GUI_Pr_fixes

Location:
src/sas
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • src/sas/qtgui/MainWindow/GuiManager.py

    r5b144c6 r768387e0  
    118118        self.dockedFilesWidget.setWidget(self.filesWidget) 
    119119 
    120         # Disable maximize/minimize and close buttons 
    121         self.dockedFilesWidget.setFeatures(QDockWidget.NoDockWidgetFeatures) 
    122  
    123         #self._workspace.workspace.addDockWidget(Qt.LeftDockWidgetArea, self.dockedFilesWidget) 
     120        # Modify menu items on widget visibility change 
     121        self.dockedFilesWidget.visibilityChanged.connect(self.updateContextMenus) 
     122 
    124123        self._workspace.addDockWidget(Qt.LeftDockWidgetArea, self.dockedFilesWidget) 
    125124        self._workspace.resizeDocks([self.dockedFilesWidget], [305], Qt.Horizontal) 
     
    164163            logger.error("%s: could not load SasView models") 
    165164            logger.error(traceback.format_exc()) 
     165 
     166    def updateContextMenus(self, visible=False): 
     167        """ 
     168        Modify the View/Data Explorer menu item text on widget visibility 
     169        """ 
     170        if visible: 
     171            self._workspace.actionHide_DataExplorer.setText("Hide Data Explorer") 
     172        else: 
     173            self._workspace.actionHide_DataExplorer.setText("Show Data Explorer") 
    166174 
    167175    def statusBarSetup(self): 
     
    427435        self._workspace.actionStartup_Settings.triggered.connect(self.actionStartup_Settings) 
    428436        self._workspace.actionCategory_Manager.triggered.connect(self.actionCategory_Manager) 
     437        self._workspace.actionHide_DataExplorer.triggered.connect(self.actionHide_DataExplorer) 
    429438        # Tools 
    430439        self._workspace.actionData_Operation.triggered.connect(self.actionData_Operation) 
     
    617626        pass 
    618627 
     628    def actionHide_DataExplorer(self): 
     629        """ 
     630        Toggle Data Explorer vsibility 
     631        """ 
     632        if self.dockedFilesWidget.isVisible(): 
     633            #self._workspace.actionHide_DataExplorer.setText("Show Data Explorer") 
     634            self.dockedFilesWidget.setVisible(False) 
     635        else: 
     636            #self._workspace.actionHide_DataExplorer.setText("Hide Data Explorer") 
     637            self.dockedFilesWidget.setVisible(True) 
     638        pass 
     639 
    619640    def actionStartup_Settings(self): 
    620641        """ 
  • src/sas/qtgui/MainWindow/UI/MainWindowUI.ui

    r33b3e4d r768387e0  
    7474    <addaction name="separator"/> 
    7575    <addaction name="actionHide_Toolbar"/> 
     76    <addaction name="actionHide_DataExplorer"/> 
    7677    <addaction name="separator"/> 
    7778    <addaction name="actionStartup_Settings"/> 
     
    552553   </property> 
    553554  </action> 
     555  <action name="actionHide_DataExplorer"> 
     556   <property name="text"> 
     557    <string>Hide Data Explorer</string> 
     558   </property> 
     559  </action> 
    554560 </widget> 
    555561 <resources/> 
  • src/sas/qtgui/MainWindow/UnitTesting/GuiManagerTest.py

    r144fe21 r768387e0  
    5353        self.assertIsInstance(self.manager.dockedFilesWidget, QDockWidget) 
    5454        self.assertIsInstance(self.manager.dockedFilesWidget.widget(), DataExplorerWindow) 
    55         self.assertEqual(self.manager.dockedFilesWidget.features(), QDockWidget.NoDockWidgetFeatures) 
    5655        self.assertEqual(self.manager._workspace.dockWidgetArea(self.manager.dockedFilesWidget), Qt.LeftDockWidgetArea) 
    5756 
  • src/sas/qtgui/Perspectives/Fitting/FittingWidget.py

    r557fc498 r86d3207  
    2828from sas.qtgui.Plotting.PlotterData import Data1D 
    2929from sas.qtgui.Plotting.PlotterData import Data2D 
     30from sas.qtgui.Plotting.Plotter import PlotterWidget 
    3031 
    3132from sas.qtgui.Perspectives.Fitting.UI.FittingWidgetUI import Ui_FittingWidgetUI 
     
    28252826        item4 = QtGui.QStandardItem() 
    28262827 
    2827         self._model_model.appendRow([item1, item2, item3, item4]) 
     2828        # cell 4: SLD button 
     2829        item5 = QtGui.QStandardItem() 
     2830        button = QtWidgets.QPushButton() 
     2831        button.setText("Show SLD Profile") 
     2832 
     2833        self._model_model.appendRow([item1, item2, item3, item4, item5]) 
    28282834 
    28292835        # Beautify the row:  span columns 2-4 
    28302836        shell_row = self._model_model.rowCount() 
    28312837        shell_index = self._model_model.index(shell_row-1, 1) 
     2838        button_index = self._model_model.index(shell_row-1, 4) 
    28322839 
    28332840        self.lstParams.setIndexWidget(shell_index, func) 
     2841        self.lstParams.setIndexWidget(button_index, button) 
    28342842        self._n_shells_row = shell_row - 1 
    28352843 
     
    28582866        func.currentTextChanged.connect(self.modifyShellsInList) 
    28592867 
     2868        # Respond to button press 
     2869        button.clicked.connect(self.onShowSLDProfile) 
     2870 
    28602871        # Available range of shells displayed in the combobox 
    28612872        func.addItems([str(i) for i in range(shell_min, shell_max+1)]) 
     
    28772888            index = 0 
    28782889            logger.error("Multiplicity incorrect! Setting to 0") 
    2879  
     2890        self.kernel_module.multiplicity = index 
    28802891        if remove_rows > 1: 
    28812892            self._model_model.removeRows(first_row, remove_rows) 
     
    29032914        self.setPolyModel() 
    29042915        self.setMagneticModel() 
     2916 
     2917    def onShowSLDProfile(self): 
     2918        """ 
     2919        Show a quick plot of SLD profile 
     2920        """ 
     2921        # get profile data 
     2922        x, y = self.kernel_module.getProfile() 
     2923        y *= 1.0e6 
     2924        profile_data = Data1D(x=x, y=y) 
     2925        profile_data.name = "SLD" 
     2926        profile_data.scale = 'linear' 
     2927        profile_data.symbol = 'Line' 
     2928        profile_data.hide_error = True 
     2929        profile_data._xaxis = "R(\AA)" 
     2930        profile_data._yaxis = "SLD(10^{-6}\AA^{-2})" 
     2931 
     2932        plotter = PlotterWidget(self, quickplot=True) 
     2933        plotter.data = profile_data 
     2934        plotter.showLegend = True 
     2935        plotter.plot(hide_error=True, marker='-') 
     2936 
     2937        self.plot_widget = QtWidgets.QWidget() 
     2938        self.plot_widget.setWindowTitle("Scattering Length Density Profile") 
     2939        layout = QtWidgets.QVBoxLayout() 
     2940        layout.addWidget(plotter) 
     2941        self.plot_widget.setLayout(layout) 
     2942        self.plot_widget.show() 
    29052943 
    29062944    def setInteractiveElements(self, enabled=True): 
  • src/sas/qtgui/Perspectives/Inversion/DMaxExplorerWidget.py

    rb0ba43e r9f2f713  
    4242        self.parent = parent 
    4343 
    44         self.setWindowTitle("Dₐₓ Explorer") 
     44        self.setWindowTitle("Dmax Explorer") 
    4545 
    4646        self.pr_state = pr_state 
     
    116116        bck = [] 
    117117        chi2 = [] 
    118  
     118        plotable_xs = [] #Introducing this to make sure size of x and y for plotting is the same.8 
    119119        try: 
    120120            dmin = float(self.model.item(W.DMIN).text()) 
     
    128128 
    129129        original = self.pr_state.d_max 
     130 
    130131        for x in xs: 
    131132            self.pr_state.d_max = x 
     
    140141                bck.append(self.pr_state.background) 
    141142                chi2.append(self.pr_state.chi2) 
     143                plotable_xs.append(x) 
    142144            except Exception as ex: 
    143145                # This inversion failed, skip this D_max value 
     
    155157            logger.error(msg) 
    156158 
    157         plotter = self.model.item(W.VARIABLE).text() 
    158         y_label = y_unit = "" 
     159        plotter = self.dependentVariable.currentText() 
    159160        x_label = "D_{max}" 
    160161        x_unit = "A" 
     
    188189            y_unit = "a.u." 
    189190 
    190         data = Data1D(xs, ys) 
     191        data = Data1D(plotable_xs, ys) 
    191192        if self.hasPlot: 
    192             self.plot.removePlot(None) 
     193            self.plot.removePlot(data.name) 
    193194        self.hasPlot = True 
    194195        data.title = plotter 
  • src/sas/qtgui/Perspectives/Inversion/InversionLogic.py

    r6da860a r3c4f02e  
    111111            new_plot.title = title 
    112112 
     113        new_plot.symbol = 'Line' 
     114        new_plot.hide_error = True 
     115 
    113116        return new_plot 
    114117 
  • src/sas/qtgui/Perspectives/Inversion/InversionPerspective.py

    r855e7ad r4b7d322  
    4444    estimateSignal = QtCore.pyqtSignal(tuple) 
    4545    estimateNTSignal = QtCore.pyqtSignal(tuple) 
     46    estimateDynamicNTSignal = QtCore.pyqtSignal(tuple) 
     47    estimateDynamicSignal = QtCore.pyqtSignal(tuple) 
    4648    calculateSignal = QtCore.pyqtSignal(tuple) 
    4749 
     
    195197        self.model.itemChanged.connect(self.model_changed) 
    196198        self.estimateNTSignal.connect(self._estimateNTUpdate) 
     199        self.estimateDynamicNTSignal.connect(self._estimateDynamicNTUpdate) 
     200        self.estimateDynamicSignal.connect(self._estimateDynamicUpdate) 
    197201        self.estimateSignal.connect(self._estimateUpdate) 
    198202        self.calculateSignal.connect(self._calculateUpdate) 
     203 
     204        self.maxDistanceInput.textEdited.connect(self.performEstimateDynamic) 
    199205 
    200206    def setupMapper(self): 
     
    310316                                            and not self.isCalculating) 
    311317        self.removeButton.setEnabled(self.logic.data_is_loaded) 
    312         self.explorerButton.setEnabled(self.logic.data_is_loaded 
    313                                        and np.all(self.logic.data.dy != 0)) 
     318        self.explorerButton.setEnabled(self.logic.data_is_loaded) 
    314319        self.stopButton.setVisible(self.isCalculating) 
    315320        self.regConstantSuggestionButton.setEnabled( 
     
    458463            self._calculator.set_qmin(qmin) 
    459464            self._calculator.set_qmax(qmax) 
     465            if np.size(self.logic.data.dy) == 0 or np.all(self.logic.data.dy) == 0: 
     466                self.logic.data.dy = self._calculator.add_errors(self.logic.data.y) 
    460467            self.updateDataList(data) 
    461468            self.populateDataComboBox(self.logic.data.filename, data) 
     
    502509        self.dataPlot = self._dataList[data_ref].get(DICT_KEYS[2]) 
    503510        self.performEstimate() 
     511 
     512    def updateDynamicGuiValues(self): 
     513        pr = self._calculator 
     514        alpha = self._calculator.suggested_alpha 
     515        self.model.setItem(WIDGETS.W_MAX_DIST, 
     516                            QtGui.QStandardItem("{:.4g}".format(pr.get_dmax()))) 
     517        self.regConstantSuggestionButton.setText("{:-3.2g}".format(alpha)) 
     518        self.noOfTermsSuggestionButton.setText( 
     519             "{:n}".format(self.nTermsSuggested)) 
     520 
     521        self.enableButtons() 
    504522 
    505523    def updateGuiValues(self): 
     
    521539        self.model.setItem(WIDGETS.W_MAX_DIST, 
    522540                           QtGui.QStandardItem("{:.4g}".format(pr.get_dmax()))) 
    523         self.regConstantSuggestionButton.setText("{:-3.2g}".format(alpha)) 
    524         self.noOfTermsSuggestionButton.setText( 
    525             "{:n}".format(self.nTermsSuggested)) 
    526541 
    527542        if isinstance(pr.chi2, np.ndarray): 
     
    674689        self.estimationThreadNT.ready(2.5) 
    675690 
     691    def performEstimateDynamicNT(self): 
     692        """ 
     693        Perform parameter estimation 
     694        """ 
     695        from .Thread import EstimateNT 
     696 
     697        self.updateCalculator() 
     698 
     699        # If a thread is already started, stop it 
     700        self.stopEstimateNTThread() 
     701 
     702        pr = self._calculator.clone() 
     703        # Skip the slit settings for the estimation 
     704        # It slows down the application and it doesn't change the estimates 
     705        pr.slit_height = 0.0 
     706        pr.slit_width = 0.0 
     707        nfunc = self.getNFunc() 
     708 
     709        self.estimationThreadNT = EstimateNT(pr, nfunc, 
     710                                             error_func=self._threadError, 
     711                                             completefn=self._estimateDynamicNTCompleted, 
     712                                             updatefn=None) 
     713        self.estimationThreadNT.queue() 
     714        self.estimationThreadNT.ready(2.5) 
     715 
    676716    def stopEstimateNTThread(self): 
    677717        if (self.estimationThreadNT is not None and 
     
    696736        self.estimationThread.ready(2.5) 
    697737 
     738    def performEstimateDynamic(self): 
     739        """ 
     740            Perform parameter estimation 
     741        """ 
     742        from .Thread import EstimatePr 
     743 
     744        # If a thread is already started, stop it 
     745        self.stopEstimationThread() 
     746 
     747        self.estimationThread = EstimatePr(self._calculator.clone(), 
     748                                           self.getNFunc(), 
     749                                           error_func=self._threadError, 
     750                                           completefn=self._estimateDynamicCompleted, 
     751                                           updatefn=None) 
     752        self.estimationThread.queue() 
     753        self.estimationThread.ready(2.5) 
     754 
    698755    def stopEstimationThread(self): 
    699756        """ Stop the estimation thread if it exists and is running """ 
     
    708765        ''' Send a signal to the main thread for model update''' 
    709766        self.estimateSignal.emit((alpha, message, elapsed)) 
     767 
     768    def _estimateDynamicCompleted(self, alpha, message, elapsed): 
     769        ''' Send a signal to the main thread for model update''' 
     770        self.estimateDynamicSignal.emit((alpha, message, elapsed)) 
    710771 
    711772    def _estimateUpdate(self, output_tuple): 
     
    723784            logger.info(message) 
    724785        self.performEstimateNT() 
     786        self.performEstimateDynamicNT() 
     787 
     788    def _estimateDynamicUpdate(self, output_tuple): 
     789        """ 
     790        Parameter estimation completed, 
     791        display the results to the user 
     792 
     793        :param alpha: estimated best alpha 
     794        :param elapsed: computation time 
     795        """ 
     796        alpha, message, elapsed = output_tuple 
     797        self._calculator.alpha = alpha 
     798        self._calculator.elapsed += self._calculator.elapsed 
     799        if message: 
     800            logger.info(message) 
     801        self.performEstimateDynamicNT() 
    725802 
    726803    def _estimateNTCompleted(self, nterms, alpha, message, elapsed): 
    727804        ''' Send a signal to the main thread for model update''' 
    728805        self.estimateNTSignal.emit((nterms, alpha, message, elapsed)) 
     806 
     807    def _estimateDynamicNTCompleted(self, nterms, alpha, message, elapsed): 
     808        ''' Send a signal to the main thread for model update''' 
     809        self.estimateDynamicNTSignal.emit((nterms, alpha, message, elapsed)) 
    729810 
    730811    def _estimateNTUpdate(self, output_tuple): 
     
    750831            self.startThread() 
    751832 
     833    def _estimateDynamicNTUpdate(self, output_tuple): 
     834        """ 
     835        Parameter estimation completed, 
     836        display the results to the user 
     837 
     838        :param alpha: estimated best alpha 
     839        :param nterms: estimated number of terms 
     840        :param elapsed: computation time 
     841        """ 
     842        nterms, alpha, message, elapsed = output_tuple 
     843        self._calculator.elapsed += elapsed 
     844        self._calculator.suggested_alpha = alpha 
     845        self.nTermsSuggested = nterms 
     846        # Save useful info 
     847        self.updateDynamicGuiValues() 
     848        if message: 
     849            logger.info(message) 
     850        if self.isBatch: 
     851            self.acceptAlpha() 
     852            self.acceptNoTerms() 
     853            self.startThread() 
     854 
    752855    def _calculateCompleted(self, out, cov, pr, elapsed): 
    753856        ''' Send a signal to the main thread for model update''' 
  • src/sas/qtgui/Perspectives/Inversion/UI/DMaxExplorer.ui

    r8f83719f rcfd61f2  
    77    <x>0</x> 
    88    <y>0</y> 
    9     <width>394</width> 
    10     <height>426</height> 
     9    <width>586</width> 
     10    <height>538</height> 
    1111   </rect> 
    1212  </property> 
     
    2121       <property name="orientation"> 
    2222        <enum>Qt::Vertical</enum> 
    23        </property> 
    24        <property name="sizeHint" stdset="0"> 
    25         <size> 
    26          <width>20</width> 
    27          <height>305</height> 
    28         </size> 
    2923       </property> 
    3024      </spacer> 
  • src/sas/qtgui/Plotting/Plotter.py

    r5b144c6 rd0952de  
    8484            if self.data.ytransform is None: 
    8585                self.data.ytransform = 'log10(y)' 
    86  
     86            #Added condition to Dmax explorer from P(r) perspective 
     87            if self.data._xaxis == 'D_{max}': 
     88                self.xscale = 'linear' 
    8789            # Transform data if required. 
    8890            if transform and (self.data.xtransform is not None or self.data.ytransform is not None): 
  • src/sas/sascalc/pr/invertor.py

    rb8080e1 reeea6a3  
    7171        A[j][i] = (Fourier transformed base function for point j) 
    7272 
    73     We them choose a number of r-points, n_r, to evaluate the second 
     73    We then choose a number of r-points, n_r, to evaluate the second 
    7474    derivative of P(r) at. This is used as our regularization term. 
    7575    For a vector r of length n_r, the following n_r rows are set to :: 
     
    144144        x, y, err, d_max, q_min, q_max and alpha 
    145145        """ 
    146         if   name == 'x': 
     146        if name == 'x': 
    147147            if 0.0 in value: 
    148148                msg = "Invertor: one of your q-values is zero. " 
     
    227227        return None 
    228228 
     229    def add_errors(self, yvalues): 
     230        """ 
     231        Adds errors to data set is they are not avaialble 
     232        :return: 
     233        """ 
     234        stats_errors = np.zeros(len(yvalues)) 
     235        for i in range(len(yvalues)): 
     236            # Scale the error so that we can fit over several decades of Q 
     237            scale = 0.05 * np.sqrt(yvalues[i]) 
     238            min_err = 0.01 * yvalues[i] 
     239            stats_errors[i] = scale * np.sqrt(np.fabs(yvalues[i])) + min_err 
     240        logger.warning("Simulated errors have been added to the data set\n") 
     241        return stats_errors 
     242 
    229243    def clone(self): 
    230244        """ 
     
    268282            A[i][j] = (Fourier transformed base function for point j) 
    269283 
    270         We them choose a number of r-points, n_r, to evaluate the second 
     284        We then choose a number of r-points, n_r, to evaluate the second 
    271285        derivative of P(r) at. This is used as our regularization term. 
    272286        For a vector r of length n_r, the following n_r rows are set to :: 
Note: See TracChangeset for help on using the changeset viewer.