Changeset 8d3d20a in sasview for src/sas/sasgui/perspectives


Ignore:
Timestamp:
Oct 6, 2016 12:35:24 PM (8 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, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
Children:
4c3be25
Parents:
0639476 (diff), e32e35a (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:
Andrew Jackson <andrew.jackson@…> (10/06/16 12:35:24)
git-committer:
GitHub <noreply@…> (10/06/16 12:35:24)
Message:

Merge pull request #11 from SasView?/corfunc

Implement Correlation Function Perspective

Location:
src/sas/sasgui/perspectives
Files:
19 added
11 edited

Legend:

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

    re4c897b rc65a265  
    1717from wx.lib.scrolledpanel import ScrolledPanel 
    1818 
    19 import sasmodels.sasview_model 
     19from sasmodels.weights import MODELS as POLYDISPERSITY_MODELS 
     20 
    2021from sas.sasgui.guiframe.panel_base import PanelBase 
    21 from sas.sasgui.guiframe.utils import format_number, check_float, IdList 
     22from sas.sasgui.guiframe.utils import format_number, check_float, IdList, check_int 
    2223from sas.sasgui.guiframe.events import PanelOnFocusEvent 
    2324from sas.sasgui.guiframe.events import StatusEvent 
     
    626627        self.disp_help_bt.Bind(wx.EVT_BUTTON, self.on_pd_help_clicked, 
    627628                               id=self.disp_help_bt.GetId()) 
    628         self.disp_help_bt.SetToolTipString("Helps for Polydispersion.") 
     629        self.disp_help_bt.SetToolTipString("Help for polydispersion.") 
    629630 
    630631        self.Bind(wx.EVT_RADIOBUTTON, self._set_dipers_Param, 
     
    932933        if len(self._disp_obj_dict) > 0: 
    933934            for k, v in self._disp_obj_dict.iteritems(): 
    934                 self.state._disp_obj_dict[k] = v 
     935                self.state._disp_obj_dict[k] = v.type 
    935936 
    936937            self.state.values = copy.deepcopy(self.values) 
     
    10091010            if len(self._disp_obj_dict) > 0: 
    10101011                for k, v in self._disp_obj_dict.iteritems(): 
    1011                     self.state._disp_obj_dict[k] = v 
     1012                    self.state._disp_obj_dict[k] = v.type 
    10121013 
    10131014            self.state.values = copy.deepcopy(self.values) 
     
    11231124                                                    state.disp_cb_dict[item]) 
    11241125                        # Create the dispersion objects 
    1125                         from sas.models.dispersion_models import ArrayDispersion 
    1126                         disp_model = ArrayDispersion() 
     1126                        disp_model = POLYDISPERSITY_MODELS['array']() 
    11271127                        if hasattr(state, "values") and \ 
    11281128                                 self.disp_cb_dict[item].GetValue() == True: 
     
    13791379        self.weights = copy.deepcopy(state.weights) 
    13801380 
    1381         for key, disp in state._disp_obj_dict.iteritems(): 
    1382             # From saved file, disp_model can not be sent in model obj. 
    1383             # it will be sent as a string here, then converted to model object. 
    1384             if disp.__class__.__name__ == 'str': 
    1385                 disp_model = None 
    1386                 com_str = "from sasmodels.weights " 
    1387                 com_str += "import %s as disp_func \ndisp_model = disp_func()" 
    1388                 exec com_str % disp 
    1389             else: 
    1390                 disp_model = disp 
     1381        for key, disp_type in state._disp_obj_dict.iteritems(): 
     1382            #disp_model = disp 
     1383            disp_model = POLYDISPERSITY_MODELS[disp_type]() 
    13911384            self._disp_obj_dict[key] = disp_model 
    13921385            param_name = key.split('.')[0] 
     
    15041497            is_2Ddata = True 
    15051498        if self.model != None: 
    1506             try: 
    1507                 is_modified = self._check_value_enter(self.fittable_param, 
    1508                                                       is_modified) 
    1509                 is_modified = self._check_value_enter(self.fixed_param, 
    1510                                                       is_modified) 
    1511                 is_modified = self._check_value_enter(self.parameters, 
    1512                                                       is_modified) 
    1513             except Exception: 
    1514                 logging.error(traceback.format_exc()) 
     1499            is_modified = (self._check_value_enter(self.fittable_param) 
     1500                           or self._check_value_enter(self.fixed_param) 
     1501                           or self._check_value_enter(self.parameters)) 
    15151502 
    15161503            # Here we should check whether the boundaries have been modified. 
     
    15331520            else: 
    15341521                self.fitrange = False 
    1535  
    1536             if not self.data.is_data: 
    1537                 is_modified = True 
    15381522 
    15391523            ## if any value is modify draw model with new value 
     
    15521536                self._draw_model() 
    15531537                self.Refresh() 
     1538 
     1539        logging.info("is_modified flag set to %g",is_modified) 
    15541540        return is_modified 
    15551541 
     
    15611547        flag = True 
    15621548        self.fitrange = True 
    1563         is_modified = False 
    15641549 
    15651550        #wx.PostEvent(self._manager.parent, StatusEvent(status=" \ 
     
    15741559                                                                [self.data]) 
    15751560            ##Check the values 
    1576             self._check_value_enter(self.fittable_param, is_modified) 
    1577             self._check_value_enter(self.fixed_param, is_modified) 
    1578             self._check_value_enter(self.parameters, is_modified) 
     1561            self._check_value_enter(self.fittable_param) 
     1562            self._check_value_enter(self.fixed_param) 
     1563            self._check_value_enter(self.parameters) 
    15791564 
    15801565            # If qmin and qmax have been modified, update qmin and qmax and 
     
    16601645        return flag 
    16611646 
    1662     def _is_modified(self, is_modified): 
    1663         """ 
    1664         return to self._is_modified 
    1665         """ 
    1666         return is_modified 
    1667  
    16681647    def _reset_parameters_state(self, listtorestore, statelist): 
    16691648        """ 
     
    19641943        wx.PostEvent(self.parent, StatusEvent(status=msg)) 
    19651944        # Flag to register when a parameter has changed. 
    1966         #is_modified = False 
    19671945        if tcrtl.GetValue().lstrip().rstrip() != "": 
    19681946            try: 
     
    19941972                    if temp_npts != self.num_points: 
    19951973                        self.num_points = temp_npts 
    1996                         #is_modified = True 
    19971974                else: 
    19981975                    msg = "Cannot plot: No points in Q range!!!  " 
     
    21702147        self.Layout() 
    21712148 
     2149 
    21722150    def _validate_qrange(self, qmin_ctrl, qmax_ctrl): 
    21732151        """ 
     
    22762254        return flag 
    22772255 
    2278     def _check_value_enter(self, list, modified): 
     2256    def _check_value_enter(self, list): 
    22792257        """ 
    22802258        :param list: model parameter and panel info 
     
    22862264                parameter's maximum value , 
    22872265                parameter's units] 
    2288         """ 
    2289         is_modified = modified 
    2290         if len(list) == 0: 
    2291             return is_modified 
     2266 
     2267        Returns True if the model parameters have changed. 
     2268        """ 
     2269        is_modified = False 
    22922270        for item in list: 
    22932271            #skip angle parameters for 1D 
    2294             if not self.enable2D: 
    2295                 if item in self.orientation_params: 
     2272            if not self.enable2D and item in self.orientation_params: 
     2273                continue 
     2274 
     2275            value_ctrl = item[2] 
     2276            if not value_ctrl.IsEnabled(): 
     2277                # ArrayDispersion disables PD, Min, Max, Npts, Nsigs 
     2278                continue 
     2279 
     2280            name = item[1] 
     2281            value_str = value_ctrl.GetValue().strip() 
     2282            if name.endswith(".npts"): 
     2283                validity = check_int(value_ctrl) 
     2284                if not validity: 
    22962285                    continue 
    2297             #try: 
    2298             name = str(item[1]) 
    2299  
    2300             if string.find(name, ".npts") == -1 and \ 
    2301                                         string.find(name, ".nsigmas") == -1: 
    2302                 ## check model parameters range 
    2303                 param_min = None 
    2304                 param_max = None 
    2305  
    2306                 ## check minimun value 
    2307                 if item[5] != None and item[5] != "": 
    2308                     if item[5].GetValue().lstrip().rstrip() != "": 
    2309                         try: 
    2310                             param_min = float(item[5].GetValue()) 
    2311                             if not self._validate_qrange(item[5], item[2]): 
    2312                                 if numpy.isfinite(param_min): 
    2313                                     item[2].SetValue(format_number(param_min)) 
    2314  
    2315                             item[5].SetBackgroundColour(wx.WHITE) 
    2316                             item[2].SetBackgroundColour(wx.WHITE) 
    2317  
    2318                         except: 
    2319                             msg = "Wrong fit parameter range entered" 
    2320                             wx.PostEvent(self._manager.parent, 
    2321                                          StatusEvent(status=msg)) 
    2322                             raise ValueError, msg 
    2323                         is_modified = True 
    2324                 ## check maximum value 
    2325                 if item[6] != None and item[6] != "": 
    2326                     if item[6].GetValue().lstrip().rstrip() != "": 
    2327                         try: 
    2328                             param_max = float(item[6].GetValue()) 
    2329                             if not self._validate_qrange(item[2], item[6]): 
    2330                                 if numpy.isfinite(param_max): 
    2331                                     item[2].SetValue(format_number(param_max)) 
    2332  
    2333                             item[6].SetBackgroundColour(wx.WHITE) 
    2334                             item[2].SetBackgroundColour(wx.WHITE) 
    2335                         except: 
    2336                             msg = "Wrong Fit parameter range entered " 
    2337                             wx.PostEvent(self._manager.parent, 
    2338                                          StatusEvent(status=msg)) 
    2339                             raise ValueError, msg 
    2340                         is_modified = True 
    2341  
    2342                 if param_min != None and param_max != None: 
    2343                     if not self._validate_qrange(item[5], item[6]): 
    2344                         msg = "Wrong Fit range entered for parameter " 
    2345                         msg += "name %s of model %s " % (name, self.model.name) 
    2346                         wx.PostEvent(self._manager.parent, 
    2347                                      StatusEvent(status=msg)) 
    2348  
    2349                 if name in self.model.details.keys(): 
    2350                     self.model.details[name][1:3] = param_min, param_max 
    2351                     is_modified = True 
    2352                 else: 
    2353                     self.model.details[name] = ["", param_min, param_max] 
    2354                     is_modified = True 
    2355             try: 
    2356                 # Check if the textctr is enabled 
    2357                 if item[2].IsEnabled(): 
    2358                     value = float(item[2].GetValue()) 
    2359                     item[2].SetBackgroundColour("white") 
    2360                     # If the value of the parameter has changed, 
    2361                     # +update the model and set the is_modified flag 
    2362                     if value != self.model.getParam(name) and \ 
    2363                                                 numpy.isfinite(value): 
    2364                         self.model.setParam(name, value) 
    2365             except: 
    2366                 item[2].SetBackgroundColour("pink") 
    2367                 msg = "Wrong Fit parameter value entered " 
    2368                 wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 
     2286                value = int(value_str) 
     2287 
     2288            elif name.endswith(".nsigmas"): 
     2289                validity = check_float(value_ctrl) 
     2290                if not validity: 
     2291                    continue 
     2292                value = float(value_str) 
     2293 
     2294            else:  # value or polydispersity 
     2295 
     2296                # Check that min, max and value are floats 
     2297                min_ctrl, max_ctrl = item[5], item[6] 
     2298                min_str = min_ctrl.GetValue().strip() 
     2299                max_str = max_ctrl.GetValue().strip() 
     2300                validity = check_float(value_ctrl) 
     2301                if min_str != "": 
     2302                    validity = validity and check_float(min_ctrl) 
     2303                if max_str != "": 
     2304                    validity = validity and check_float(max_ctrl) 
     2305                if not validity: 
     2306                    continue 
     2307 
     2308                # Check that min is less than max 
     2309                low = -numpy.inf if min_str == "" else float(min_str) 
     2310                high = numpy.inf if max_str == "" else float(max_str) 
     2311                if high < low: 
     2312                    min_ctrl.SetBackgroundColour("pink") 
     2313                    min_ctrl.Refresh() 
     2314                    max_ctrl.SetBackgroundColour("pink") 
     2315                    max_ctrl.Refresh() 
     2316                    #msg = "Invalid fit range for %s: min must be smaller than max"%name 
     2317                    #wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 
     2318                    continue 
     2319 
     2320                # Force value between min and max 
     2321                value = float(value_str) 
     2322                if value < low: 
     2323                    value = low 
     2324                    value_ctrl.SetValue(format_number(value)) 
     2325                elif value > high: 
     2326                    value = high 
     2327                    value_ctrl.SetValue(format_number(value)) 
     2328 
     2329                if name not in self.model.details.keys(): 
     2330                    self.model.details[name] = ["", None, None] 
     2331                old_low, old_high = self.model.details[name][1:3] 
     2332                if old_low != low or old_high != high: 
     2333                    # The configuration has changed but it won't change the 
     2334                    # computed curve so no need to set is_modified to True 
     2335                    #is_modified = True 
     2336                    self.model.details[name][1:3] = low, high 
     2337 
     2338            # Update value in model if it has changed 
     2339            if value != self.model.getParam(name): 
     2340                self.model.setParam(name, value) 
     2341                is_modified = True 
    23692342 
    23702343        return is_modified 
     
    25392512                self._disp_obj_dict[name1] = disp_model 
    25402513                self.model.set_dispersion(param_name, disp_model) 
    2541                 self.state._disp_obj_dict[name1] = disp_model 
     2514                self.state._disp_obj_dict[name1] = disp_model.type 
    25422515 
    25432516                value1 = str(format_number(self.model.getParam(name1), True)) 
     
    25622535                        item[0].Enable() 
    25632536                        item[2].Enable() 
     2537                        item[3].Show(True) 
     2538                        item[4].Show(True) 
    25642539                        item[5].Enable() 
    25652540                        item[6].Enable() 
     
    26542629        self._disp_obj_dict[name] = disp 
    26552630        self.model.set_dispersion(name.split('.')[0], disp) 
    2656         self.state._disp_obj_dict[name] = disp 
     2631        self.state._disp_obj_dict[name] = disp.type 
    26572632        self.values[name] = values 
    26582633        self.weights[name] = weights 
     
    27222697        :param disp_function: dispersion distr. function 
    27232698        """ 
    2724         # List of the poly_model name in the combobox 
    2725         list = ["RectangleDispersion", "ArrayDispersion", 
    2726                 "LogNormalDispersion", "GaussianDispersion", 
    2727                 "SchulzDispersion"] 
    2728  
    27292699        # Find the selection 
    2730         try: 
    2731             selection = list.index(disp_func.__class__.__name__) 
    2732             return selection 
    2733         except: 
    2734             return 3 
     2700        if disp_func is not None: 
     2701            try: 
     2702                return POLYDISPERSITY_MODELS.values().index(disp_func.__class__) 
     2703            except ValueError: 
     2704                pass  # Fall through to default class 
     2705        return POLYDISPERSITY_MODELS.keys().index('gaussian') 
    27352706 
    27362707    def on_reset_clicked(self, event): 
     
    33193290                    pd = content[name][1] 
    33203291                    if name.count('.') > 0: 
     3292                        # If this is parameter.width, then pd may be a floating 
     3293                        # point value or it may be an array distribution. 
     3294                        # Nothing to do for parameter.npts or parameter.nsigmas. 
    33213295                        try: 
    33223296                            float(pd) 
    3323                         except: 
     3297                            if name.endswith('.npts'): 
     3298                                pd = int(pd) 
     3299                        except Exception: 
    33243300                            #continue 
    33253301                            if not pd and pd != '': 
     
    33293305                        # Only array func has pd == '' case. 
    33303306                        item[2].Enable(False) 
     3307                    else: 
     3308                        item[2].Enable(True) 
    33313309                    if item[2].__class__.__name__ == "ComboBox": 
    33323310                        if content[name][1] in self.model.fun_list: 
     
    33553333                        pd = value[0] 
    33563334                        if name.count('.') > 0: 
     3335                            # If this is parameter.width, then pd may be a floating 
     3336                            # point value or it may be an array distribution. 
     3337                            # Nothing to do for parameter.npts or parameter.nsigmas. 
    33573338                            try: 
    33583339                                pd = float(pd) 
     3340                                if name.endswith('.npts'): 
     3341                                    pd = int(pd) 
    33593342                            except: 
    33603343                                #continue 
     
    33653348                            # Only array func has pd == '' case. 
    33663349                            item[2].Enable(False) 
     3350                        else: 
     3351                            item[2].Enable(True) 
    33673352                        if item[2].__class__.__name__ == "ComboBox": 
    33683353                            if value[0] in self.model.fun_list: 
     
    33843369        Helps get paste for poly function 
    33853370 
    3386         :param item: Gui param items 
    3387         :param value: the values for parameter ctrols 
    3388         """ 
    3389         is_array = False 
    3390         if len(value[1]) > 0: 
    3391             # Only for dispersion func.s 
    3392             try: 
    3393                 item[7].SetValue(value[1]) 
    3394                 selection = item[7].GetCurrentSelection() 
    3395                 name = item[7].Name 
    3396                 param_name = name.split('.')[0] 
    3397                 dispersity = item[7].GetClientData(selection) 
    3398                 disp_model = dispersity() 
    3399                 # Only for array disp 
    3400                 try: 
    3401                     pd_vals = numpy.array(value[2]) 
    3402                     pd_weights = numpy.array(value[3]) 
    3403                     if len(pd_vals) > 0 and len(pd_vals) > 0: 
    3404                         if len(pd_vals) == len(pd_weights): 
    3405                             self._set_disp_array_cb(item=item) 
    3406                             self._set_array_disp_model(name=name, 
    3407                                                        disp=disp_model, 
    3408                                                        values=pd_vals, 
    3409                                                        weights=pd_weights) 
    3410                             is_array = True 
    3411                 except Exception: 
    3412                     logging.error(traceback.format_exc()) 
    3413                 if not is_array: 
    3414                     self._disp_obj_dict[name] = disp_model 
    3415                     self.model.set_dispersion(name, 
    3416                                               disp_model) 
    3417                     self.state._disp_obj_dict[name] = \ 
    3418                                               disp_model 
    3419                     self.model.set_dispersion(param_name, disp_model) 
    3420                     self.state.values = self.values 
    3421                     self.state.weights = self.weights 
    3422                     self.model._persistency_dict[param_name] = \ 
    3423                                             [self.state.values, 
    3424                                              self.state.weights] 
    3425  
    3426             except Exception: 
    3427                 logging.error(traceback.format_exc()) 
    3428                 print "Error in BasePage._paste_poly_help: %s" % \ 
    3429                                         sys.exc_info()[1] 
    3430  
    3431     def _set_disp_array_cb(self, item): 
     3371        *item* is the parameter name 
     3372 
     3373        *value* depends on which parameter is being processed, and whether it 
     3374        has array polydispersity. 
     3375 
     3376        For parameters without array polydispersity: 
     3377 
     3378            parameter => ['FLOAT', ''] 
     3379            parameter.width => ['FLOAT', 'DISTRIBUTION', ''] 
     3380            parameter.npts => ['FLOAT', ''] 
     3381            parameter.nsigmas => ['FLOAT', ''] 
     3382 
     3383        For parameters with array polydispersity: 
     3384 
     3385            parameter => ['FLOAT', ''] 
     3386            parameter.width => ['FILENAME', 'array', [x1, ...], [w1, ...]] 
     3387            parameter.npts => ['FLOAT', ''] 
     3388            parameter.nsigmas => ['FLOAT', ''] 
     3389        """ 
     3390        # Do nothing if not setting polydispersity 
     3391        if len(value[1]) == 0: 
     3392            return 
     3393 
     3394        try: 
     3395            name = item[7].Name 
     3396            param_name = name.split('.')[0] 
     3397            item[7].SetValue(value[1]) 
     3398            selection = item[7].GetCurrentSelection() 
     3399            dispersity = item[7].GetClientData(selection) 
     3400            disp_model = dispersity() 
     3401 
     3402            if value[1] == 'array': 
     3403                pd_vals = numpy.array(value[2]) 
     3404                pd_weights = numpy.array(value[3]) 
     3405                if len(pd_vals) == 0 or len(pd_vals) != len(pd_weights): 
     3406                    msg = ("bad array distribution parameters for %s" 
     3407                           % param_name) 
     3408                    raise ValueError(msg) 
     3409                self._set_disp_cb(True, item=item) 
     3410                self._set_array_disp_model(name=name, 
     3411                                           disp=disp_model, 
     3412                                           values=pd_vals, 
     3413                                           weights=pd_weights) 
     3414            else: 
     3415                self._set_disp_cb(False, item=item) 
     3416                self._disp_obj_dict[name] = disp_model 
     3417                self.model.set_dispersion(param_name, disp_model) 
     3418                self.state._disp_obj_dict[name] = disp_model.type 
     3419                # TODO: It's not an array, why update values and weights? 
     3420                self.model._persistency_dict[param_name] = \ 
     3421                    [self.values, self.weights] 
     3422                self.state.values = self.values 
     3423                self.state.weights = self.weights 
     3424 
     3425        except Exception: 
     3426            logging.error(traceback.format_exc()) 
     3427            print "Error in BasePage._paste_poly_help: %s" % \ 
     3428                                    sys.exc_info()[1] 
     3429 
     3430    def _set_disp_cb(self, isarray, item): 
    34323431        """ 
    34333432        Set cb for array disp 
    34343433        """ 
    3435         item[0].SetValue(False) 
    3436         item[0].Enable(False) 
    3437         item[2].Enable(False) 
    3438         item[3].Show(False) 
    3439         item[4].Show(False) 
    3440         item[5].SetValue('') 
    3441         item[5].Enable(False) 
    3442         item[6].SetValue('') 
    3443         item[6].Enable(False) 
     3434        if isarray: 
     3435            item[0].SetValue(False) 
     3436            item[0].Enable(False) 
     3437            item[2].Enable(False) 
     3438            item[3].Show(False) 
     3439            item[4].Show(False) 
     3440            item[5].SetValue('') 
     3441            item[5].Enable(False) 
     3442            item[6].SetValue('') 
     3443            item[6].Enable(False) 
     3444        else: 
     3445            item[0].Enable() 
     3446            item[2].Enable() 
     3447            item[3].Show(True) 
     3448            item[4].Show(True) 
     3449            item[5].Enable() 
     3450            item[6].Enable() 
    34443451 
    34453452    def update_pinhole_smear(self): 
  • src/sas/sasgui/perspectives/fitting/batchfitpage.py

    rfc18690 ree4b3cb  
    256256#         if self.model != None:            
    257257#             ##Check the values 
    258 #             self._check_value_enter( self.fittable_param, is_modified) 
    259 #             self._check_value_enter( self.fixed_param, is_modified) 
    260 #             self._check_value_enter( self.parameters, is_modified) 
     258#             self._check_value_enter( self.fittable_param) 
     259#             self._check_value_enter( self.fixed_param) 
     260#             self._check_value_enter( self.parameters) 
    261261#  
    262262#             # If qmin and qmax have been modified, update qmin and qmax and  
  • src/sas/sasgui/perspectives/fitting/fitpage.py

    r934ce649 r6c382da  
    1010import math 
    1111import time 
     12import traceback 
    1213 
    1314from sasmodels.weights import MODELS as POLYDISPERSITY_MODELS 
     
    13651366            try: 
    13661367                tcrtl.SetBackgroundColour(wx.WHITE) 
    1367                 self._check_value_enter(self.fittable_param, is_modified) 
    1368                 self._check_value_enter(self.parameters, is_modified) 
     1368                self._check_value_enter(self.fittable_param) 
     1369                self._check_value_enter(self.parameters) 
    13691370            except: 
    13701371                tcrtl.SetBackgroundColour("pink") 
     
    20582059            msg = "Error: This model state has missing or outdated " 
    20592060            msg += "information.\n" 
    2060             msg += "%s" % (sys.exc_value) 
     2061            msg += traceback.format_exc() 
    20612062            wx.PostEvent(self._manager.parent, 
    20622063                         StatusEvent(status=msg, info="error")) 
  • src/sas/sasgui/perspectives/fitting/fitting.py

    r7673ecd rca4d985  
    313313        """ 
    314314        event_id = event.GetId() 
    315         self.update_custom_combo()         
     315        self.update_custom_combo() 
    316316 
    317317    def update_custom_combo(self): 
     
    342342                                page.formfactorbox.SetLabel(current_val) 
    343343        except: 
    344             pass 
    345  
     344            logging.error("update_custom_combo: %s", sys.exc_value) 
    346345 
    347346    def set_edit_menu(self, owner): 
     
    16661665        wx.PostEvent(self.parent, StatusEvent(status=msg, type="update")) 
    16671666 
     1667    def create_theory_1D(self, x, y, page_id, model, data, state, 
     1668                         data_description, data_id, dy=None): 
     1669        """ 
     1670            Create a theory object associate with an existing Data1D 
     1671            and add it to the data manager. 
     1672            @param x: x-values of the data 
     1673            @param y: y_values of the data 
     1674            @param page_id: fit page ID 
     1675            @param model: model used for fitting 
     1676            @param data: Data1D object to create the theory for 
     1677            @param state: model state 
     1678            @param data_description: title to use in the data manager 
     1679            @param data_id: unique data ID 
     1680        """ 
     1681        new_plot = Data1D(x=x, y=y) 
     1682        if dy is None: 
     1683            new_plot.is_data = False 
     1684            new_plot.dy = numpy.zeros(len(y)) 
     1685            # If this is a theory curve, pick the proper symbol to make it a curve 
     1686            new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM 
     1687        else: 
     1688            new_plot.is_data = True 
     1689            new_plot.dy = dy 
     1690        new_plot.interactive = True 
     1691        new_plot.dx = None 
     1692        new_plot.dxl = None 
     1693        new_plot.dxw = None 
     1694        _yaxis, _yunit = data.get_yaxis() 
     1695        _xaxis, _xunit = data.get_xaxis() 
     1696        new_plot.title = data.name 
     1697        new_plot.group_id = data.group_id 
     1698        if new_plot.group_id == None: 
     1699            new_plot.group_id = data.group_id 
     1700        new_plot.id = data_id 
     1701        # Find if this theory was already plotted and replace that plot given 
     1702        # the same id 
     1703        self.page_finder[page_id].get_theory_data(fid=data.id) 
     1704 
     1705        if data.is_data: 
     1706            data_name = str(data.name) 
     1707        else: 
     1708            data_name = str(model.__class__.__name__) 
     1709 
     1710        new_plot.name = data_description + " [" + data_name + "]" 
     1711        new_plot.xaxis(_xaxis, _xunit) 
     1712        new_plot.yaxis(_yaxis, _yunit) 
     1713        self.page_finder[page_id].set_theory_data(data=new_plot, 
     1714                                                  fid=data.id) 
     1715        self.parent.update_theory(data_id=data.id, theory=new_plot, 
     1716                                   state=state) 
     1717        return new_plot 
     1718 
    16681719    def _complete1D(self, x, y, page_id, elapsed, index, model, 
    16691720                    weight=None, fid=None, 
    16701721                    toggle_mode_on=False, state=None, 
    16711722                    data=None, update_chisqr=True, 
    1672                     source='model', plot_result=True): 
    1673         """ 
    1674         Complete plotting 1D data 
     1723                    source='model', plot_result=True, 
     1724                    unsmeared_model=None, unsmeared_data=None, 
     1725                    unsmeared_error=None, sq_model=None, pq_model=None): 
     1726        """ 
     1727            Complete plotting 1D data 
     1728            @param unsmeared_model: fit model, without smearing 
     1729            @param unsmeared_data: data, rescaled to unsmeared model 
     1730            @param unsmeared_error: data error, rescaled to unsmeared model 
    16751731        """ 
    16761732        try: 
    16771733            numpy.nan_to_num(y) 
    1678  
    1679             new_plot = Data1D(x=x, y=y) 
    1680             new_plot.is_data = False 
    1681             new_plot.dy = numpy.zeros(len(y)) 
    1682             new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM 
    1683             _yaxis, _yunit = data.get_yaxis() 
    1684             _xaxis, _xunit = data.get_xaxis() 
    1685             new_plot.title = data.name 
    1686  
    1687             new_plot.group_id = data.group_id 
    1688             if new_plot.group_id == None: 
    1689                 new_plot.group_id = data.group_id 
    1690             new_plot.id = str(page_id) + " " + data.name 
    1691             #if new_plot.id in self.color_dict: 
    1692             #    new_plot.custom_color = self.color_dict[new_plot.id] 
    1693             #find if this theory was already plotted and replace that plot given 
    1694             #the same id 
    1695             self.page_finder[page_id].get_theory_data(fid=data.id) 
    1696  
    1697             if data.is_data: 
    1698                 data_name = str(data.name) 
    1699             else: 
    1700                 data_name = str(model.__class__.__name__) 
    1701  
    1702             new_plot.name = model.name + " [" + data_name + "]" 
    1703             new_plot.xaxis(_xaxis, _xunit) 
    1704             new_plot.yaxis(_yaxis, _yunit) 
    1705             self.page_finder[page_id].set_theory_data(data=new_plot, 
    1706                                                       fid=data.id) 
    1707             self.parent.update_theory(data_id=data.id, theory=new_plot, 
    1708                                        state=state) 
     1734            new_plot = self.create_theory_1D(x, y, page_id, model, data, state, 
     1735                                             data_description=model.name, 
     1736                                             data_id=str(page_id) + " " + data.name) 
     1737            if unsmeared_model is not None: 
     1738                self.create_theory_1D(x, unsmeared_model, page_id, model, data, state, 
     1739                                      data_description=model.name + " unsmeared", 
     1740                                      data_id=str(page_id) + " " + data.name + " unsmeared") 
     1741 
     1742                self.create_theory_1D(x, unsmeared_data, page_id, model, data, state, 
     1743                                      data_description="Data unsmeared", 
     1744                                      data_id="Data  " + data.name + " unsmeared", 
     1745                                      dy=unsmeared_error) 
     1746                 
     1747            if sq_model is not None and pq_model is not None: 
     1748                self.create_theory_1D(x, sq_model, page_id, model, data, state, 
     1749                                      data_description=model.name + " S(q)", 
     1750                                      data_id=str(page_id) + " " + data.name + " S(q)") 
     1751                self.create_theory_1D(x, pq_model, page_id, model, data, state, 
     1752                                      data_description=model.name + " P(q)", 
     1753                                      data_id=str(page_id) + " " + data.name + " P(q)") 
     1754 
     1755 
    17091756            current_pg = self.fit_panel.get_page_by_id(page_id) 
    17101757            title = new_plot.title 
  • src/sas/sasgui/perspectives/fitting/media/fitting.rst

    rd85c194 r05829fb  
    1818 
    1919   Information on the SasView Optimisers <optimizer.rst> 
    20     
     20 
     21   Writing a Plugin <plugin.rst> 
  • src/sas/sasgui/perspectives/fitting/media/fitting_help.rst

    rb64b87c r05829fb  
    132132* By :ref:`Writing_a_Plugin` 
    133133 
    134 *NB: Because of the way these options are implemented, it is not possible for them* 
    135 *to use the polydispersity algorithms in SasView. Only models in the model library* 
    136 *can do this. At the time of writing (Release 3.1.0) work is in hand to make it* 
    137 *easier to add new models to the model library.* 
    138  
    139134.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
    140135 
     
    163158the :ref:`Advanced` option. 
    164159 
     160*NB: "Fit Parameters" has been split into two sections, those which can be 
     161polydisperse (shape and orientation parameters) and those which are not 
     162(scattering length densities, for example).* 
     163 
    165164Sum|Multi(p1,p2) 
    166165^^^^^^^^^^^^^^^^ 
     
    192191*Advanced Custom Model Editor*. 
    193192 
    194 *NB: Unless you are confident about what you are doing, it is recommended that you* 
    195 *only modify lines denoted with the ## <----- comments!* 
     193See :ref:`Writing_a_Plugin` for details on the plugin format. 
     194 
     195*NB: Sum/Product models are still using the SasView 3.x model format.  Unless 
     196you are confident about what you are doing, it is recommended that you 
     197only modify lines denoted with the ## <----- comments!* 
    196198 
    197199When editing is complete, select *Run -> Compile* from the *Model Editor* menu bar. An 
     
    211213 
    212214*NB: Custom models shipped with SasView cannot be removed in this way.* 
    213  
    214 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
    215  
    216 .. _Writing_a_Plugin: 
    217  
    218 Writing a Plugin 
    219 ---------------- 
    220  
    221 Advanced users can write their own model in Python and save it to the the SasView 
    222 *plugin_models* folder 
    223  
    224   *C:\\Users\\[username]\\.sasview\\plugin_models* - (on Windows) 
    225  
    226 in .py format. The next time SasView is started it will compile the plugin and add 
    227 it to the list of *Customized Models*. 
    228  
    229 It is recommended that existing plugin models be used as templates. 
    230215 
    231216.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
  • src/sas/sasgui/perspectives/fitting/model_thread.py

    r934ce649 rca4d985  
    77import math 
    88from sas.sascalc.data_util.calcthread import CalcThread 
     9from sas.sascalc.fit.MultiplicationModel import MultiplicationModel 
    910 
    1011class Calc2D(CalcThread): 
     
    166167        index = (self.qmin <= self.data.x) & (self.data.x <= self.qmax) 
    167168 
     169        # If we use a smearer, also return the unsmeared model 
     170        unsmeared_output = None 
     171        unsmeared_data = None 
     172        unsmeared_error = None 
    168173        ##smearer the ouput of the plot 
    169174        if self.smearer is not None: 
     
    171176                                                             self.qmax) 
    172177            mask = self.data.x[first_bin:last_bin+1] 
    173             output[first_bin:last_bin+1] = self.model.evalDistribution(mask) 
    174             output = self.smearer(output, first_bin, last_bin) 
     178            unsmeared_output = numpy.zeros((len(self.data.x))) 
     179            unsmeared_output[first_bin:last_bin+1] = self.model.evalDistribution(mask) 
     180            output = self.smearer(unsmeared_output, first_bin, last_bin) 
     181             
     182            # Rescale data to unsmeared model 
     183            unsmeared_data = numpy.zeros((len(self.data.x))) 
     184            unsmeared_error = numpy.zeros((len(self.data.x))) 
     185            unsmeared_data[first_bin:last_bin+1] = self.data.y[first_bin:last_bin+1]\ 
     186                                                    * unsmeared_output[first_bin:last_bin+1]\ 
     187                                                    / output[first_bin:last_bin+1] 
     188            unsmeared_error[first_bin:last_bin+1] = self.data.dy[first_bin:last_bin+1]\ 
     189                                                    * unsmeared_output[first_bin:last_bin+1]\ 
     190                                                    / output[first_bin:last_bin+1] 
     191            unsmeared_output=unsmeared_output[index] 
     192            unsmeared_data=unsmeared_data[index] 
     193            unsmeared_error=unsmeared_error 
    175194        else: 
    176195            output[index] = self.model.evalDistribution(self.data.x[index]) 
     196 
     197        sq_model = None 
     198        pq_model = None 
     199        if isinstance(self.model, MultiplicationModel): 
     200            sq_model = numpy.zeros((len(self.data.x))) 
     201            pq_model = numpy.zeros((len(self.data.x))) 
     202            sq_model[index] = self.model.s_model.evalDistribution(self.data.x[index]) 
     203            pq_model[index] = self.model.p_model.evalDistribution(self.data.x[index]) 
    177204 
    178205        elapsed = time.time() - self.starttime 
     
    187214                      data=self.data, 
    188215                      update_chisqr=self.update_chisqr, 
    189                       source=self.source) 
     216                      source=self.source, 
     217                      unsmeared_model=unsmeared_output, 
     218                      unsmeared_data=unsmeared_data, 
     219                      unsmeared_error=unsmeared_error, 
     220                      pq_model=pq_model, 
     221                      sq_model=sq_model) 
    190222 
    191223    def results(self): 
  • src/sas/sasgui/perspectives/fitting/pagestate.py

    r7673ecd r6c382da  
    2424from xml.dom.minidom import parseString 
    2525from lxml import etree 
     26 
     27import sasmodels.weights 
    2628 
    2729import sas.sascalc.dataloader 
     
    474476                value = content[1] 
    475477            except Exception: 
    476                 logging.error(traceback.format_exc()) 
     478                msg = "Report string expected 'name: value' but got %r"%line 
     479                logging.error(msg) 
    477480            if name.count("State created"): 
    478481                repo_time = "" + value 
     
    516519                        title_name = HEADER % title 
    517520                except Exception: 
    518                     logging.error(traceback.format_exc()) 
     521                    msg = "While parsing 'data: ...'\n" 
     522                    logging.error(msg + traceback.format_exc()) 
    519523            if name == "model name ": 
    520524                try: 
     
    531535                    q_range = CENTRE % q_name 
    532536                except Exception: 
    533                     logging.error(traceback.format_exc()) 
     537                    msg = "While parsing 'Plotting Range: ...'\n" 
     538                    logging.error(msg + traceback.format_exc()) 
    534539        paramval = "" 
    535540        for lines in param_string.split(":"): 
     
    711716        # For self.values ={ disp_param_name: [vals,...],...} 
    712717        # and for self.weights ={ disp_param_name: [weights,...],...} 
    713         value_list = {} 
    714718        for item in LIST_OF_MODEL_ATTRIBUTES: 
    715719            element = newdoc.createElement(item[0]) 
     
    725729 
    726730        # Create doc for the dictionary of self._disp_obj_dic 
    727         for item in DISPERSION_LIST: 
    728             element = newdoc.createElement(item[0]) 
    729             value_list = getattr(self, item[1]) 
    730             for key, val in value_list.iteritems(): 
    731                 value = repr(val) 
     731        for tagname, varname, tagtype in DISPERSION_LIST: 
     732            element = newdoc.createElement(tagname) 
     733            value_list = getattr(self, varname) 
     734            for key, value in value_list.iteritems(): 
    732735                sub_element = newdoc.createElement(key) 
    733736                sub_element.setAttribute('name', str(key)) 
     
    847850                # Recover _disp_obj_dict from xml file 
    848851                self._disp_obj_dict = {} 
    849                 for item in DISPERSION_LIST: 
    850                     # Get node 
    851                     node = get_content("ns:%s" % item[0], entry) 
     852                for tagname, varname, tagtype in DISPERSION_LIST: 
     853                    node = get_content("ns:%s" % tagname, entry) 
    852854                    for attr in node: 
    853                         name = str(attr.get('name')) 
    854                         val = attr.get('value') 
    855                         value = val.split(" instance")[0] 
    856                         disp_name = value.split("<")[1] 
    857                         try: 
    858                             # Try to recover disp_model object from strings 
    859                             com = "from sas.models.dispersion_models " 
    860                             com += "import %s as disp" 
    861                             com_name = disp_name.split(".")[3] 
    862                             exec com % com_name 
    863                             disp_model = disp() 
    864                             attribute = getattr(self, item[1]) 
    865                             attribute[name] = com_name 
    866                         except Exception: 
    867                             logging.error(traceback.format_exc()) 
     855                        parameter = str(attr.get('name')) 
     856                        value = attr.get('value') 
     857                        if value.startswith("<"): 
     858                            try: 
     859                                # <path.to.NamedDistribution object/instance...> 
     860                                cls_name = value[1:].split()[0].split('.')[-1] 
     861                                cls = getattr(sasmodels.weights, cls_name) 
     862                                value = cls.type 
     863                            except Exception: 
     864                                logging.error("unable to load distribution %r for %s" 
     865                                              % (value, parameter)) 
     866                                continue 
     867                        _disp_obj_dict = getattr(self, varname) 
     868                        _disp_obj_dict[parameter] = value 
    868869 
    869870                # get self.values and self.weights dic. if exists 
    870                 for item in LIST_OF_MODEL_ATTRIBUTES: 
    871                     node = get_content("ns:%s" % item[0], entry) 
     871                for tagname, varname in LIST_OF_MODEL_ATTRIBUTES: 
     872                    node = get_content("ns:%s" % tagname, entry) 
    872873                    dic = {} 
    873874                    value_list = [] 
    874875                    for par in node: 
    875876                        name = par.get('name') 
    876                         values = par.text.split('\n') 
     877                        values = par.text.split() 
    877878                        # Get lines only with numbers 
    878879                        for line in values: 
     
    882883                            except Exception: 
    883884                                # pass if line is empty (it happens) 
    884                                 logging.error(traceback.format_exc()) 
     885                                msg = ("Error reading %r from %s %s\n" 
     886                                       % (line, tagname, name)) 
     887                                logging.error(msg + traceback.format_exc()) 
    885888                        dic[name] = numpy.array(value_list) 
    886                     setattr(self, item[1], dic) 
     889                    setattr(self, varname, dic) 
    887890 
    888891    def set_plot_state(self, figs, canvases): 
     
    12311234 
    12321235        except: 
    1233             logging.info("XML document does not contain fitting information.\n %s" % sys.exc_value) 
     1236            logging.info("XML document does not contain fitting information.\n" 
     1237                         + traceback.format_exc()) 
    12341238 
    12351239        return state 
     
    15691573                    if output[ind].run_name is not None\ 
    15701574                        and len(output[ind].run_name) != 0: 
    1571                         name = output[ind].run_name 
     1575                        if isinstance(output[ind].run_name, dict): 
     1576                            name = output[ind].run_name.keys()[0] 
     1577                        else: 
     1578                            name = output[ind].run_name 
    15721579                    else: 
    15731580                        name = original_fname 
  • src/sas/sasgui/perspectives/invariant/invariant_panel.py

    rc12f9b4 r654e8e0  
    250250 
    251251            num = self.state.saved_state['state_num'] 
    252             if num > 0: 
     252            if int(num) > 0: 
    253253                self._set_undo_flag(True) 
    254             if num < len(state.state_list) - 1: 
     254            if int(num) < len(state.state_list) - 1: 
    255255                self._set_redo_flag(True) 
    256256 
     
    830830        """ 
    831831        try: 
    832             attr = getattr(self, key) 
     832            if key in ['compute_num', 'file', 'is_time_machine', 'state_num']: 
     833                return 
     834            else: 
     835                attr = getattr(self, key) 
    833836            if attr.__class__.__name__ == "StaticText": 
    834837                return 
    835             if type(value) is not bool: 
     838            if value in ["True", "False", True, False]: 
     839                value = bool(value) 
     840            else: 
    836841                value = str(value) 
    837842            attr.SetValue(value) 
     
    18601865                                   (self.button_calculate, 0, 
    18611866                                    wx.RIGHT | wx.TOP | wx.BOTTOM, 10), 
    1862                                    (self.button_help, 0,  
     1867                                   (self.button_help, 0, 
    18631868                                    wx.RIGHT | wx.TOP | wx.BOTTOM, 10),]) 
    18641869    def _do_layout(self): 
     
    18821887        self.SetSizer(self.main_sizer) 
    18831888        self.SetAutoLayout(True) 
    1884          
     1889 
    18851890    def on_help(self, event): 
    18861891        """ 
    1887         Bring up the Invariant Documentation whenever the HELP button is  
     1892        Bring up the Invariant Documentation whenever the HELP button is 
    18881893        clicked. 
    18891894 
  • src/sas/sasgui/perspectives/invariant/invariant_state.py

    rc10d9d6c rcb93b40  
    426426                        if input_field is not None: 
    427427                            temp_state[item] = val 
    428                             self.state_list[ind] = temp_state 
     428                            self.state_list[str(ind)] = temp_state 
    429429 
    430430            # Parse current state (ie, saved_state) 
     
    790790            doc = state.toXML(datainfo.name, doc=doc, entry_node=sasentry) 
    791791        return doc 
    792  
  • src/sas/sasgui/perspectives/pr/media/pr_help.rst

    rb64b87c r0391dae  
    1515*P(r)* is set to be equal to an expansion of base functions of the type 
    1616 
    17   |bigphi|\_n(r) = 2.r.sin(|pi|\ .n.r/D_max) 
     17.. math:: 
     18  \Phi_{n(r)} = 2 r sin(\frac{\pi n r}{D_{max}}) 
    1819 
    19 The coefficient of each base function in the expansion is found by performing  
     20The coefficient of each base function in the expansion is found by performing 
    2021a least square fit with the following fit function 
    2122 
    22   |chi|\ :sup:`2` = |bigsigma|\ :sub:`i` [ I\ :sub:`meas`\ (Q\ :sub:`i`\ ) - I\ :sub:`th`\ (Q\ :sub:`i`\ ) ] :sup:`2` / (Error) :sup:`2` + Reg_term 
     23.. math:: 
    2324 
    24 where I\ :sub:`meas`\ (Q) is the measured scattering intensity and  
    25 I\ :sub:`th`\ (Q) is the prediction from the Fourier transform of the *P(r)*  
    26 expansion.  
     25  \chi^2=\frac{\sum_i (I_{meas}(Q_i)-I_{th}(Q_i))^2}{error^2}+Reg\_term 
     26   
    2727 
    28 The *Reg_term* term is a regularization term set to the second derivative  
    29 d\ :sup:`2`\ *P(r)* / dr\ :sup:`2` integrated over *r*. It is used to produce a  
    30 smooth *P(r)* output. 
     28where $I_{meas}(Q_i)$ is the measured scattering intensity and $I_{th}(Q_i)$ is 
     29the prediction from the Fourier transform of the *P(r)* expansion.  
     30 
     31The $Reg\_term$ term is a regularization term set to the second derivative  
     32$d^2P(r)/d^2r$ integrated over $r$. It is used to produce a smooth *P(r)* output. 
    3133 
    3234.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
     
    4547   system. 
    4648 
     49P(r) inversion requires that the background be perfectly subtracted.  This is 
     50often difficult to do well and thus many data sets will include a background. 
     51For those cases, the user should check the "estimate background" box and the 
     52module will do its best to estimate it. 
     53 
     54The P(r) module is constantly computing in the background what the optimum 
     55*number of terms* should be as well as the optimum *regularization constant*. 
     56These are constantly updated in the buttons next to the entry boxes on the GUI. 
     57These are almost always close and unless the user has a good reason to choose 
     58differently they should just click on the buttons to accept both.  {D_max} must 
     59still be set by the user.  However, besides looking at the output, the user can 
     60click the explore button which will bring up a graph of chi^2 vs Dmax over a 
     61range around the current Dmax.  The user can change the range and the number of 
     62points to explore in that range.  They can also choose to plot several other 
     63parameters as a function of Dmax including: I0, Rg, Oscillation parameter, 
     64background, positive fraction, and 1-sigma positive fraction. 
     65 
    4766.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
    4867 
     
    5574.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
    5675 
    57 .. note::  This help document was last changed by Steve King, 01May2015 
     76.. note::  This help document was last modified by Paul Butler, 05 September, 2016 
Note: See TracChangeset for help on using the changeset viewer.