Changeset 8c945ec in sasview for src/sas/sasgui/perspectives/fitting


Ignore:
Timestamp:
Sep 18, 2017 8:07:49 PM (7 years ago)
Author:
GitHub <noreply@…>
Branches:
master, 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, magnetic_scatt, release-4.2.2, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
Children:
66acafe, fca1f50
Parents:
3152a02 (diff), 5c1c486 (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.
git-author:
Paul Butler <butlerpd@…> (09/18/17 20:07:49)
git-committer:
GitHub <noreply@…> (09/18/17 20:07:49)
Message:

Merge pull request #101 from lewisodriscoll/4.2.0-fixes

4.2.0 fixes

Location:
src/sas/sasgui/perspectives/fitting
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • src/sas/sasgui/perspectives/fitting/basepage.py

    r914c49d5 rb76e65a  
    29292929            return False 
    29302930 
     2931 
     2932    def _get_copy_params_details(self): 
     2933        """ 
     2934        Combines polydisperse parameters with self.parameters so that they can 
     2935        be written to the clipboard (for Excel or LaTeX). Also returns a list of 
     2936        the names of parameters that have been fitted 
     2937 
     2938        :returns: all_params - A list of all parameters, in the format of  
     2939        self.parameters 
     2940        :returns: fitted_par_names - A list of the names of parameters that have 
     2941        been fitted 
     2942        """ 
     2943        # Names of params that are being fitted 
     2944        fitted_par_names = [param[1] for param in self.param_toFit] 
     2945        # Names of params with associated polydispersity 
     2946        disp_params = [param[1].split('.')[0] for param in self.fittable_param] 
     2947 
     2948        # Create array of all parameters 
     2949        all_params = copy.copy(self.parameters) 
     2950        for param in self.parameters: 
     2951            if param[1] in disp_params: 
     2952                # Polydisperse params aren't in self.parameters, so need adding 
     2953                # to all_params 
     2954                name = param[1] + ".width" 
     2955                index = all_params.index(param) + 1 
     2956                to_insert = [] 
     2957                if name in fitted_par_names: 
     2958                    # Param is fitted, so already has a param list in self.param_toFit 
     2959                    to_insert = self.param_toFit[fitted_par_names.index(name)] 
     2960                else: 
     2961                    # Param isn't fitted, so mockup a param list 
     2962                    to_insert = [None, name, self.model.getParam(name), None, None] 
     2963                all_params.insert(index, to_insert) 
     2964        return all_params, fitted_par_names 
     2965 
    29312966    def get_copy_excel(self): 
    29322967        """ 
     
    29422977        Get the string copies of the param names and values in the tap 
    29432978        """ 
     2979        if not self.parameters: 
     2980            # Do nothing if parameters doesn't exist 
     2981            return False 
     2982 
    29442983        content = '' 
    2945  
    29462984        crlf = chr(13) + chr(10) 
    29472985        tab = chr(9) 
    29482986 
    2949         # Do it if params exist 
    2950         if self.parameters: 
    2951  
    2952             for param in self.parameters: 
    2953                 content += param[1]  # parameter name 
     2987        all_params, fitted_param_names = self._get_copy_params_details() 
     2988 
     2989        # Construct row of parameter names 
     2990        for param in all_params: 
     2991            name = param[1] # Parameter name 
     2992            content += name 
     2993            content += tab 
     2994            if name in fitted_param_names: 
     2995                # Only print errors for fitted parameters 
     2996                content += name + "_err" 
    29542997                content += tab 
    2955                 content += param[1] + "_err" 
    2956                 content += tab 
    2957  
    2958             content += crlf 
    2959  
    2960             # row of values and errors... 
    2961             for param in self.parameters: 
    2962                 content += param[2].GetValue()  # value 
    2963                 content += tab 
    2964                 content += param[4].GetValue()  # error 
    2965                 content += tab 
    2966  
    2967             return content 
    2968         else: 
    2969             return False 
     2998 
     2999        content += crlf 
     3000 
     3001        # Construct row of parameter values and errors 
     3002        for param in all_params: 
     3003            value = param[2] 
     3004            if hasattr(value, 'GetValue'): 
     3005                # param[2] is a text box 
     3006                value = value.GetValue() 
     3007            else: 
     3008                # param[2] is a float (from our self._get_copy_params_details) 
     3009                value = str(value) 
     3010            content += value 
     3011            content += tab 
     3012            if param[1] in fitted_param_names: 
     3013                # Only print errors for fitted parameters 
     3014                content += param[4].GetValue() 
     3015                content += tab  
     3016 
     3017        return content 
    29703018 
    29713019    def get_copy_latex(self): 
     
    29823030        Get the string copies of the param names and values in the tap 
    29833031        """ 
     3032        if not self.parameters: 
     3033            # Do nothing if self.parameters doesn't exist 
     3034            return False 
     3035         
    29843036        content = '\\begin{table}' 
    29853037        content += '\\begin{tabular}[h]' 
     
    29883040        tab = chr(9) 
    29893041 
    2990         # Do it if params exist 
    2991         if self.parameters: 
    2992  
    2993             content += '{|' 
    2994             for param in self.parameters: 
    2995                 content += 'l|l|' 
    2996             content += '}\hline' 
    2997             content += crlf 
    2998  
    2999             for index, param in enumerate(self.parameters): 
    3000                 content += param[1].replace('_', '\_')  # parameter name 
     3042        all_params, fitted_param_names = self._get_copy_params_details() 
     3043 
     3044        content += '{|' 
     3045        for param in all_params: 
     3046            content += 'l|l|' 
     3047        content += '}\hline' 
     3048        content += crlf 
     3049 
     3050        # Construct row of parameter names 
     3051        for index, param in enumerate(all_params): 
     3052            name = param[1] # Parameter name 
     3053            content += name.replace('_', '\_')  # Escape underscores 
     3054            if name in fitted_param_names: 
     3055                # Only print errors for fitted parameters 
    30013056                content += ' & ' 
    3002                 content += param[1].replace('_', '\_') + "\_err" 
    3003                 if index < len(self.parameters) - 1: 
    3004                     content += ' & ' 
    3005             content += '\\\\ \\hline' 
    3006             content += crlf 
    3007  
    3008             # row of values and errors... 
    3009             for index, param in enumerate(self.parameters): 
    3010                 content += param[2].GetValue()  # parameter value 
     3057                content += name.replace('_', '\_') + "\_err" 
     3058            if index < len(all_params) - 1: 
    30113059                content += ' & ' 
    3012                 content += param[4].GetValue()  # parameter error 
    3013                 if index < len(self.parameters) - 1: 
    3014                     content += ' & ' 
    3015             content += '\\\\ \\hline' 
    3016             content += crlf 
    3017  
    3018             content += '\\end{tabular}' 
    3019             content += '\\end{table}' 
    3020             return content 
    3021         else: 
    3022             return False 
     3060 
     3061        content += '\\\\ \\hline' 
     3062        content += crlf 
     3063 
     3064        # Construct row of values and errors 
     3065        for index, param in enumerate(all_params): 
     3066            value = param[2] 
     3067            if hasattr(value, "GetValue"): 
     3068                # value is a text box 
     3069                value = value.GetValue() 
     3070            else: 
     3071                # value is a float (from self._get_copy_params_details) 
     3072                value = str(value) 
     3073            content += value 
     3074            if param[1] in fitted_param_names: 
     3075                # Only print errors for fitted params 
     3076                content += ' & ' 
     3077                content += param[4].GetValue() 
     3078            if index < len(all_params) - 1: 
     3079                content += ' & ' 
     3080         
     3081        content += '\\\\ \\hline' 
     3082        content += crlf 
     3083        content += '\\end{tabular}' 
     3084        content += '\\end{table}' 
     3085 
     3086        return content 
    30233087 
    30243088    def set_clipboard(self, content=None): 
  • src/sas/sasgui/perspectives/fitting/fitpage.py

    red2276f r0b6f83c  
    289289        self.btFitHelp.SetToolTipString("General fitting help.") 
    290290        self.btFitHelp.Bind(wx.EVT_BUTTON, self._onFitHelp) 
    291          
     291 
    292292        # Resolution Smearing Help button (for now use same technique as 
    293293        # used for dI help to get tiniest possible button that works 
     
    303303        self.btSmearHelp.SetToolTipString("Resolution smearing help.") 
    304304        self.btSmearHelp.Bind(wx.EVT_BUTTON, self._onSmearHelp) 
    305          
     305 
    306306        # textcntrl for custom resolution 
    307307        self.smear_pinhole_percent = ModelTextCtrl(self, wx.ID_ANY, 
     
    564564        sizer.Add(self.draw_button, 0, 0) 
    565565        sizer.Add((-1, 5)) 
    566          
     566 
    567567        sizer.Add(self.tcChi, 0, 0) 
    568568        sizer.Add(self.Npts_fit, 0, 0) 
     
    570570        sizer.Add(self.btFit, 0, 0) 
    571571        sizer.Add(self.btFitHelp, 0, 0) 
    572          
     572 
    573573        boxsizer_range.Add(sizer_chi2) 
    574574        boxsizer_range.Add(sizer) 
     
    21812181        self.save_current_state() 
    21822182 
     2183        if not self.is_mac: 
     2184            self.Layout() 
     2185            self.Refresh() 
    21832186        # plot model ( when drawing, do not update chisqr value again) 
    21842187        self._draw_model(update_chisqr=False, source='fit') 
     
    27752778            else: 
    27762779                return cmp(a.lower(), b.lower()) 
    2777          
     2780 
    27782781        # keys obtained now from ordered dict, so commenting alphabetical 
    27792782        # ordering keys.sort(custom_compare) 
  • src/sas/sasgui/perspectives/fitting/fitpanel.py

    r67b0a99 r6f9abd3  
    501501            if data is None: 
    502502                return None 
     503        focused_page = self.GetPage(self.GetSelection()) 
    503504        for page in self.opened_pages.values(): 
    504505            # check if the selected data existing in the fitpanel 
    505506            pos = self.GetPageIndex(page) 
    506507            if not check_data_validity(page.get_data()) and not page.batch_on: 
     508                if page.model is not None and page != focused_page: 
     509                    # Page has an active theory and is in background - don't 
     510                    # send data here. 
     511                    continue 
    507512                # make sure data get placed in 1D empty tab if data is 1D 
    508513                # else data get place on 2D tab empty tab 
  • src/sas/sasgui/perspectives/fitting/fitting.py

    r2d9526d r5c1c486  
    13261326 
    13271327                is_data2d = issubclass(data.__class__, Data2D) 
    1328                 #check consistency of arrays 
     1328                # Check consistency of arrays 
    13291329                if not is_data2d: 
    13301330                    if len(res.theory) == len(res.index[res.index]) and \ 
     
    13371337                    new_theory[res.index == False] = np.nan 
    13381338                    correct_result = True 
    1339                 #get all fittable parameters of the current model 
     1339                # Get all fittable parameters of the current model 
    13401340                param_list = model.getParamList() 
    13411341                for param in model.getDispParamList(): 
    1342                     if not model.is_fittable(param) and \ 
     1342                    if '.' in param and param in param_list: 
     1343                        # Ensure polydispersity results are displayed 
     1344                        p1, p2 = param.split('.') 
     1345                        if not model.is_fittable(p1) and not (p2 == 'width' and param in res.param_list)\ 
     1346                            and param in param_list: 
     1347                            param_list.remove(param) 
     1348                    elif not model.is_fittable(param) and \ 
    13431349                        param in param_list: 
    13441350                        param_list.remove(param) 
     
    13611367                    batch_outputs["Chi2"].append(ERROR) 
    13621368                    for param in param_list: 
    1363                         # save value of  fixed parameters 
     1369                        # Save value of  fixed parameters 
    13641370                        if param not in res.param_list: 
    13651371                            batch_outputs[str(param)].append(ERROR) 
    13661372                        else: 
    1367                             #save only fitted values 
     1373                            # Save only fitted values 
    13681374                            batch_outputs[param].append(ERROR) 
    13691375                            batch_inputs["error on %s" % str(param)].append(ERROR) 
  • src/sas/sasgui/perspectives/fitting/media/fitting_help.rst

    r05b0bf6 rca383a0  
    195195the :ref:`Advanced_Plugin_Editor` . 
    196196 
     197**SasView version 4.2** made it possible to specify whether a plugin created with  
     198the *New Plugin Model* dialog is actually a form factor P(Q) or a structure factor  
     199S(Q). To do this, simply add one or other of the following lines under the *import*  
     200statements. 
     201 
     202For a form factor:: 
     203 
     204     form_factor = True 
     205          
     206or for a structure factor:: 
     207 
     208     structure_factor = True 
     209          
     210If the plugin is a structure factor it is *also* necessary to add two variables to  
     211the parameter list:: 
     212 
     213     parameters = [  
     214                     ['radius_effective', '', 1, [0.0, numpy.inf], 'volume', ''], 
     215                     ['volfraction', '', 1, [0.0, 1.0], '', ''], 
     216                     [...], 
     217 
     218and to the declarations of the functions Iq and Iqxy::: 
     219 
     220     def Iq(x , radius_effective, volfraction, ...): 
     221 
     222     def Iqxy(x, y, radius_effective, volfraction, ...): 
     223 
     224Such a plugin should then be available in the S(Q) drop-down box on a FitPage (once  
     225a P(Q) model has been selected). 
     226 
    197227Sum|Multi(p1,p2) 
    198228^^^^^^^^^^^^^^^^ 
     
    206236or:: 
    207237 
    208      Plugin Model = scale_factor * model_1 /* model_2 + background 
     238     Plugin Model = scale_factor * (model1 * model2) + background 
    209239 
    210240In the *Easy Sum/Multi Editor* give the new model a function name and brief 
    211241description (to appear under the *Details* button on the *FitPage*). Then select 
    212242two existing models, as p1 and p2, and the required operator, '+' or '*' between 
    213 them. Finally, click the *Apply* button to generate the model and then click *Close*. 
    214  
    215 Any changes to a plugin model generated in this way only become effective *after* it is re-selected from the model drop-down menu on the FitPage. 
     243them. Finally, click the *Apply* button to generate and test the model and then click *Close*. 
     244 
     245Any changes to a plugin model generated in this way only become effective *after* it is re-selected  
     246from the plugin models drop-down menu on the FitPage. If the model is not listed you can force a  
     247recompilation of the plugins by selecting *Fitting* > *Plugin Model Operations* > *Load Plugin Models*. 
     248 
     249**SasView version 4.2** introduced a much simplified and more extensible structure for plugin models  
     250generated through the Easy Sum/Multi Editor. For example, the code for a combination of a sphere model  
     251with a power law model now looks like this:: 
     252 
     253     from sasmodels.core import load_model_info 
     254     from sasmodels.sasview_model import make_model_from_info 
     255      
     256     model_info = load_model_info('sphere+power_law') 
     257     model_info.name = 'MyPluginModel' 
     258     model_info.description = 'sphere + power_law' 
     259     Model = make_model_from_info(model_info) 
     260 
     261To change the models or operators contributing to this plugin it is only necessary to edit the string  
     262in the brackets after *load_model_info*, though it would also be a good idea to update the model name  
     263and description too!!! 
     264 
     265The model specification string can handle multiple models and combinations of operators (+ or *) which  
     266are processed according to normal conventions. Thus 'model1+model2*model3' would be valid and would  
     267multiply model2 by model3 before adding model1. In this example, parameters in the *FitPage* would be  
     268prefixed A (for model2), B (for model3) and C (for model1). Whilst this might appear a little  
     269confusing, unless you were creating a plugin model from multiple instances of the same model the parameter  
     270assignments ought to be obvious when you load the plugin. 
     271 
     272If you need to include another plugin model in the model specification string, just prefix the name of  
     273that model with *custom*. For instance:: 
     274 
     275     sphere+custom.MyPluginModel 
     276 
     277To create a P(Q)*\S(Q) model use the @ symbol instead of * like this:: 
     278 
     279     sphere@hardsphere 
     280      
     281This streamlined approach to building complex plugin models from existing library models, or models  
     282available on the *Model Marketplace*, also permits the creation of P(Q)*\S(Q) plugin models, something  
     283that was not possible in earlier versions of SasView.  
    216284 
    217285.. _Advanced_Plugin_Editor: 
  • src/sas/sasgui/perspectives/fitting/media/plugin.rst

    r72100ee re081946  
    1818* By writing a model from scratch outside of SasView (only recommended for 
    1919  code monkeys!) 
     20 
     21**What follows below is quite technical. If you just want a helping hand to get  
     22started creating your own models see** :ref:`Adding_your_own_models`. 
    2023 
    2124Overview 
Note: See TracChangeset for help on using the changeset viewer.