Changeset 1bd266b in sasview for src


Ignore:
Timestamp:
Sep 8, 2018 10:52:16 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:
4d959c8
Parents:
e908916 (diff), 5e0891b (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:
15 edited

Legend:

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

    r60d55a7 r0cd98a1  
    4242        # Main model for keeping loaded data 
    4343        self.model = QtGui.QStandardItemModel(self) 
    44  
    4544        # Secondary model for keeping frozen data sets 
    4645        self.theory_model = QtGui.QStandardItemModel(self) 
     
    9897        self.communicator.plotUpdateSignal.connect(self.updatePlot) 
    9998        self.communicator.maskEditorSignal.connect(self.showEditDataMask) 
     99        self.communicator.extMaskEditorSignal.connect(self.extShowEditDataMask) 
    100100 
    101101        self.cbgraph.editTextChanged.connect(self.enableGraphCombo) 
     
    598598        plot2D.plot(plot_set) 
    599599        self.addPlot(plot2D) 
    600         self.active_plots[plot2D.data.id] = plot2D 
     600        self.active_plots[plot2D.data.name] = plot2D 
    601601        #============================================ 
    602602        # Experimental hook for silx charts 
     
    626626                new_plot.plot(plot_set, transform=transform) 
    627627                # active_plots may contain multiple charts 
    628                 self.active_plots[plot_set.id] = new_plot 
     628                self.active_plots[plot_set.name] = new_plot 
    629629            elif isinstance(plot_set, Data2D): 
    630630                self.addDataPlot2D(plot_set, item) 
     
    697697                old_plot.plot() 
    698698                # need this for lookup - otherwise this plot will never update 
    699                 self.active_plots[plot_set.id] = old_plot 
     699                self.active_plots[plot_set.name] = old_plot 
    700700 
    701701    def updatePlot(self, data): 
     
    711711 
    712712        ids_keys = list(self.active_plots.keys()) 
    713         ids_vals = [val.data.id for val in self.active_plots.values()] 
    714  
    715         data_id = data.id 
     713        ids_vals = [val.data.name for val in self.active_plots.values()] 
     714 
     715        data_id = data.name 
    716716        if data_id in ids_keys: 
    717717            self.active_plots[data_id].replacePlot(data_id, data) 
     
    952952        model = proxy.sourceModel() 
    953953 
    954         if index.isValid(): 
    955             model_item = model.itemFromIndex(proxy.mapToSource(index)) 
    956             # Find the mapped index 
    957             orig_index = model_item.isCheckable() 
    958             if orig_index: 
    959                 # Check the data to enable/disable actions 
    960                 is_2D = isinstance(GuiUtils.dataFromItem(model_item), Data2D) 
    961                 self.actionQuick3DPlot.setEnabled(is_2D) 
    962                 self.actionEditMask.setEnabled(is_2D) 
    963                 # Fire up the menu 
    964                 self.context_menu.exec_(self.current_view.mapToGlobal(position)) 
     954        if not index.isValid(): 
     955            return 
     956        model_item = model.itemFromIndex(proxy.mapToSource(index)) 
     957        # Find the mapped index 
     958        orig_index = model_item.isCheckable() 
     959        if not orig_index: 
     960            return 
     961        # Check the data to enable/disable actions 
     962        is_2D = isinstance(GuiUtils.dataFromItem(model_item), Data2D) 
     963        self.actionQuick3DPlot.setEnabled(is_2D) 
     964        self.actionEditMask.setEnabled(is_2D) 
     965        # Fire up the menu 
     966        self.context_menu.exec_(self.current_view.mapToGlobal(position)) 
    965967 
    966968    def showDataInfo(self): 
     
    10591061        self.new_plot.show() 
    10601062 
     1063    def extShowEditDataMask(self): 
     1064        self.showEditDataMask() 
     1065 
    10611066    def showEditDataMask(self, data=None): 
    10621067        """ 
    10631068        Mask Editor for 2D plots 
    10641069        """ 
    1065         if data is None or not isinstance(data, Data2D): 
    1066             index = self.current_view.selectedIndexes()[0] 
    1067             proxy = self.current_view.model() 
    1068             model = proxy.sourceModel() 
    1069             model_item = model.itemFromIndex(proxy.mapToSource(index)) 
    1070  
    1071             data = GuiUtils.dataFromItem(model_item) 
     1070        try: 
     1071            if data is None or not isinstance(data, Data2D): 
     1072                index = self.current_view.selectedIndexes()[0] 
     1073                proxy = self.current_view.model() 
     1074                model = proxy.sourceModel() 
     1075                model_item = model.itemFromIndex(proxy.mapToSource(index)) 
     1076 
     1077                data = GuiUtils.dataFromItem(model_item) 
     1078 
     1079            if data is None or not isinstance(data, Data2D): 
     1080                msg = QtWidgets.QMessageBox() 
     1081                msg.setIcon(QtWidgets.QMessageBox.Information) 
     1082                msg.setText("Error: cannot apply mask. \ 
     1083                                Please select a 2D dataset.") 
     1084                msg.setStandardButtons(QtWidgets.QMessageBox.Cancel) 
     1085                msg.exec_() 
     1086                return 
     1087        except: 
     1088            msg = QtWidgets.QMessageBox() 
     1089            msg.setIcon(QtWidgets.QMessageBox.Information) 
     1090            msg.setText("Error: No dataset selected. \ 
     1091                            Please select a 2D dataset.") 
     1092            msg.setStandardButtons(QtWidgets.QMessageBox.Cancel) 
     1093            msg.exec_() 
     1094            return 
    10721095 
    10731096        mask_editor = MaskEditor(self, data) 
  • src/sas/qtgui/MainWindow/GuiManager.py

    rf84d793 r339e22b  
    422422        self._workspace.actionExcel.triggered.connect(self.actionExcel) 
    423423        self._workspace.actionLatex.triggered.connect(self.actionLatex) 
    424  
    425424        # View 
    426425        self._workspace.actionShow_Grid_Window.triggered.connect(self.actionShow_Grid_Window) 
     
    452451        self._workspace.actionManage_Custom_Models.triggered.connect(self.actionManage_Custom_Models) 
    453452        self._workspace.actionAddMult_Models.triggered.connect(self.actionAddMult_Models) 
     453        self._workspace.actionEditMask.triggered.connect(self.actionEditMask) 
     454 
    454455        # Window 
    455456        self._workspace.actionCascade.triggered.connect(self.actionCascade) 
     
    781782        self.add_mult_editor.show() 
    782783 
     784    def actionEditMask(self): 
     785 
     786        self.communicate.extMaskEditorSignal.emit() 
     787 
    783788    #============ ANALYSIS ================= 
    784789    def actionFitting(self): 
  • src/sas/qtgui/MainWindow/UI/MainWindowUI.ui

    rdda8f16 r2f14b5d  
    113113    <addaction name="actionManage_Custom_Models"/> 
    114114    <addaction name="actionAddMult_Models"/> 
     115    <addaction name="separator"/> 
     116    <addaction name="actionEditMask"/> 
    115117   </widget> 
    116118   <widget class="QMenu" name="menuWindow"> 
     
    413415   </property> 
    414416  </action> 
     417    <action name="actionEditMask"> 
     418   <property name="text"> 
     419    <string>Edit Mask</string> 
     420   </property> 
     421  </action> 
    415422  <action name="actionCascade"> 
    416423   <property name="text"> 
  • src/sas/qtgui/Perspectives/Fitting/FittingLogic.py

    rdcabba7 r9ba91b7  
    161161        Create a new 1D data instance based on fitting results 
    162162        """ 
    163  
    164163        return self._create1DPlot(tab_id, return_data['x'], return_data['y'], 
    165164                                  return_data['model'], return_data['data']) 
     
    212211        (pq_plot, sq_plot). If either are unavailable, the corresponding plot is None. 
    213212        """ 
    214  
    215         pq_plot = None 
    216         sq_plot = None 
    217  
    218         if return_data.get('pq_values', None) is not None: 
    219             pq_plot = self._create1DPlot(tab_id, return_data['x'], 
    220                     return_data['pq_values'], return_data['model'], 
    221                     return_data['data'], component="P(Q)") 
    222         if return_data.get('sq_values', None) is not None: 
    223             sq_plot = self._create1DPlot(tab_id, return_data['x'], 
    224                     return_data['sq_values'], return_data['model'], 
    225                     return_data['data'], component="S(Q)") 
    226  
    227         return pq_plot, sq_plot 
     213        plots = [] 
     214        for name, result in return_data['intermediate_results'].items(): 
     215            plots.append(self._create1DPlot(tab_id, return_data['x'], result, 
     216                         return_data['model'], return_data['data'], 
     217                         component=name)) 
     218        return plots 
    228219 
    229220    def computeDataRange(self): 
  • src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py

    rb69b549 r01b4877  
    167167    return rows 
    168168 
    169 def addSimpleParametersToModel(parameters, is2D, parameters_original=None, model=None, view=None): 
     169def addSimpleParametersToModel(parameters, is2D, parameters_original=None, model=None, view=None, row_num=None): 
    170170    """ 
    171171    Update local ModelModel with sasmodel parameters (non-dispersed, non-magnetic) 
     
    216216        # Append to the model and use the combobox, if required 
    217217        if None not in (model, view): 
    218             model.appendRow(row) 
     218            if row_num is None: 
     219                model.appendRow(row) 
     220            else: 
     221                model.insertRow(row_num, row) 
     222                row_num += 1 
     223 
    219224            if cbox: 
    220225                view.setIndexWidget(item2.index(), cbox) 
     226 
    221227        rows.append(row) 
    222228 
  • src/sas/qtgui/Perspectives/Fitting/FittingWidget.py

    rf0365a2e r5e0891b  
    4848from sas.qtgui.Perspectives.Fitting.ReportPageLogic import ReportPageLogic 
    4949 
    50  
    5150TAB_MAGNETISM = 4 
    5251TAB_POLY = 3 
     
    188187 
    189188        # Overwrite data type descriptor 
     189 
    190190        self.is2D = True if isinstance(self.logic.data, Data2D) else False 
    191191 
     
    563563        When clicked on white space: model description 
    564564        """ 
    565         rows = [s.row() for s in self.lstParams.selectionModel().selectedRows()] 
     565        rows = [s.row() for s in self.lstParams.selectionModel().selectedRows() 
     566                if self.isCheckable(s.row())] 
    566567        menu = self.showModelDescription() if not rows else self.modelContextMenu(rows) 
    567568        try: 
     
    799800    def getConstraintForRow(self, row): 
    800801        """ 
    801         For the given row, return its constraint, if any 
    802         """ 
    803         if self.isCheckable(row): 
    804             item = self._model_model.item(row, 1) 
    805             try: 
    806                 return item.child(0).data() 
    807             except AttributeError: 
    808                 # return none when no constraints 
    809                 pass 
    810         return None 
     802        For the given row, return its constraint, if any (otherwise None) 
     803        """ 
     804        if not self.isCheckable(row): 
     805            return None 
     806        item = self._model_model.item(row, 1) 
     807        try: 
     808            return item.child(0).data() 
     809        except AttributeError: 
     810            return None 
    811811 
    812812    def rowHasConstraint(self, row): 
     
    814814        Finds out if row of the main model has a constraint child 
    815815        """ 
    816         if self.isCheckable(row): 
    817             item = self._model_model.item(row, 1) 
    818             if item.hasChildren(): 
    819                 c = item.child(0).data() 
    820                 if isinstance(c, Constraint): 
    821                     return True 
     816        if not self.isCheckable(row): 
     817            return False 
     818        item = self._model_model.item(row, 1) 
     819        if not item.hasChildren(): 
     820            return False 
     821        c = item.child(0).data() 
     822        if isinstance(c, Constraint): 
     823            return True 
    822824        return False 
    823825 
     
    826828        Finds out if row of the main model has an active constraint child 
    827829        """ 
    828         if self.isCheckable(row): 
    829             item = self._model_model.item(row, 1) 
    830             if item.hasChildren(): 
    831                 c = item.child(0).data() 
    832                 if isinstance(c, Constraint) and c.active: 
    833                     return True 
     830        if not self.isCheckable(row): 
     831            return False 
     832        item = self._model_model.item(row, 1) 
     833        if not item.hasChildren(): 
     834            return False 
     835        c = item.child(0).data() 
     836        if isinstance(c, Constraint) and c.active: 
     837            return True 
    834838        return False 
    835839 
     
    838842        Finds out if row of the main model has an active, nontrivial constraint child 
    839843        """ 
    840         if self.isCheckable(row): 
    841             item = self._model_model.item(row, 1) 
    842             if item.hasChildren(): 
    843                 c = item.child(0).data() 
    844                 if isinstance(c, Constraint) and c.func and c.active: 
    845                     return True 
     844        if not self.isCheckable(row): 
     845            return False 
     846        item = self._model_model.item(row, 1) 
     847        if not item.hasChildren(): 
     848            return False 
     849        c = item.child(0).data() 
     850        if isinstance(c, Constraint) and c.func and c.active: 
     851            return True 
    846852        return False 
    847853 
     
    10531059            # Show constraint, if present 
    10541060            row = rows[0].row() 
    1055             if self.rowHasConstraint(row): 
    1056                 func = self.getConstraintForRow(row).func 
    1057                 if func is not None: 
    1058                     self.communicate.statusBarUpdateSignal.emit("Active constrain: "+func) 
     1061            if not self.rowHasConstraint(row): 
     1062                return 
     1063            func = self.getConstraintForRow(row).func 
     1064            if func is not None: 
     1065                self.communicate.statusBarUpdateSignal.emit("Active constrain: "+func) 
    10591066 
    10601067    def replaceConstraintName(self, old_name, new_name=""): 
     
    18071814        # Force data recalculation so existing charts are updated 
    18081815        self.showPlot() 
     1816        # This is an important processEvent. 
     1817        # This allows charts to be properly updated in order 
     1818        # of plots being applied. 
     1819        QtWidgets.QApplication.processEvents() 
    18091820        self.recalculatePlotData() 
    18101821 
     
    20912102            return 
    20922103 
     2104        product_params = None 
     2105 
    20932106        if self.kernel_module is None: 
    20942107            # Structure factor is the only selected model; build it and show all its params 
     
    20962109            s_params = self.kernel_module._model_info.parameters 
    20972110            s_params_orig = s_params 
    2098  
    20992111        else: 
    21002112            s_kernel = self.models[structure_factor]() 
     
    21132125            if "radius_effective_mode" in all_param_names: 
    21142126                # Show all parameters 
     2127                # In this case, radius_effective is NOT pruned by sasmodels.product 
    21152128                s_params = modelinfo.ParameterTable(all_params[p_pars_len:p_pars_len+s_pars_len]) 
    21162129                s_params_orig = modelinfo.ParameterTable(s_kernel._model_info.parameters.kernel_parameters) 
     2130                product_params = modelinfo.ParameterTable( 
     2131                        self.kernel_module._model_info.parameters.kernel_parameters[p_pars_len+s_pars_len:]) 
    21172132            else: 
    21182133                # Ensure radius_effective is not displayed 
    21192134                s_params_orig = modelinfo.ParameterTable(s_kernel._model_info.parameters.kernel_parameters[1:]) 
    21202135                if "radius_effective" in all_param_names: 
     2136                    # In this case, radius_effective is NOT pruned by sasmodels.product 
    21212137                    s_params = modelinfo.ParameterTable(all_params[p_pars_len+1:p_pars_len+s_pars_len]) 
     2138                    product_params = modelinfo.ParameterTable( 
     2139                            self.kernel_module._model_info.parameters.kernel_parameters[p_pars_len+s_pars_len:]) 
    21222140                else: 
     2141                    # In this case, radius_effective is pruned by sasmodels.product 
    21232142                    s_params = modelinfo.ParameterTable(all_params[p_pars_len:p_pars_len+s_pars_len-1]) 
     2143                    product_params = modelinfo.ParameterTable( 
     2144                            self.kernel_module._model_info.parameters.kernel_parameters[p_pars_len+s_pars_len-1:]) 
    21242145 
    21252146        # Add heading row 
     
    21292150        # Any renamed parameters are stored as data in the relevant item, for later handling 
    21302151        FittingUtilities.addSimpleParametersToModel( 
    2131                 s_params, 
    2132                 self.is2D, 
    2133                 s_params_orig, 
    2134                 self._model_model, 
    2135                 self.lstParams) 
     2152                parameters=s_params, 
     2153                is2D=self.is2D, 
     2154                parameters_original=s_params_orig, 
     2155                model=self._model_model, 
     2156                view=self.lstParams) 
     2157 
     2158        # Insert product-only params into QModel 
     2159        if product_params: 
     2160            prod_rows = FittingUtilities.addSimpleParametersToModel( 
     2161                    parameters=product_params, 
     2162                    is2D=self.is2D, 
     2163                    parameters_original=None, 
     2164                    model=self._model_model, 
     2165                    view=self.lstParams, 
     2166                    row_num=2) 
     2167 
     2168            # Since this all happens after shells are dealt with and we've inserted rows, fix this counter 
     2169            self._n_shells_row += len(prod_rows) 
    21362170 
    21372171    def haveParamsToFit(self): 
     
    23942428 
    23952429        # Create plots for intermediate product data 
    2396         pq_data, sq_data = self.logic.new1DProductPlots(return_data, self.tab_id) 
    2397         if pq_data is not None: 
    2398             pq_data.symbol = "Line" 
    2399             self.createNewIndex(pq_data) 
    2400             # self.communicate.plotUpdateSignal.emit([pq_data]) 
    2401             new_plots.append(pq_data) 
    2402         if sq_data is not None: 
    2403             sq_data.symbol = "Line" 
    2404             self.createNewIndex(sq_data) 
    2405             # self.communicate.plotUpdateSignal.emit([sq_data]) 
    2406             new_plots.append(sq_data) 
     2430        plots = self.logic.new1DProductPlots(return_data, self.tab_id) 
     2431        for plot in plots: 
     2432            plot.symbol = "Line" 
     2433            self.createNewIndex(plot) 
     2434            new_plots.append(plot) 
    24072435 
    24082436        for plot in new_plots: 
     
    28052833        self._num_shell_params = len(new_rows) 
    28062834        self.current_shell_displayed = index 
     2835 
     2836        # Change 'n' in the parameter model, thereby updating the underlying model 
     2837        self._model_model.item(self._n_shells_row, 1).setText(str(index)) 
    28072838 
    28082839        # Update relevant models 
     
    31493180            formatted_output = FittingUtilities.formatParameters(param_list) 
    31503181        elif format == "Excel": 
    3151             formatted_output = FittingUtilities.formatParametersExcel(param_list) 
     3182            formatted_output = FittingUtilities.formatParametersExcel(param_list[1:]) 
    31523183        elif format == "Latex": 
    3153             formatted_output = FittingUtilities.formatParametersLatex(param_list) 
     3184            formatted_output = FittingUtilities.formatParametersLatex(param_list[1:]) 
    31543185        else: 
    31553186            raise AttributeError("Bad format specifier.") 
     
    33163347        self._poly_model.blockSignals(False) 
    33173348 
     3349 
     3350 
  • src/sas/qtgui/Perspectives/Fitting/ModelThread.py

    rdcabba7 r5181e9b  
    164164        index = (self.qmin <= self.data.x) & (self.data.x <= self.qmax) 
    165165 
     166        intermediate_results = None 
     167 
    166168        # If we use a smearer, also return the unsmeared model 
    167169        unsmeared_output = None 
     
    174176            mask = self.data.x[first_bin:last_bin+1] 
    175177            unsmeared_output = numpy.zeros((len(self.data.x))) 
    176             unsmeared_output[first_bin:last_bin+1] = self.model.evalDistribution(mask) 
     178 
     179            return_data = self.model.calculate_Iq(mask) 
     180            if isinstance(return_data, tuple): 
     181                # see sasmodels beta_approx: SasviewModel.calculate_Iq 
     182                # TODO: implement intermediate results in smearers 
     183                return_data, _ = return_data 
     184            unsmeared_output[first_bin:last_bin+1] = return_data 
    177185            output = self.smearer(unsmeared_output, first_bin, last_bin) 
    178186 
     
    193201                unsmeared_error=unsmeared_error 
    194202        else: 
    195             output[index] = self.model.evalDistribution(self.data.x[index]) 
    196  
    197         sq_values = None 
    198         pq_values = None 
    199         s_model = None 
    200         p_model = None 
    201         if isinstance(self.model, MultiplicationModel): 
    202             s_model = self.model.s_model 
    203             p_model = self.model.p_model 
    204         elif hasattr(self.model, "calc_composition_models"): 
    205             results = self.model.calc_composition_models(self.data.x[index]) 
    206             if results is not None: 
    207                 pq_values, sq_values = results 
    208  
    209         if pq_values is None or sq_values is None: 
    210             if p_model is not None and s_model is not None: 
    211                 sq_values = numpy.zeros((len(self.data.x))) 
    212                 pq_values = numpy.zeros((len(self.data.x))) 
    213                 sq_values[index] = s_model.evalDistribution(self.data.x[index]) 
    214                 pq_values[index] = p_model.evalDistribution(self.data.x[index]) 
     203            return_data = self.model.calculate_Iq(self.data.x[index]) 
     204            if isinstance(return_data, tuple): 
     205                # see sasmodels beta_approx: SasviewModel.calculate_Iq 
     206                return_data, intermediate_results = return_data 
     207            output[index] = return_data 
     208 
     209        if intermediate_results: 
     210            # the model returns a callable which is then used to retrieve the data 
     211            intermediate_results = intermediate_results() 
     212        else: 
     213            # TODO: this conditional branch needs refactoring 
     214            sq_values = None 
     215            pq_values = None 
     216            s_model = None 
     217            p_model = None 
     218 
     219            if isinstance(self.model, MultiplicationModel): 
     220                s_model = self.model.s_model 
     221                p_model = self.model.p_model 
     222 
     223            elif hasattr(self.model, "calc_composition_models"): 
     224                results = self.model.calc_composition_models(self.data.x[index]) 
     225                if results is not None: 
     226                    pq_values, sq_values = results 
     227 
     228            if pq_values is None or sq_values is None: 
     229                if p_model is not None and s_model is not None: 
     230                    sq_values = numpy.zeros((len(self.data.x))) 
     231                    pq_values = numpy.zeros((len(self.data.x))) 
     232                    sq_values[index] = s_model.evalDistribution(self.data.x[index]) 
     233                    pq_values[index] = p_model.evalDistribution(self.data.x[index]) 
     234 
     235            if pq_values is not None and sq_values is not None: 
     236                intermediate_results  = { 
     237                    "P(Q)": pq_values, 
     238                    "S(Q)": sq_values 
     239                } 
     240            else: 
     241                intermediate_results = {} 
    215242 
    216243        elapsed = time.time() - self.starttime 
     
    223250            source = self.source, unsmeared_output = unsmeared_output, 
    224251            unsmeared_data = unsmeared_data, unsmeared_error = unsmeared_error, 
    225             pq_values = pq_values, sq_values = sq_values) 
     252            intermediate_results = intermediate_results) 
    226253 
    227254        if LocalConfig.USING_TWISTED: 
  • src/sas/qtgui/Perspectives/Fitting/UI/OptionsWidgetUI.ui

    r79bd268 r309fa1b  
    3232        <item row="0" column="1"> 
    3333         <widget class="QLineEdit" name="txtMinRange"> 
     34          <property name="minimumSize"> 
     35           <size> 
     36            <width>80</width> 
     37            <height>0</height> 
     38           </size> 
     39          </property> 
    3440          <property name="toolTip"> 
    3541           <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Minimum value of Q.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> 
     
    5460        <item row="1" column="1"> 
    5561         <widget class="QLineEdit" name="txtMaxRange"> 
     62          <property name="minimumSize"> 
     63           <size> 
     64            <width>80</width> 
     65            <height>0</height> 
     66           </size> 
     67          </property> 
    5668          <property name="toolTip"> 
    5769           <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Maximum value of Q.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> 
  • src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingLogicTest.py

    re752ab8 rbfb5d9e  
    9999        data.name = "boop" 
    100100        data.id = "poop" 
    101         return_data = (data.x,data.y, 7, None, None, 
    102                        0, True, 0.0, 1, data, 
    103                        data, False, None, 
    104                        None, None, None, 
    105                        None, None) 
     101        # Condensed return data (new1DPlot only uses these fields) 
     102        return_data = dict(x = data.x, 
     103                           y = data.y, 
     104                           model = data, 
     105                           data = data) 
     106        # return_data = (data.x,data.y, 7, None, None, 
     107        #                0, True, 0.0, 1, data, 
     108        #                data, False, None, 
     109        #                None, None, None, 
     110        #                None, None) 
    106111 
    107112        new_plot = self.logic.new1DPlot(return_data=return_data, tab_id=0) 
     
    139144        qmin, qmax, npts = self.logic.computeDataRange() 
    140145 
    141         return_data = (x_0, data, 7, data, None, 
    142                         True, 0.0, 1, 0, qmin, qmax, 
    143                         0.1, False, None) 
     146        # Condensed return data (new2DPlot only uses these fields) 
     147        return_data = dict(image = x_0, 
     148                           data = data, 
     149                           page_id = 7, 
     150                           model = data) 
     151        # return_data = (x_0, data, 7, data, None, 
     152        #                 True, 0.0, 1, 0, qmin, qmax, 
     153        #                 0.1, False, None) 
    144154 
    145155        new_plot = self.logic.new2DPlot(return_data=return_data) 
  • src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingOptionsTest.py

    r725d9c06 rbfb5d9e  
    3838        # The combo box 
    3939        self.assertIsInstance(self.widget.cbAlgorithm, QtWidgets.QComboBox) 
    40         self.assertEqual(self.widget.cbAlgorithm.count(), 5) 
     40        self.assertEqual(self.widget.cbAlgorithm.count(), 6) 
    4141        self.assertEqual(self.widget.cbAlgorithm.itemText(0), 'Nelder-Mead Simplex') 
    4242        self.assertEqual(self.widget.cbAlgorithm.itemText(4), 'Levenberg-Marquardt') 
  • src/sas/qtgui/Plotting/Plotter.py

    rc2f3ca2 r0cd98a1  
    182182 
    183183        # Update the list of data sets (plots) in chart 
    184         self.plot_dict[self._data.id] = self.data 
    185  
    186         self.plot_lines[self._data.id] = line 
     184        self.plot_dict[self._data.name] = self.data 
     185 
     186        self.plot_lines[self._data.name] = line 
    187187 
    188188        # Now add the legend with some customizations. 
     
    201201        # refresh canvas 
    202202        self.canvas.draw() 
    203         # This is an important processEvent. 
    204         # This allows charts to be properly updated in order 
    205         # of plots being applied. 
    206         QtWidgets.QApplication.processEvents() 
    207203 
    208204    def createContextMenu(self): 
     
    420416        This effectlvely refreshes the chart with changes to one of its plots 
    421417        """ 
    422         import logging 
    423418        self.removePlot(id) 
    424419        self.plot(data=new_plot) 
  • src/sas/qtgui/Utilities/GuiUtils.py

    r6da3e3d r339e22b  
    265265    # Mask Editor requested 
    266266    maskEditorSignal = QtCore.pyqtSignal(Data2D) 
     267 
     268    #second Mask Editor for external 
     269    extMaskEditorSignal = QtCore.pyqtSignal() 
    267270 
    268271    # Fitting parameter copy to clipboard 
  • 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/qtgui/Perspectives/Inversion/InversionPerspective.py

    r3c6ecd9 r34cf92c  
    4343    estimateSignal = QtCore.pyqtSignal(tuple) 
    4444    estimateNTSignal = QtCore.pyqtSignal(tuple) 
     45    estimateDynamicNTSignal = QtCore.pyqtSignal(tuple) 
     46    estimateDynamicSignal = QtCore.pyqtSignal(tuple) 
    4547    calculateSignal = QtCore.pyqtSignal(tuple) 
    4648 
     
    194196        self.model.itemChanged.connect(self.model_changed) 
    195197        self.estimateNTSignal.connect(self._estimateNTUpdate) 
     198        self.estimateDynamicNTSignal.connect(self._estimateDynamicNTUpdate) 
     199        self.estimateDynamicSignal.connect(self._estimateDynamicUpdate) 
    196200        self.estimateSignal.connect(self._estimateUpdate) 
    197201        self.calculateSignal.connect(self._calculateUpdate) 
     202 
     203        self.maxDistanceInput.textEdited.connect(self.performEstimateDynamic) 
    198204 
    199205    def setupMapper(self): 
     
    309315                                            and not self.isCalculating) 
    310316        self.removeButton.setEnabled(self.logic.data_is_loaded) 
    311         self.explorerButton.setEnabled(self.logic.data_is_loaded 
    312                                        and np.all(self.logic.data.dy != 0)) 
     317        self.explorerButton.setEnabled(self.logic.data_is_loaded) 
    313318        self.stopButton.setVisible(self.isCalculating) 
    314319        self.regConstantSuggestionButton.setEnabled( 
     
    501506        self.dataPlot = self._dataList[data_ref].get(DICT_KEYS[2]) 
    502507        self.performEstimate() 
     508 
     509    def updateDynamicGuiValues(self): 
     510        pr = self._calculator 
     511        alpha = self._calculator.suggested_alpha 
     512        self.model.setItem(WIDGETS.W_MAX_DIST, 
     513                            QtGui.QStandardItem("{:.4g}".format(pr.get_dmax()))) 
     514        self.regConstantSuggestionButton.setText("{:-3.2g}".format(alpha)) 
     515        self.noOfTermsSuggestionButton.setText( 
     516             "{:n}".format(self.nTermsSuggested)) 
     517 
     518        self.enableButtons() 
    503519 
    504520    def updateGuiValues(self): 
     
    641657        self.calcThread.ready(2.5) 
    642658 
     659        #Perform estimate should be done on value enter this should solve delay problem 
     660        self.performEstimate() 
     661 
    643662    def stopCalcThread(self): 
    644663        """ Stops a thread if it exists and is running """ 
     
    667686                                             error_func=self._threadError, 
    668687                                             completefn=self._estimateNTCompleted, 
     688                                             updatefn=None) 
     689        self.estimationThreadNT.queue() 
     690        self.estimationThreadNT.ready(2.5) 
     691 
     692    def performEstimateDynamicNT(self): 
     693        """ 
     694        Perform parameter estimation 
     695        """ 
     696        from .Thread import EstimateNT 
     697 
     698        self.updateCalculator() 
     699 
     700        # If a thread is already started, stop it 
     701        self.stopEstimateNTThread() 
     702 
     703        pr = self._calculator.clone() 
     704        # Skip the slit settings for the estimation 
     705        # It slows down the application and it doesn't change the estimates 
     706        pr.slit_height = 0.0 
     707        pr.slit_width = 0.0 
     708        nfunc = self.getNFunc() 
     709 
     710        self.estimationThreadNT = EstimateNT(pr, nfunc, 
     711                                             error_func=self._threadError, 
     712                                             completefn=self._estimateDynamicNTCompleted, 
    669713                                             updatefn=None) 
    670714        self.estimationThreadNT.queue() 
     
    693737        self.estimationThread.ready(2.5) 
    694738 
     739    def performEstimateDynamic(self): 
     740        """ 
     741            Perform parameter estimation 
     742        """ 
     743        from .Thread import EstimatePr 
     744 
     745        # If a thread is already started, stop it 
     746        self.stopEstimationThread() 
     747 
     748        self.estimationThread = EstimatePr(self._calculator.clone(), 
     749                                           self.getNFunc(), 
     750                                           error_func=self._threadError, 
     751                                           completefn=self._estimateDynamicCompleted, 
     752                                           updatefn=None) 
     753        self.estimationThread.queue() 
     754        self.estimationThread.ready(2.5) 
     755 
    695756    def stopEstimationThread(self): 
    696757        """ Stop the estimation thread if it exists and is running """ 
     
    705766        ''' Send a signal to the main thread for model update''' 
    706767        self.estimateSignal.emit((alpha, message, elapsed)) 
     768 
     769    def _estimateDynamicCompleted(self, alpha, message, elapsed): 
     770        ''' Send a signal to the main thread for model update''' 
     771        self.estimateDynamicSignal.emit((alpha, message, elapsed)) 
    707772 
    708773    def _estimateUpdate(self, output_tuple): 
     
    721786        self.performEstimateNT() 
    722787 
     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() 
     802 
    723803    def _estimateNTCompleted(self, nterms, alpha, message, elapsed): 
    724804        ''' Send a signal to the main thread for model update''' 
    725805        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)) 
    726810 
    727811    def _estimateNTUpdate(self, output_tuple): 
     
    747831            self.startThread() 
    748832 
     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 
    749855    def _calculateCompleted(self, out, cov, pr, elapsed): 
    750856        ''' Send a signal to the main thread for model update''' 
  • 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.