Changeset 48e55c9 in sasview


Ignore:
Timestamp:
Sep 9, 2018 5:27:05 AM (11 days ago)
Author:
wojciech
Branches:
ESS_GUI, ESS_GUI_Pr_fixes
Children:
28965e9
Parents:
4d959c8 (diff), bb477f5 (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:
11 edited

Legend:

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

    r0cd98a1 r2b8286c  
    9898        self.communicator.maskEditorSignal.connect(self.showEditDataMask) 
    9999        self.communicator.extMaskEditorSignal.connect(self.extShowEditDataMask) 
     100        self.communicator.changeDataExplorerTabSignal.connect(self.changeTabs) 
    100101 
    101102        self.cbgraph.editTextChanged.connect(self.enableGraphCombo) 
     
    139140        else: 
    140141            self.current_view = self.freezeView 
     142 
     143    def changeTabs(self, tab=0): 
     144        """ 
     145        Switch tabs of the data explorer 
     146        0: data tab 
     147        1: theory tab 
     148        """ 
     149        assert(tab in [0,1]) 
     150        self.setCurrentIndex(tab) 
    141151 
    142152    def displayHelp(self): 
     
    553563        return item 
    554564 
    555     def displayFile(self, filename=None, is_data=True): 
     565    def displayFile(self, filename=None, is_data=True, id=None): 
    556566        """ 
    557567        Forces display of charts for the given filename 
     
    560570        # Now query the model item for available plots 
    561571        plots = GuiUtils.plotsFromFilename(filename, model) 
    562  
     572        # Each fitpage contains the name based on fit widget number 
     573        fitpage_name = "" if id is None else "M"+str(id) 
    563574        new_plots = [] 
    564575        for item, plot in plots.items(): 
    565             if not self.updatePlot(plot): 
    566                 # Don't plot intermediate results, e.g. P(Q), S(Q) 
    567                 match = GuiUtils.theory_plot_ID_pattern.match(plot.id) 
    568                 # 2nd match group contains the identifier for the intermediate result, if present (e.g. "[P(Q)]") 
    569                 if match and match.groups()[1] != None: 
    570                     continue 
     576            if self.updatePlot(plot) and filename != plot.name: 
     577                continue 
     578            # Don't plot intermediate results, e.g. P(Q), S(Q) 
     579            match = GuiUtils.theory_plot_ID_pattern.match(plot.id) 
     580            # 2nd match group contains the identifier for the intermediate result, if present (e.g. "[P(Q)]") 
     581            if match and match.groups()[1] != None: 
     582                continue 
     583            # Don't include plots from different fitpages, but always include the original data 
     584            if fitpage_name in plot.name or filename == plot.name: 
    571585                # 'sophisticated' test to generate standalone plot for residuals 
    572586                if 'esiduals' in plot.title: 
     
    579593            self.plotData(new_plots) 
    580594 
    581     def displayData(self, data_list): 
     595    def displayData(self, data_list, id=None): 
    582596        """ 
    583597        Forces display of charts for the given data set 
     
    588602        # the data explorer indices. 
    589603        filename = plot_to_show.filename 
    590         self.displayFile(filename=filename, is_data=plot_to_show.is_data) 
     604        self.displayFile(filename=filename, is_data=plot_to_show.is_data, id=id) 
    591605 
    592606    def addDataPlot2D(self, plot_set, item): 
  • src/sas/qtgui/MainWindow/GuiManager.py

    r339e22b r5b144c6  
    921921            self.filesWidget.displayFile(filename=filename, is_data=True) 
    922922 
    923     def showPlot(self, plot): 
     923    def showPlot(self, plot, id): 
    924924        """ 
    925925        Pass the show plot request to the data explorer 
    926926        """ 
    927927        if hasattr(self, "filesWidget"): 
    928             self.filesWidget.displayData(plot) 
     928            self.filesWidget.displayData(plot, id) 
    929929 
    930930    def uncheckAllMenuItems(self, menuObject): 
  • src/sas/qtgui/Perspectives/Fitting/FittingLogic.py

    r9ba91b7 r61f0c75  
    213213        plots = [] 
    214214        for name, result in return_data['intermediate_results'].items(): 
     215            if not isinstance(result, np.ndarray): 
     216                continue 
    215217            plots.append(self._create1DPlot(tab_id, return_data['x'], result, 
    216218                         return_data['model'], return_data['data'], 
  • src/sas/qtgui/Perspectives/Fitting/FittingWidget.py

    r5e0891b rbb477f5  
    569569            menu.exec_(self.lstParams.viewport().mapToGlobal(position)) 
    570570        except AttributeError as ex: 
    571             logging.error("Error generating context menu: %s" % ex) 
     571            logger.error("Error generating context menu: %s" % ex) 
    572572        return 
    573573 
     
    14561456            self.communicate.statusBarUpdateSignal.emit(msg) 
    14571457            msg += results.mesg 
    1458             logging.error(msg) 
     1458            logger.error(msg) 
    14591459            return 
    14601460 
     
    14991499        if self.calc_fit._interrupting: 
    15001500            msg = "Fitting cancelled by user after: %s s." % GuiUtils.formatNumber(elapsed) 
    1501             logging.warning("\n"+msg+"\n") 
     1501            logger.warning("\n"+msg+"\n") 
    15021502        else: 
    15031503            msg = "Fitting completed successfully in: %s s." % GuiUtils.formatNumber(elapsed) 
     
    18411841        data_to_show = self.data if self.data_is_loaded else self.model_data 
    18421842        if data_to_show is not None: 
    1843             self.communicate.plotRequestedSignal.emit([data_to_show]) 
     1843            self.communicate.plotRequestedSignal.emit([data_to_show], self.tab_id) 
    18441844 
    18451845    def onOptionsUpdate(self): 
     
    20522052                kernel_module = generate.load_kernel_module(name) 
    20532053            except ModuleNotFoundError as ex: 
    2054                 logging.error("Can't find the model "+ str(ex)) 
     2054                logger.error("Can't find the model "+ str(ex)) 
    20552055                return 
    20562056 
     
    22872287            fitted_data.symbol = "Line" 
    22882288            self.createTheoryIndex(fitted_data) 
     2289            # Switch to the theory tab for user's glee 
     2290            self.communicate.changeDataExplorerTabSignal.emit(1) 
    22892291 
    22902292    def updateModelIndex(self, fitted_data): 
     
    24222424 
    24232425        if self.data_is_loaded: 
     2426            # delete any plots associated with the data that were not updated (e.g. to remove beta(Q), S_eff(Q)) 
    24242427            GuiUtils.deleteRedundantPlots(self.all_data[self.data_index], new_plots) 
     2428            pass 
    24252429        else: 
    24262430            # delete theory items for the model, in order to get rid of any redundant items, e.g. beta(Q), S_eff(Q) 
     
    25112515        """ 
    25122516        # TODO: remimplement thread cancellation 
    2513         logging.error("".join(traceback.format_exception(etype, value, tb))) 
     2517        logger.error("".join(traceback.format_exception(etype, value, tb))) 
    25142518 
    25152519    def setTableProperties(self, table): 
     
    26932697 
    26942698        if not datafile: 
    2695             logging.info("No weight data chosen.") 
     2699            logger.info("No weight data chosen.") 
    26962700            raise IOError 
    26972701 
     
    28092813        self._n_shells_row = shell_row - 1 
    28102814 
    2811         # Set the index to the state-kept value 
    2812         func.setCurrentIndex(self.current_shell_displayed 
    2813                              if self.current_shell_displayed < func.count() else 0) 
     2815        # Get the default number of shells for the model 
     2816        kernel_pars = self.kernel_module._model_info.parameters.kernel_parameters 
     2817        shell_par = None 
     2818        for par in kernel_pars: 
     2819            if par.name == param_name: 
     2820                shell_par = par 
     2821                break 
     2822        if not shell_par: 
     2823            logger.error("Could not find %s in kernel parameters.", param_name) 
     2824        default_shell_count = shell_par.default 
     2825 
     2826        # Add default number of shells to the model 
     2827        func.setCurrentIndex(default_shell_count) 
    28142828 
    28152829    def modifyShellsInList(self, index): 
     
    31253139            param_value = str(self._model_model.item(row, 1).text()) 
    31263140            param_error = None 
     3141            param_min = None 
     3142            param_max = None 
    31273143            column_offset = 0 
    31283144            if self.has_error_column: 
    31293145                param_error = str(self._model_model.item(row, 2).text()) 
    31303146                column_offset = 1 
    3131             param_min = str(self._model_model.item(row, 2+column_offset).text()) 
    3132             param_max = str(self._model_model.item(row, 3+column_offset).text()) 
     3147 
     3148            try: 
     3149                param_min = str(self._model_model.item(row, 2+column_offset).text()) 
     3150                param_max = str(self._model_model.item(row, 3+column_offset).text()) 
     3151            except: 
     3152                pass 
     3153 
    31333154            param_list.append([param_name, param_checked, param_value, param_error, param_min, param_max]) 
    31343155 
     
    32203241 
    32213242                # limits 
    3222                 limit_lo = item[3] 
    3223                 context[name].append(limit_lo) 
    3224                 limit_hi = item[4] 
    3225                 context[name].append(limit_hi) 
     3243                try: 
     3244                    limit_lo = item[3] 
     3245                    context[name].append(limit_lo) 
     3246                    limit_hi = item[4] 
     3247                    context[name].append(limit_hi) 
     3248                except: 
     3249                    pass 
    32263250 
    32273251                # Polydisp 
     
    32823306                ioffset = 1 
    32833307            # min/max 
    3284             param_repr = GuiUtils.formatNumber(param_dict[param_name][2+ioffset], high=True) 
    3285             self._model_model.item(row, 2+ioffset).setText(param_repr) 
    3286             param_repr = GuiUtils.formatNumber(param_dict[param_name][3+ioffset], high=True) 
    3287             self._model_model.item(row, 3+ioffset).setText(param_repr) 
     3308            try: 
     3309                param_repr = GuiUtils.formatNumber(param_dict[param_name][2+ioffset], high=True) 
     3310                self._model_model.item(row, 2+ioffset).setText(param_repr) 
     3311                param_repr = GuiUtils.formatNumber(param_dict[param_name][3+ioffset], high=True) 
     3312                self._model_model.item(row, 3+ioffset).setText(param_repr) 
     3313            except: 
     3314                pass 
     3315 
    32883316            self.setFocus() 
     3317 
    32893318 
    32903319 
  • src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py

    r4ea8020 rf712bf30  
    613613 
    614614        # Check that the number of rows increased 
     615        # (note that n == 1 by default in core_multi_shell so this increases index by 2) 
    615616        more_rows = self.widget._model_model.rowCount() - last_row 
    616         self.assertEqual(more_rows, 6) # 6 new rows: 2 params per index 
    617  
    618         # Back to 0 
     617        self.assertEqual(more_rows, 4) # 4 new rows: 2 params per index 
     618 
     619        # Set to 0 
    619620        self.widget.lstParams.indexWidget(func_index).setCurrentIndex(0) 
    620         self.assertEqual(self.widget._model_model.rowCount(), last_row) 
     621        self.assertEqual(self.widget._model_model.rowCount(), last_row - 2) # 2 fewer rows than default 
    621622 
    622623    def testPlotTheory(self): 
  • src/sas/qtgui/Perspectives/Inversion/InversionPerspective.py

    r4d959c8 r48e55c9  
    562562            title = self.prPlot.name 
    563563            GuiUtils.updateModelItemWithPlot(self._data, self.prPlot, title) 
    564             self.communicate.plotRequestedSignal.emit([self.prPlot]) 
     564            self.communicate.plotRequestedSignal.emit([self.prPlot], None) 
    565565        if self.dataPlot is not None: 
    566566            title = self.dataPlot.name 
    567567            GuiUtils.updateModelItemWithPlot(self._data, self.dataPlot, title) 
    568             self.communicate.plotRequestedSignal.emit([self.dataPlot]) 
     568            self.communicate.plotRequestedSignal.emit([self.dataPlot], None) 
    569569        self.enableButtons() 
    570570 
  • src/sas/qtgui/Plotting/Plotter.py

    r0cd98a1 r5b144c6  
    561561 
    562562        #Remove another Fit, if exists 
    563         self.removePlot("fit") 
     563        self.removePlot("Fit") 
    564564 
    565565        self.fit_result.reset_view() 
  • src/sas/qtgui/Plotting/UnitTesting/PlotterTest.py

    rb8080e1 r5b144c6  
    5757        self.plotter.data = self.data 
    5858        self.plotter.show() 
    59         FigureCanvas.draw_idle = MagicMock() 
     59        FigureCanvas.draw = MagicMock() 
    6060 
    6161        self.plotter.plot(hide_error=False) 
    6262 
    6363        self.assertEqual(self.plotter.ax.get_xscale(), 'log') 
    64         self.assertTrue(FigureCanvas.draw_idle.called) 
     64        self.assertTrue(FigureCanvas.draw.called) 
    6565 
    6666        self.plotter.figure.clf() 
     
    7070        self.plotter.data = self.data 
    7171        self.plotter.show() 
    72         FigureCanvas.draw_idle = MagicMock() 
     72        FigureCanvas.draw = MagicMock() 
    7373 
    7474        self.plotter.plot(hide_error=True) 
    7575 
    7676        self.assertEqual(self.plotter.ax.get_yscale(), 'log') 
    77         self.assertTrue(FigureCanvas.draw_idle.called) 
     77        self.assertTrue(FigureCanvas.draw.called) 
    7878        self.plotter.figure.clf() 
    7979 
     
    9191        self.plotter.data = data 
    9292        self.plotter.show() 
    93         FigureCanvas.draw_idle = MagicMock() 
     93        FigureCanvas.draw = MagicMock() 
    9494 
    9595        self.plotter.plot(hide_error=True) 
     
    9797        self.assertEqual(self.plotter.ax.get_xscale(), 'linear') 
    9898        self.assertEqual(self.plotter.ax.get_yscale(), 'linear') 
    99         self.assertTrue(FigureCanvas.draw_idle.called) 
     99        self.assertTrue(FigureCanvas.draw.called) 
    100100 
    101101    def testCreateContextMenuQuick(self): 
     
    262262        # Just this one plot 
    263263        self.assertEqual(len(list(self.plotter.plot_dict.keys())), 1) 
    264         self.plotter.onLinearFit(1) 
     264        self.plotter.onLinearFit('Test name') 
    265265 
    266266        # Check that exec_ got called 
     
    289289 
    290290        # Delete one set 
    291         self.plotter.onRemovePlot(2) 
     291        self.plotter.onRemovePlot('Test name 2') 
    292292        # Assure we have two sets 
    293293        self.assertEqual(len(list(self.plotter.plot_dict.keys())), 1) 
     
    296296 
    297297        # Delete the remaining set 
    298         self.plotter.onRemovePlot(1) 
     298        self.plotter.onRemovePlot('Test name') 
    299299        # Assure we have no plots 
    300300        self.assertEqual(len(list(self.plotter.plot_dict.keys())), 0) 
     
    331331        self.assertEqual(yl, "$YAXIS(cake)$") 
    332332        # The hide_error flag should also remain 
    333         self.assertTrue(self.plotter.plot_dict[2].hide_error) 
     333        self.assertTrue(self.plotter.plot_dict['Test name 2'].hide_error) 
    334334        self.plotter.figure.clf() 
    335335 
     
    355355 
    356356        # Reverse the toggle 
    357         self.plotter.onToggleHideError(2) 
     357        self.plotter.onToggleHideError('Test name 2') 
    358358        # See that the labels didn't change 
    359359        xl = self.plotter.ax.xaxis.label.get_text() 
     
    362362        self.assertEqual(yl, "$YAXIS(cake)$") 
    363363        # The hide_error flag should toggle 
    364         self.assertEqual(self.plotter.plot_dict[2].hide_error, not error_status) 
     364        self.assertEqual(self.plotter.plot_dict['Test name 2'].hide_error, not error_status) 
    365365        self.plotter.figure.clf() 
    366366 
     
    417417        self.assertEqual(yl, "$YAXIS(cake)$") 
    418418        # The hide_error flag should be as set 
    419         self.assertEqual(self.plotter.plot_dict[2].hide_error, error_status) 
     419        self.assertEqual(self.plotter.plot_dict['Test name 2'].hide_error, error_status) 
    420420        self.plotter.figure.clf() 
    421421 
  • src/sas/qtgui/Utilities/GuiUtils.py

    r339e22b r5d28d6b  
    225225    # New plot requested from the GUI manager 
    226226    # Old "NewPlotEvent" 
    227     plotRequestedSignal = QtCore.pyqtSignal(list) 
     227    plotRequestedSignal = QtCore.pyqtSignal(list, int) 
    228228 
    229229    # Plot from file names 
     
    277277    # Notify about new categories/models from category manager 
    278278    updateModelCategoriesSignal = QtCore.pyqtSignal() 
     279 
     280    # Tell the data explorer to switch tabs 
     281    changeDataExplorerTabSignal = QtCore.pyqtSignal(int) 
    279282 
    280283def updateModelItemWithPlot(item, update_data, name=""): 
     
    288291    for index in range(item.rowCount()): 
    289292        plot_item = item.child(index) 
    290         if plot_item.isCheckable(): 
    291             plot_data = plot_item.child(0).data() 
    292             if plot_data.id is not None and \ 
    293                    (plot_data.name == update_data.name or plot_data.id == update_data.id): 
     293        if not plot_item.isCheckable(): 
     294            continue 
     295        plot_data = plot_item.child(0).data() 
     296        if plot_data.id is not None and \ 
     297                plot_data.name == update_data.name: 
     298                #(plot_data.name == update_data.name or plot_data.id == update_data.id): 
    294299            # if plot_data.id is not None and plot_data.id == update_data.id: 
    295                 # replace data section in item 
    296                 plot_item.child(0).setData(update_data) 
    297                 plot_item.setText(name) 
    298                 # Plot title if any 
    299                 if plot_item.child(1).hasChildren(): 
    300                     plot_item.child(1).child(0).setText("Title: %s"%name) 
    301                 # Force redisplay 
    302                 return 
     300            # replace data section in item 
     301            plot_item.child(0).setData(update_data) 
     302            plot_item.setText(name) 
     303            # Plot title if any 
     304            if plot_item.child(1).hasChildren(): 
     305                plot_item.child(1).child(0).setText("Title: %s"%name) 
     306            # Force redisplay 
     307            return 
    303308 
    304309    # Create the new item 
  • src/sas/qtgui/Perspectives/Inversion/DMaxExplorerWidget.py

    rb0ba43e re908916  
    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 
     
    188190            y_unit = "a.u." 
    189191 
    190         data = Data1D(xs, ys) 
     192        data = Data1D(plotable_xs, ys) 
    191193        if self.hasPlot: 
    192194            self.plot.removePlot(None) 
  • src/sas/sascalc/pr/invertor.py

    rb8080e1 r6701a0b  
    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        """ 
     
    244258        invertor.x = self.x 
    245259        invertor.y = self.y 
    246         invertor.err = self.err 
     260        if np.size(self.err) == 0 or np.all(self.err) == 0: 
     261            invertor.err = self.add_errors(self.y) 
     262        else: 
     263            invertor.err = self.err 
    247264        invertor.est_bck = self.est_bck 
    248265        invertor.background = self.background 
     
    268285            A[i][j] = (Fourier transformed base function for point j) 
    269286 
    270         We them choose a number of r-points, n_r, to evaluate the second 
     287        We then choose a number of r-points, n_r, to evaluate the second 
    271288        derivative of P(r) at. This is used as our regularization term. 
    272289        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.