Ignore:
Timestamp:
Apr 27, 2017 8:39:35 AM (7 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:
0215e0a
Parents:
98b13f72
Message:

Refactored fitting options tab

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/sas/qtgui/Perspectives/Fitting/FittingWidget.py

    • Property mode changed from 100755 to 100644
    r98b13f72 r180bd54  
    22import json 
    33import os 
    4 import numpy 
     4import numpy as np 
    55from collections import defaultdict 
    66from itertools import izip 
     
    3131from sas.qtgui.Perspectives.Fitting import FittingUtilities 
    3232from SmearingWidget import SmearingWidget 
     33from OptionsWidget import OptionsWidget 
    3334 
    3435TAB_MAGNETISM = 4 
     
    3738CATEGORY_STRUCTURE = "Structure Factor" 
    3839STRUCTURE_DEFAULT = "None" 
    39 QMIN_DEFAULT = 0.0005 
    40 QMAX_DEFAULT = 0.5 
    41 NPTS_DEFAULT = 50 
    4240 
    4341class FittingWidget(QtGui.QWidget, Ui_FittingWidgetUI): 
     
    6967        # Parameters to fit 
    7068        self.parameters_to_fit = None 
    71         # Weight radio box group 
    72         self.weightingGroup = QtGui.QButtonGroup() 
     69        # Fit options 
     70        self.q_range_min = 0.005 
     71        self.q_range_max = 0.1 
     72        self.npts = 25 
     73        self.log_points = False 
     74        self.weighting = 0 
    7375 
    7476        # Which tab is this widget displayed in? 
     
    7880        self.current_shell_displayed = 0 
    7981        self.has_error_column = False 
    80  
    81         # Range parameters 
    82         self.q_range_min = QMIN_DEFAULT 
    83         self.q_range_max = QMAX_DEFAULT 
    84         self.npts = NPTS_DEFAULT 
    8582 
    8683        # Main Data[12]D holder 
     
    9289        self.communicate = self.parent.communicate 
    9390 
     91        # Options widget 
     92        layout = QtGui.QGridLayout() 
     93        self.options_widget = OptionsWidget(self, self.logic) 
     94        layout.addWidget(self.options_widget)  
     95        self.tabOptions.setLayout(layout) 
     96 
    9497        # Smearing widget 
    9598        layout = QtGui.QGridLayout() 
    9699        self.smearing_widget = SmearingWidget(self) 
    97100        layout.addWidget(self.smearing_widget)  
    98         #self.tabFitting.removeTab(2) 
    99         self.tabFitting.insertTab(2, self.smearing_widget, "Resolution") 
     101        self.tabResolution.setLayout(layout) 
    100102 
    101103        # Define bold font for use in various controls 
     
    186188        self.updateQRange() 
    187189        self.cmdFit.setEnabled(True) 
    188         self.boxWeighting.setEnabled(True) 
    189         self.cmdMaskEdit.setEnabled(True) 
    190         # Switch off txtNpts related controls 
    191         self.txtNpts.setEnabled(False) 
    192         self.txtNptsFit.setEnabled(False) 
    193         self.chkLogData.setEnabled(False) 
    194190        # Switch off Data2D control 
    195191        self.chk2DView.setEnabled(False) 
    196192        self.chk2DView.setVisible(False) 
    197193        self.chkMagnetism.setEnabled(True) 
    198  
    199         # Weighting controls 
    200         if self.is2D: 
    201             if self.logic.data.err_data is None or\ 
    202                     numpy.all(err == 1 for err in self.logic.data.err_data) or \ 
    203                     not numpy.any(self.logic.data.err_data): 
    204                 self.rbWeighting2.setEnabled(False) 
    205                 self.rbWeighting1.setChecked(True) 
    206             else: 
    207                 self.rbWeighting2.setEnabled(True) 
    208                 self.rbWeighting2.setChecked(True) 
    209         else: 
    210             if self.logic.data.dy is None or\ 
    211                     numpy.all(self.logic.data.dy == 1) or\ 
    212                     not numpy.any(self.logic.data.dy): 
    213                 self.rbWeighting2.setEnabled(False) 
    214                 self.rbWeighting1.setChecked(True) 
    215             else: 
    216                 self.rbWeighting2.setEnabled(True) 
    217                 self.rbWeighting2.setChecked(True) 
     194        # Similarly on other tabs 
     195        self.options_widget.setEnablementOnDataLoad() 
    218196 
    219197        # Smearing tab 
     
    260238            self.onSelectModel() 
    261239 
    262     def toggleLogData(self, isChecked): 
    263         """ Toggles between log and linear data sets """ 
    264         pass 
    265  
    266240    def initializeControls(self): 
    267241        """ 
     
    270244        self.cmdFit.setEnabled(False) 
    271245        self.cmdPlot.setEnabled(True) 
    272         self.cmdComputePoints.setVisible(False) # probably redundant 
     246        self.options_widget.cmdComputePoints.setVisible(False) # probably redundant 
    273247        self.chkPolydispersity.setEnabled(True) 
    274248        self.chkPolydispersity.setCheckState(False) 
     
    281255        self.tabFitting.setTabEnabled(TAB_MAGNETISM, False) 
    282256        self.lblChi2Value.setText("---") 
    283         # Group boxes 
    284         self.boxWeighting.setEnabled(False) 
    285         self.cmdMaskEdit.setEnabled(False) 
    286         # Button groups 
    287         self.weightingGroup.addButton(self.rbWeighting1) 
    288         self.weightingGroup.addButton(self.rbWeighting2) 
    289         self.weightingGroup.addButton(self.rbWeighting3) 
    290         self.weightingGroup.addButton(self.rbWeighting4) 
    291257        # Smearing tab 
    292258        self.smearing_widget.updateSmearing(self.data) 
     259        # Line edits in the option tab 
     260        self.updateQRange() 
    293261 
    294262    def initializeSignals(self): 
     
    304272        self.chkPolydispersity.toggled.connect(self.togglePoly) 
    305273        self.chkMagnetism.toggled.connect(self.toggleMagnetism) 
    306         self.chkLogData.toggled.connect(self.toggleLogData) 
    307274        # Buttons 
    308275        self.cmdFit.clicked.connect(self.onFit) 
    309276        self.cmdPlot.clicked.connect(self.onPlot) 
    310         self.cmdMaskEdit.clicked.connect(self.onMaskEdit) 
    311         self.cmdReset.clicked.connect(self.onReset) 
    312         # Line edits 
    313         self.txtNpts.editingFinished.connect(self.onNpts) 
    314         self.txtMinRange.editingFinished.connect(self.onMinRange) 
    315         self.txtMaxRange.editingFinished.connect(self.onMaxRange) 
    316         # Button groups 
    317         self.weightingGroup.buttonClicked.connect(self.onWeightingChoice) 
    318277 
    319278        # Respond to change in parameters from the UI 
     
    322281        # TODO after the poly_model prototype accepted 
    323282        #self._magnet_model.itemChanged.connect(self.onMagneticModelChange) 
     283 
     284        # Signals from separate tabs asking for replot 
     285        self.options_widget.plot_signal.connect(self.onOptionsUpdate) 
    324286 
    325287    def onSelectModel(self): 
     
    391353        # Populate the models combobox 
    392354        self.cbModel.addItems(sorted([model for (model, _) in model_list])) 
    393  
    394     def onWeightingChoice(self, button): 
    395         """ 
    396         Update weighting in the fit state 
    397         """ 
    398         button_id = button.group().checkedId() 
    399         button_id = abs(button_id + 2) 
    400         #self.fitPage.weighting = button_id 
    401         print button_id 
    402355 
    403356    def onPolyModelChange(self, item): 
     
    448401        params_to_fit = self.parameters_to_fit 
    449402 
    450         # Potential weights added 
     403        # Potential weights added directly to data 
    451404        self.addWeightingToData(data) 
    452405 
    453406        # Potential smearing added 
     407        # Remember that smearing_min/max can be None -> 
     408        # deal with it until Python gets discriminated unions 
    454409        smearing, accuracy, smearing_min, smearing_max = self.smearing_widget.state() 
    455410 
     
    512467        res = res_list[0] 
    513468        if res.fitness is None or \ 
    514             not numpy.isfinite(res.fitness) or \ 
    515             numpy.any(res.pvec == None) or \ 
    516             not numpy.all(numpy.isfinite(res.pvec)): 
     469            not np.isfinite(res.fitness) or \ 
     470            np.any(res.pvec == None) or \ 
     471            not np.all(np.isfinite(res.pvec)): 
    517472            msg = "Fitting did not converge!!!" 
    518473            self.communicate.statusBarUpdateSignal.emit(msg) 
     
    607562        Plot the current set of data 
    608563        """ 
    609         if self.data is None : 
     564        if not self.data_is_loaded: 
    610565            self.createDefaultDataset() 
    611566        self.calculateQGridForModel() 
    612567 
    613     def onNpts(self): 
    614         """ 
    615         Callback for number of points line edit update 
    616         """ 
    617         # assumes type/value correctness achieved with QValidator 
    618         try: 
    619             self.npts = int(self.txtNpts.text()) 
    620         except ValueError: 
    621             # TODO 
    622             # This will return the old value to model/view and return 
    623             # notifying the user about format available. 
    624             pass 
    625         # Force redisplay 
    626         if self.model_is_loaded: 
    627             self.onPlot() 
    628  
    629     def onMinRange(self): 
    630         """ 
    631         Callback for minimum range of points line edit update 
    632         """ 
    633         # assumes type/value correctness achieved with QValidator 
    634         try: 
    635             self.q_range_min = float(self.txtMinRange.text()) 
    636         except ValueError: 
    637             # TODO 
    638             # This will return the old value to model/view and return 
    639             # notifying the user about format available. 
    640             return 
    641         # set Q range labels on the main tab 
    642         #self.lblMinRangeDef.setText(str(self.q_range_min)) 
    643         if self.model_is_loaded: 
    644             self.onPlot() 
    645  
    646     def onMaxRange(self): 
    647         """ 
    648         Callback for maximum range of points line edit update 
    649         """ 
    650         # assumes type/value correctness achieved with QValidator 
    651         try: 
    652             self.q_range_max = float(self.txtMaxRange.text()) 
    653         except: 
    654             pass 
    655         # set Q range labels on the main tab 
    656         self.lblMaxRangeDef.setText(str(self.q_range_max)) 
    657         if self.model_is_loaded: 
    658             self.onPlot() 
    659  
    660     def onMaskEdit(self): 
    661         """ 
    662         Callback for running the mask editor 
    663         """ 
    664         pass 
    665  
    666     def onReset(self): 
    667         """ 
    668         Callback for resetting qmin/qmax 
    669         """ 
    670         pass 
     568    def onOptionsUpdate(self): 
     569        """ 
     570        Update local option values and replot 
     571        """ 
     572        self.q_range_min, self.q_range_max, self.npts, self.log_points, self.weighting = \ 
     573            self.options_widget.state() 
     574        self.onPlot() 
    671575 
    672576    def setDefaultStructureCombo(self): 
     
    686590        # Create default datasets if no data passed 
    687591        if self.is2D: 
    688             qmax = self.q_range_max/numpy.sqrt(2) 
     592            qmax = self.q_range_max/np.sqrt(2) 
    689593            qstep = self.npts 
    690594            self.logic.createDefault2dData(qmax, qstep, self.tab_id) 
     595            return 
     596        elif self.log_points: 
     597            qmin = -10.0 if self.q_range_min < 1.e-10 else np.log10(self.q_range_min) 
     598            qmax =  10.0 if self.q_range_max > 1.e10 else np.log10(self.q_range_max) 
     599            interval = np.logspace(start=qmin, stop=qmax, num=self.npts, endpoint=True, base=10.0) 
    691600        else: 
    692             interval = numpy.linspace(start=self.q_range_min, stop=self.q_range_max, 
    693                         num=self.npts, endpoint=True) 
    694             self.logic.createDefault1dData(interval, self.tab_id) 
     601            interval = np.linspace(start=self.q_range_min, stop=self.q_range_max, 
     602                    num=self.npts, endpoint=True) 
     603        self.logic.createDefault1dData(interval, self.tab_id) 
    695604 
    696605    def readCategoryInfo(self): 
     
    745654        """ 
    746655        Adds weighting contribution to fitting data 
    747         """ 
    748         # Check the state of the Weighting radio buttons 
    749         button_id = self.weightingGroup.checkedId() 
    750         # Cast the id to a valid index 
    751         button_id = abs(button_id + 2) 
    752         if button_id == 0: 
    753             # No weight added 
    754             return 
     656        #""" 
    755657        # Send original data for weighting 
    756         weight = get_weight(data=data, is2d=self.is2D, flag=button_id) 
    757         if self.is2D: 
    758             data.err_data = weight 
    759         else: 
    760             data.dy = weight 
     658        weight = get_weight(data=data, is2d=self.is2D, flag=self.weighting) 
     659        update_module = data.err_data if self.is2D else data.dy 
     660        update_module = weight 
    761661 
    762662    def updateQRange(self): 
     
    770670        self.lblMaxRangeDef.setText(str(self.q_range_max)) 
    771671        # set Q range labels on the options tab 
    772         self.txtMaxRange.setText(str(self.q_range_max)) 
    773         self.txtMinRange.setText(str(self.q_range_min)) 
    774         self.txtNpts.setText(str(self.npts)) 
    775         self.txtNptsFit.setText(str(self.npts)) 
     672        self.options_widget.updateQRange(self.q_range_min, self.q_range_max, self.npts) 
    776673 
    777674    def SASModelToQModel(self, model_name, structure_factor=None): 
     
    959856        Prepare the fitting data object, based on current ModelModel 
    960857        """ 
     858        if self.kernel_module is None: 
     859            return 
    961860        # Awful API to a backend method. 
    962861        method = self.methodCalculateForData()(data=self.data, 
Note: See TracChangeset for help on using the changeset viewer.