Changes in / [a235f715:c79304b] in sasview


Ignore:
Files:
2 added
10 edited

Legend:

Unmodified
Added
Removed
  • docs/sphinx-docs/source/user/sasgui/perspectives/invariant/invariant_help.rst

    r5f5c596 r9bbc074  
    44.. by S King, ISIS, during SasView CodeCamp-III in Feb 2015. 
    55 
    6 Invariant Calculation Perspective 
    7 ================================= 
     6Invariant Calculation 
     7===================== 
    88 
    99Description 
     
    1919.. image:: image001.gif 
    2020 
    21 where *g = Q* for pinhole geometry (SAS) and *g = Qv* (the slit height) for   
     21where *g = q* for pinhole geometry (SAS) and *g = q*\ :sub:`v` (the slit height) for   
    2222slit geometry (USAS). 
    2323 
     
    4545.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
    4646 
    47 Using the perspective 
    48 --------------------- 
     47Using invariant analysis 
     48------------------------ 
    4949 
    50501) Select *Invariant* from the *Analysis* menu on the SasView toolbar. 
     
    5353 
    54543) Select a dataset and use the *Send To* button on the *Data Explorer* to load  
    55    the dataset into the *Invariant* perspective. 
     55   the dataset into the *Invariant* panel. 
    5656 
    57 4) Use the *Customised Input* boxes on the *Invariant* perspective to subtract  
     574) Use the *Customised Input* boxes on the *Invariant* panel to subtract  
    5858   any background, specify the contrast (i.e. difference in SLDs - this must be  
    5959   specified for the eventual value of Q*\  to be on an absolute scale), or to  
     
    7373 
    74748) If the value of Q*\  calculated with the extrapolated regions is invalid, a  
    75    red warning will appear at the top of the *Invariant* perspective panel. 
     75   red warning will appear at the top of the *Invariant* panel. 
    7676 
    7777   The details of the calculation are available by clicking the *Details*  
  • docs/sphinx-docs/source/user/user.rst

    r5a71761 r20a3c55  
    1414          
    1515   Working with SasView <working> 
     16 
     17   Computations with GPU <gpu_computations> 
  • sasview/local_config.py

    rd85c194 r9bbc074  
    8282_corner_image = os.path.join(icon_path, "angles_flat.png") 
    8383_welcome_image = os.path.join(icon_path, "SVwelcome.png") 
    84 _copyright = "(c) 2009 - 2013, UTK, UMD, NIST, ORNL, ISIS, ESS and ILL" 
     84_copyright = "(c) 2009 - 2016, UTK, UMD, NIST, ORNL, ISIS, ESS and ILL" 
    8585 
    8686 
  • sasview/setup_exe.py

    r525aaa2 r9bbc074  
    165165        self.version = local_config.__version__ 
    166166        self.company_name = "SasView.org" 
    167         self.copyright = "copyright 2009 - 2013" 
     167        self.copyright = "copyright 2009 - 2016" 
    168168        self.name = "SasView" 
    169169         
  • src/sas/sasgui/guiframe/utils.py

    rd85c194 ra0373d5  
    4646    return flag 
    4747 
    48      
     48 
     49def check_int(item): 
     50    """ 
     51    :param item: txtcrtl containing a value 
     52    """ 
     53    flag = True 
     54    try: 
     55        mini = int(item.GetValue()) 
     56        item.SetBackgroundColour(wx.WHITE) 
     57        item.Refresh() 
     58    except: 
     59        flag = False 
     60        item.SetBackgroundColour("pink") 
     61        item.Refresh() 
     62    return flag 
     63 
     64 
    4965class PanelMenu(wx.Menu): 
    5066    """ 
  • src/sas/sasgui/perspectives/fitting/basepage.py

    ree4b3cb r6c382da  
    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] 
     
    22812274                continue 
    22822275 
    2283             name = str(item[1]) 
    2284             if name.endswith(".npts") or name.endswith(".nsigmas"): 
     2276            value_ctrl = item[2] 
     2277            if not value_ctrl.IsEnabled(): 
     2278                # ArrayDispersion disables PD, Min, Max, Npts, Nsigs 
    22852279                continue 
    22862280 
    2287             # Check that min, max and value are floats 
    2288             value_ctrl, min_ctrl, max_ctrl = item[2], item[5], item[6] 
    2289             min_str = min_ctrl.GetValue().strip() 
    2290             max_str = max_ctrl.GetValue().strip() 
     2281            name = item[1] 
    22912282            value_str = value_ctrl.GetValue().strip() 
    2292             validity = check_float(value_ctrl) 
    2293             if min_str != "": 
    2294                 validity = validity and check_float(min_ctrl) 
    2295             if max_str != "": 
    2296                 validity = validity and check_float(max_ctrl) 
    2297             if not validity: 
    2298                 continue 
    2299  
    2300             # Check that min is less than max 
    2301             low = -numpy.inf if min_str == "" else float(min_str) 
    2302             high = numpy.inf if max_str == "" else float(max_str) 
    2303             if high < low: 
    2304                 min_ctrl.SetBackgroundColour("pink") 
    2305                 min_ctrl.Refresh() 
    2306                 max_ctrl.SetBackgroundColour("pink") 
    2307                 max_ctrl.Refresh() 
    2308                 #msg = "Invalid fit range for %s: min must be smaller than max"%name 
    2309                 #wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 
    2310                 continue 
    2311  
    2312             # Force value between min and max 
    2313             value = float(value_str) 
    2314             if value < low: 
    2315                 value = low 
    2316                 value_ctrl.SetValue(format_number(value)) 
    2317             elif value > high: 
    2318                 value = high 
    2319                 value_ctrl.SetValue(format_number(value)) 
     2283            if name.endswith(".npts"): 
     2284                validity = check_int(value_ctrl) 
     2285                if not validity: 
     2286                    continue 
     2287                value = int(value_str) 
     2288 
     2289            elif name.endswith(".nsigmas"): 
     2290                validity = check_float(value_ctrl) 
     2291                if not validity: 
     2292                    continue 
     2293                value = float(value_str) 
     2294 
     2295            else:  # value or polydispersity 
     2296 
     2297                # Check that min, max and value are floats 
     2298                min_ctrl, max_ctrl = item[5], item[6] 
     2299                min_str = min_ctrl.GetValue().strip() 
     2300                max_str = max_ctrl.GetValue().strip() 
     2301                validity = check_float(value_ctrl) 
     2302                if min_str != "": 
     2303                    validity = validity and check_float(min_ctrl) 
     2304                if max_str != "": 
     2305                    validity = validity and check_float(max_ctrl) 
     2306                if not validity: 
     2307                    continue 
     2308 
     2309                # Check that min is less than max 
     2310                low = -numpy.inf if min_str == "" else float(min_str) 
     2311                high = numpy.inf if max_str == "" else float(max_str) 
     2312                if high < low: 
     2313                    min_ctrl.SetBackgroundColour("pink") 
     2314                    min_ctrl.Refresh() 
     2315                    max_ctrl.SetBackgroundColour("pink") 
     2316                    max_ctrl.Refresh() 
     2317                    #msg = "Invalid fit range for %s: min must be smaller than max"%name 
     2318                    #wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 
     2319                    continue 
     2320 
     2321                # Force value between min and max 
     2322                value = float(value_str) 
     2323                if value < low: 
     2324                    value = low 
     2325                    value_ctrl.SetValue(format_number(value)) 
     2326                elif value > high: 
     2327                    value = high 
     2328                    value_ctrl.SetValue(format_number(value)) 
     2329 
     2330                if name not in self.model.details.keys(): 
     2331                    self.model.details[name] = ["", None, None] 
     2332                old_low, old_high = self.model.details[name][1:3] 
     2333                if old_low != low or old_high != high: 
     2334                    # The configuration has changed but it won't change the 
     2335                    # computed curve so no need to set is_modified to True 
     2336                    #is_modified = True 
     2337                    self.model.details[name][1:3] = low, high 
    23202338 
    23212339            # Update value in model if it has changed 
     
    23232341                self.model.setParam(name, value) 
    23242342                is_modified = True 
    2325  
    2326             if name not in self.model.details.keys(): 
    2327                 self.model.details[name] = ["", None, None] 
    2328             old_low, old_high = self.model.details[name][1:3] 
    2329             if old_low != low or old_high != high: 
    2330                 # The configuration has changed but it won't change the 
    2331                 # computed curve so no need to set is_modified to True 
    2332                 #is_modified = True 
    2333                 self.model.details[name][1:3] = low, high 
    23342343 
    23352344        return is_modified 
     
    25042513                self._disp_obj_dict[name1] = disp_model 
    25052514                self.model.set_dispersion(param_name, disp_model) 
    2506                 self.state._disp_obj_dict[name1] = disp_model 
     2515                self.state._disp_obj_dict[name1] = disp_model.type 
    25072516 
    25082517                value1 = str(format_number(self.model.getParam(name1), True)) 
     
    25272536                        item[0].Enable() 
    25282537                        item[2].Enable() 
     2538                        item[3].Show(True) 
     2539                        item[4].Show(True) 
    25292540                        item[5].Enable() 
    25302541                        item[6].Enable() 
     
    26192630        self._disp_obj_dict[name] = disp 
    26202631        self.model.set_dispersion(name.split('.')[0], disp) 
    2621         self.state._disp_obj_dict[name] = disp 
     2632        self.state._disp_obj_dict[name] = disp.type 
    26222633        self.values[name] = values 
    26232634        self.weights[name] = weights 
     
    26872698        :param disp_function: dispersion distr. function 
    26882699        """ 
    2689         # List of the poly_model name in the combobox 
    2690         list = ["RectangleDispersion", "ArrayDispersion", 
    2691                 "LogNormalDispersion", "GaussianDispersion", 
    2692                 "SchulzDispersion"] 
    2693  
    26942700        # Find the selection 
    2695         try: 
    2696             selection = list.index(disp_func.__class__.__name__) 
    2697             return selection 
    2698         except: 
    2699             return 3 
     2701        if disp_func is not None: 
     2702            try: 
     2703                return POLYDISPERSITY_MODELS.values().index(disp_func.__class__) 
     2704            except ValueError: 
     2705                pass  # Fall through to default class 
     2706        return POLYDISPERSITY_MODELS.keys().index('gaussian') 
    27002707 
    27012708    def on_reset_clicked(self, event): 
     
    32843291                    pd = content[name][1] 
    32853292                    if name.count('.') > 0: 
     3293                        # If this is parameter.width, then pd may be a floating 
     3294                        # point value or it may be an array distribution. 
     3295                        # Nothing to do for parameter.npts or parameter.nsigmas. 
    32863296                        try: 
    32873297                            float(pd) 
    3288                         except: 
     3298                            if name.endswith('.npts'): 
     3299                                pd = int(pd) 
     3300                        except Exception: 
    32893301                            #continue 
    32903302                            if not pd and pd != '': 
     
    32943306                        # Only array func has pd == '' case. 
    32953307                        item[2].Enable(False) 
     3308                    else: 
     3309                        item[2].Enable(True) 
    32963310                    if item[2].__class__.__name__ == "ComboBox": 
    32973311                        if content[name][1] in self.model.fun_list: 
     
    33203334                        pd = value[0] 
    33213335                        if name.count('.') > 0: 
     3336                            # If this is parameter.width, then pd may be a floating 
     3337                            # point value or it may be an array distribution. 
     3338                            # Nothing to do for parameter.npts or parameter.nsigmas. 
    33223339                            try: 
    33233340                                pd = float(pd) 
     3341                                if name.endswith('.npts'): 
     3342                                    pd = int(pd) 
    33243343                            except: 
    33253344                                #continue 
     
    33303349                            # Only array func has pd == '' case. 
    33313350                            item[2].Enable(False) 
     3351                        else: 
     3352                            item[2].Enable(True) 
    33323353                        if item[2].__class__.__name__ == "ComboBox": 
    33333354                            if value[0] in self.model.fun_list: 
     
    33493370        Helps get paste for poly function 
    33503371 
    3351         :param item: Gui param items 
    3352         :param value: the values for parameter ctrols 
    3353         """ 
    3354         is_array = False 
    3355         if len(value[1]) > 0: 
    3356             # Only for dispersion func.s 
    3357             try: 
    3358                 item[7].SetValue(value[1]) 
    3359                 selection = item[7].GetCurrentSelection() 
    3360                 name = item[7].Name 
    3361                 param_name = name.split('.')[0] 
    3362                 dispersity = item[7].GetClientData(selection) 
    3363                 disp_model = dispersity() 
    3364                 # Only for array disp 
    3365                 try: 
    3366                     pd_vals = numpy.array(value[2]) 
    3367                     pd_weights = numpy.array(value[3]) 
    3368                     if len(pd_vals) > 0 and len(pd_vals) > 0: 
    3369                         if len(pd_vals) == len(pd_weights): 
    3370                             self._set_disp_array_cb(item=item) 
    3371                             self._set_array_disp_model(name=name, 
    3372                                                        disp=disp_model, 
    3373                                                        values=pd_vals, 
    3374                                                        weights=pd_weights) 
    3375                             is_array = True 
    3376                 except Exception: 
    3377                     logging.error(traceback.format_exc()) 
    3378                 if not is_array: 
    3379                     self._disp_obj_dict[name] = disp_model 
    3380                     self.model.set_dispersion(name, 
    3381                                               disp_model) 
    3382                     self.state._disp_obj_dict[name] = \ 
    3383                                               disp_model 
    3384                     self.model.set_dispersion(param_name, disp_model) 
    3385                     self.state.values = self.values 
    3386                     self.state.weights = self.weights 
    3387                     self.model._persistency_dict[param_name] = \ 
    3388                                             [self.state.values, 
    3389                                              self.state.weights] 
    3390  
    3391             except Exception: 
    3392                 logging.error(traceback.format_exc()) 
    3393                 print "Error in BasePage._paste_poly_help: %s" % \ 
    3394                                         sys.exc_info()[1] 
    3395  
    3396     def _set_disp_array_cb(self, item): 
     3372        *item* is the parameter name 
     3373 
     3374        *value* depends on which parameter is being processed, and whether it 
     3375        has array polydispersity. 
     3376 
     3377        For parameters without array polydispersity: 
     3378 
     3379            parameter => ['FLOAT', ''] 
     3380            parameter.width => ['FLOAT', 'DISTRIBUTION', ''] 
     3381            parameter.npts => ['FLOAT', ''] 
     3382            parameter.nsigmas => ['FLOAT', ''] 
     3383 
     3384        For parameters with array polydispersity: 
     3385 
     3386            parameter => ['FLOAT', ''] 
     3387            parameter.width => ['FILENAME', 'array', [x1, ...], [w1, ...]] 
     3388            parameter.npts => ['FLOAT', ''] 
     3389            parameter.nsigmas => ['FLOAT', ''] 
     3390        """ 
     3391        # Do nothing if not setting polydispersity 
     3392        if len(value[1]) == 0: 
     3393            return 
     3394 
     3395        try: 
     3396            name = item[7].Name 
     3397            param_name = name.split('.')[0] 
     3398            item[7].SetValue(value[1]) 
     3399            selection = item[7].GetCurrentSelection() 
     3400            dispersity = item[7].GetClientData(selection) 
     3401            disp_model = dispersity() 
     3402 
     3403            if value[1] == 'array': 
     3404                pd_vals = numpy.array(value[2]) 
     3405                pd_weights = numpy.array(value[3]) 
     3406                if len(pd_vals) == 0 or len(pd_vals) != len(pd_weights): 
     3407                    msg = ("bad array distribution parameters for %s" 
     3408                           % param_name) 
     3409                    raise ValueError(msg) 
     3410                self._set_disp_cb(True, item=item) 
     3411                self._set_array_disp_model(name=name, 
     3412                                           disp=disp_model, 
     3413                                           values=pd_vals, 
     3414                                           weights=pd_weights) 
     3415            else: 
     3416                self._set_disp_cb(False, item=item) 
     3417                self._disp_obj_dict[name] = disp_model 
     3418                self.model.set_dispersion(param_name, disp_model) 
     3419                self.state._disp_obj_dict[name] = disp_model.type 
     3420                # TODO: It's not an array, why update values and weights? 
     3421                self.model._persistency_dict[param_name] = \ 
     3422                    [self.values, self.weights] 
     3423                self.state.values = self.values 
     3424                self.state.weights = self.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_cb(self, isarray, item): 
    33973432        """ 
    33983433        Set cb for array disp 
    33993434        """ 
    3400         item[0].SetValue(False) 
    3401         item[0].Enable(False) 
    3402         item[2].Enable(False) 
    3403         item[3].Show(False) 
    3404         item[4].Show(False) 
    3405         item[5].SetValue('') 
    3406         item[5].Enable(False) 
    3407         item[6].SetValue('') 
    3408         item[6].Enable(False) 
     3435        if isarray: 
     3436            item[0].SetValue(False) 
     3437            item[0].Enable(False) 
     3438            item[2].Enable(False) 
     3439            item[3].Show(False) 
     3440            item[4].Show(False) 
     3441            item[5].SetValue('') 
     3442            item[5].Enable(False) 
     3443            item[6].SetValue('') 
     3444            item[6].Enable(False) 
     3445        else: 
     3446            item[0].Enable() 
     3447            item[2].Enable() 
     3448            item[3].Show(True) 
     3449            item[4].Show(True) 
     3450            item[5].Enable() 
     3451            item[6].Enable() 
    34093452 
    34103453    def update_pinhole_smear(self): 
  • src/sas/sasgui/perspectives/fitting/fitpage.py

    ree4b3cb r6c382da  
    1010import math 
    1111import time 
     12import traceback 
    1213 
    1314from sasmodels.weights import MODELS as POLYDISPERSITY_MODELS 
     
    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/media/plugin.rst

    r05829fb re925f61  
    11.. _Writing_a_Plugin: 
    22 
    3 Writing a Plugin 
    4 ================ 
    5  
    6 Users can write their own models and save it to the the SasView 
     3Writing a Plugin Model 
     4====================== 
     5 
     6Overview 
     7^^^^^^^^ 
     8 
     9You can write your own model and save it to the the SasView 
    710*plugin_models* folder 
    811 
    9   *C:\\Users\\[username]\\.sasview\\plugin_models* - (on Windows) 
     12  *C:\\Users\\[username]\\.sasview\\plugin_models* (on Windows) 
    1013 
    1114The next time SasView is started it will compile the plugin and add 
    12 it to the list of *Customized Models*.  It is recommended that an 
     15it to the list of *Customized Models* in a FitPage.  It is recommended that an 
    1316existing model be used as a template. 
    14  
    15 This page was originally written by our MOST experienced developers, 
    16 but has subsequently been edited by our LEAST experienced developer who felt 
    17 some instructions could have been clearer, and learnt one or two things that 
    18 were missing altogether! But they succeeded in converting a model that passed 
    19 testing, so there is no reason why you should not be able to do the same. 
    2017 
    2118SasView has three ways of writing models: 
     
    2926  `cylinder.c <https://github.com/SasView/sasmodels/blob/master/sasmodels/models/cylinder.c>`_ 
    3027 
    31 Many models are available for download from the 
    32 `model marketplace <http://marketplace.sasview.org/>`_. 
    33  
    34 The builtin modules are available in the *sasmodels-data/models* subdirectory 
    35 of the sasview distribution.  On Windows, this will be something like 
    36 *C:\Program Files (x86)\SasView\models*.  On MacOSX, these will be within 
     28The built-in modules are available in the *sasmodels-data\\models* subdirectory 
     29of your SasView installation folder.  On Windows, this will be something like 
     30*C:\\Program Files (x86)\\SasView\\sasmodels-data\\models*.  On Mac OSX, these will be within 
    3731the application bundle as 
    3832*/Applications/SasView 4.0.app/Contents/Resources/sasmodels-data/models*. 
    3933 
     34Other models are available for download from our 
     35`Model Marketplace <http://marketplace.sasview.org/>`_. You can contribute your own models to the  
     36Marketplace aswell. 
     37 
    4038Create New Model Files 
    4139^^^^^^^^^^^^^^^^^^^^^^ 
    4240 
    43 In the *~/.sasview/plugin_models* directory, copy the appropriate files 
     41In the *~\\.sasview\\plugin_models* directory, copy the appropriate files 
    4442(using the examples above as templates) to mymodel.py (and mymodel.c, etc) 
    4543as required, where "mymodel" is the name for the model you are creating. 
     
    4745*Please follow these naming rules:* 
    4846 
    49 - No capitalization and thus no CamelCase. 
    50 - If necessary use underscore to separate (i.e. barbell not BarBell or 
     47- No capitalization and thus no CamelCase 
     48- If necessary use underscore to separate words (i.e. barbell not BarBell or 
    5149  broad_peak not BroadPeak) 
    52 - Don't include “model” in the name (i.e. barbell not BarBellModel) 
     50- Do not include “model” in the name (i.e. barbell not BarBellModel) 
    5351 
    5452 
    5553Edit New Model Files 
    5654^^^^^^^^^^^^^^^^^^^^ 
     55 
     56Model Contents 
     57.............. 
    5758 
    5859The model interface definition is in the .py file.  This file contains: 
     
    6566    - without spaces (use underscores to separate words instead) 
    6667    - without any capitalization or CamelCase 
    67     - without incorporating the word 'model' 
     68    - without incorporating the word "model" 
    6869    - examples: *barbell* **not** *BarBell*; *broad_peak* **not** *BroadPeak*;  
    6970      *barbell* **not** *BarBellModel* 
     
    7273   - this is the **title** string in the *.py* file 
    7374   - this is a one or two line description of the model, which will appear 
    74      at the start of the model documentation and as a tooltip in the GUI 
     75     at the start of the model documentation and as a tooltip in the SasView GUI 
    7576 
    7677- a **short discription**: 
    7778   - this is the **description** string in the *.py* file 
    7879   - this is a medium length description which appears when you click 
    79      *Description* on the model fit page 
     80     *Description* on the model FitPage 
    8081 
    8182- a **parameter table**: 
     
    8586   - this is ReStructuredText enclosed between the r""" and """ delimiters 
    8687     at the top of the *.py* file 
     88   - what you write here is abstracted into the SasView help documentation 
     89   - this is what other users will refer to when they want to know what your model does;  
     90     so please be helpful! 
    8791 
    8892- a **definition** of the model: 
     
    97101 
    98102- a **plot** of the function, with a **figure caption**: 
    99    - this is automatically generated from the default parameters 
     103   - this is automatically generated from your default parameters 
    100104 
    101105- at least one **reference**: 
     
    107111   - the *.py* file should also contain a comment identifying *who* 
    108112     converted/created the model file 
     113 
     114Models that do not conform to these requirements will *never* be incorporated  
     115into the built-in library. 
    109116 
    110117More complete documentation for the sasmodels package can be found at 
     
    170177 
    171178The model should include a **formula** written using LaTeX markup. 
    172 The above example uses the *math* command to make a displayed equation.  You 
     179The example above uses the *math* command to make a displayed equation.  You 
    173180can also use *\$formula\$* for an inline formula. This is handy for defining 
    174181the relationship between the model parameters and formula variables, such 
    175182as the phrase "\$r\$ is the radius" used above.  The live demo MathJax 
    176183page `<http://www.mathjax.org/>`_ is handy for checking that the equations 
    177 will look like you expect. 
     184will look like you intend. 
    178185 
    179186Math layout uses the `amsmath <http://www.ams.org/publications/authors/tex/amslatex>`_ 
     
    207214 
    208215    name = "sphere"  # optional: defaults to the filename without .py 
     216 
    209217    title = "Spheres with uniform scattering length density" 
     218 
    210219    description = """\ 
    211220    P(q)=(scale/V)*[3V(sld-sld_solvent)*(sin(qr)-qr cos(qr)) 
     
    216225        sld_solvent: the SLD of the solvent 
    217226    """ 
     227 
    218228    category = "shape:sphere" 
     229 
    219230    single = True   # optional: defaults to True 
     231 
    220232    opencl = False  # optional: defaults to False 
     233 
    221234    structure_factor = False  # optional: defaults to False 
    222235 
     
    229242**title = "short description"** is short description of the model which 
    230243is included after the model name in the automatically generated documentation. 
    231 The title can also be used for a tooltip, for example. 
     244The title can also be used for a tooltip. 
    232245 
    233246**description = """doc string"""** is a longer description of the model. It 
    234 shows up when you press the "Description" button of the SasView fit page. 
     247shows up when you press the "Description" button of the SasView FitPage. 
    235248It should give a brief description of the equation and the parameters 
    236249without the need to read the entire model documentation. The triple quotes 
    237250allow you to write the description over multiple lines. Keep the lines 
    238251short since the GUI will wrap each one separately if they are too long. 
    239 **Make sure the parameter names in the description match the model definition.** 
     252**Make sure the parameter names in the description match the model definition!** 
    240253 
    241254**category = "shape:sphere"** defines where the model will appear in the 
    242255model documentation.  In this example, the model will appear alphabetically 
    243 in the list of spheroid models. 
     256in the list of spheroid models in the *Shape* category. 
    244257 
    245258**single = True** indicates that the model can be run using single 
     
    275288        ["radius",      "Ang",        50, [0, inf],    "volume", "Sphere radius"], 
    276289    ] 
    277     # pylint: disable=bad-whitespace, line-too-long 
     290    # pylint: enable=bad-whitespace, line-too-long 
    278291 
    279292**parameters = [["name", "units", default, [min,max], "type", "tooltip"],...]** 
    280 defines the parameters form the model. 
    281  
    282 - **the order of the parameters in the definition will be the order of 
    283   the parameters in the user interface and the order of the parameters 
    284   in Iq(), Iqxy() and form_volume().** 
    285  
    286 - **scale and background parameters are implicit to all models, so 
    287   they do not need to be included in the parameter table** 
    288  
    289 - **"name"** is the name of the parameter shown on the fit screen 
     293defines the parameters that form the model. 
     294 
     295**Note: The order of the parameters in the definition will be the order of the  
     296parameters in the user interface and the order of the parameters in Iq(),  
     297Iqxy() and form_volume(). And** *scale* **and** *background* **parameters are  
     298implicit to all models, so they do not need to be included in the parameter table.** 
     299 
     300- **"name"** is the name of the parameter shown on the FitPage. 
    290301 
    291302  - parameter names should follow the mathematical convention; e.g., 
    292     *radius_core* not *core_radius*, or *sld_solvent* not *solvent_sld* 
     303    *radius_core* not *core_radius*, or *sld_solvent* not *solvent_sld*. 
     304 
    293305  - model parameter names should be consistent between different models, 
    294306    so *sld_solvent*, for example, should have exactly the same name 
    295     in every model 
     307    in every model. 
     308 
    296309  - to see all the parameter names currently in use, type the following in the 
    297310    python shell/editor under the Tools menu:: 
     
    301314 
    302315    *re-use* as many as possible!!! 
     316 
    303317  - use "name[n]" for multiplicity parameters, where *n* is the name of 
    304318    the parameter defining the number of shells/layers/segments, etc. 
     
    306320- **"units"** are displayed along with the parameter name 
    307321 
    308   - every parameter should have units; use "None" if there are no units 
     322  - every parameter should have units; use "None" if there are no units. 
     323 
    309324  - **sld's should be given in units of 1e-6/Ang^2, and not simply 
    310325    1/Ang^2 to be consistent with the builtin models.  Adjust your formulas 
    311326    appropriately.** 
     327 
    312328  - fancy units markup is available for some units, including:: 
    313329 
     
    322338      and using negative exponents instead of the / operator, though 
    323339      the unit name should use the / operator for consistency. 
    324     - post a message to the sasview developers list with the changes 
    325  
    326 - **default** is the initial value for the parameter 
     340    - please post a message to the SasView developers mailing list with your changes. 
     341 
     342- **default** is the initial value for the parameter. 
    327343 
    328344  - **the parameter default values are used to auto-generate a plot of 
    329345    the model function in the documentation.** 
    330346 
    331 - **[min, max]** are the lower and upper limits on the parameter 
    332  
    333   - lower and upper limits can be any number, or -inf or inf. 
     347- **[min, max]** are the lower and upper limits on the parameter. 
     348 
     349  - lower and upper limits can be any number, or *-inf* or *inf*. 
     350 
    334351  - the limits will show up as the default limits for the fit making it easy, 
    335352    for example, to force the radius to always be greater than zero. 
    336353 
    337 - **"type"** can be one of: "", "sld", "volume", or "orientation" 
     354- **"type"** can be one of: "", "sld", "volume", or "orientation". 
    338355 
    339356  - "sld" parameters can have magnetic moments when fitting magnetic models; 
    340357    depending on the spin polarization of the beam and the $q$ value being 
    341358    examined, the effective sld for that material will be used to compute the 
    342     scattered intensity 
     359    scattered intensity. 
     360 
    343361  - "volume" parameters are passed to Iq(), Iqxy(), and form_volume(), and 
    344362    have polydispersity loops generated automatically. 
     363 
    345364  - "orientation" parameters are only passed to Iqxy(), and have angular 
    346365    dispersion. 
     
    380399............. 
    381400 
    382 For pure python models, define the Iq funtion:: 
     401For pure python models, define the *Iq* function:: 
    383402 
    384403      import numpy as np 
     
    391410The parameters *par1, par2, ...* are the list of non-orientation parameters 
    392411to the model in the order that they appear in the parameter table. 
    393 **Note that the autogenerated model file uses *x* rather than *q*.** 
     412**Note that the autogenerated model file uses** *x* **rather than** *q*. 
    394413 
    395414The *.py* file should import trigonometric and exponential functions from 
    396 numpy rather that from math.  This lets us evaluate the model for the whole 
     415numpy rather than from math.  This lets us evaluate the model for the whole 
    397416range of $q$ values at once rather than looping over each $q$ separately in 
    398417python.  With $q$ as a vector, you cannot use if statements, but must instead 
     
    430449list includes the *volume* parameters in order.  This is used for a weighted 
    431450volume normalization so that scattering is on an absolute scale.  If 
    432 *form_volume* is not definded, then the default *form_volume = 1.0* will be 
     451*form_volume* is not defined, then the default *form_volume = 1.0* will be 
    433452used. 
    434453 
     
    436455................. 
    437456 
    438 Like pure python models, inline C models need define an *Iq* function:: 
     457Like pure python models, inline C models need to define an *Iq* function:: 
    439458 
    440459    Iq = """ 
     
    516535These functions have been tuned to be fast and numerically stable down 
    517536to $q=0$ even in single precision.  In some cases they work around bugs 
    518 which appear on some platforms but not others. 
     537which appear on some platforms but not others. So use them where needed!!! 
    519538 
    520539Models are defined using double precision declarations for the 
    521540parameters and return values.  Declarations and constants will be converted 
    522541to float or long double depending on the precision requested. 
     542 
    523543**Floating point constants must include the decimal point.**  This allows us 
    524544to convert values such as 1.0 (double precision) to 1.0f (single precision) 
     
    540560 
    541561A value defined as SAS_DOUBLE will stay double precision; this should 
    542 not be used since some graphics card don't support double precision. 
     562not be used since some graphics cards do not support double precision. 
    543563 
    544564 
     
    557577Form Factors 
    558578............ 
    559  
    560 :: 
    561  
    562     def ER(radius, thickness): 
    563         """Effective radius of a core-shell sphere.""" 
    564         return radius + thickness 
    565579 
    566580Away from the dilute limit you can estimate scattering including 
     
    572586form averaged over all the polydispersity values. 
    573587 
    574 Consider the *core_shell_sphere*, which has a simple effective radius 
     588:: 
     589 
     590    def ER(radius, thickness): 
     591        """Effective radius of a core-shell sphere.""" 
     592        return radius + thickness 
     593 
     594Now consider the *core_shell_sphere*, which has a simple effective radius 
    575595equal to the radius of the core plus the thickness of the shell, as 
    576596shown above. Given polydispersity over *(r1, r2, ..., rm)* in radius and 
     
    597617one return value for each point in the mesh grid. 
    598618 
    599 *NOTE: we may be removing or modifying this feature soon.*  As of this 
    600 writing, core-shell sphere returns (1., 1.) for *VR*, giving a volume 
    601 ratio of 1.0. 
     619*NOTE: we may be removing or modifying this feature soon. As of the  
     620time of writing, core-shell sphere returns (1., 1.) for VR, giving a volume 
     621ratio of 1.0.* 
    602622 
    603623Unit Tests 
     
    640660^^^^^^^^^^^^^^^^^^^ 
    641661 
     662Installed SasView 
     663................. 
     664 
    642665If you are editing your model from the SasView GUI, you can test it 
    643 by selecting *Run -> Compile* from the *Model Editor* menu bar. An 
     666by selecting *Run > Compile* from the *Model Editor* menu bar. An 
    644667*Info* box will appear with the results of the compilation and a 
    645668check that the model runs. 
    646669 
     670 
     671Built SasView 
     672............. 
     673 
    647674If the model compiles and runs, you can next run the unit tests that 
    648 you have added using the **test=** values. Switch to the *Shell* tab 
     675you have added using the **test =** values. Switch to the *Shell* tab 
    649676and type the following:: 
    650677 
     
    686713For the random models, 
    687714 
    688 - sld will be in(-0.5,10.5), 
    689 - angles (theta, phi, psi) will be in (-180,180), 
    690 - angular dispersion will be in (0,45), 
    691 - polydispersity will be in (0,1) 
    692 - other values will be in (0, 2*v) where v is the value of the parameter in demo. 
    693  
    694 Dispersion parameters n, sigma and type will be unchanged from demo so that 
     715- *sld* will be in the range (-0.5,10.5), 
     716- angles (*theta, phi, psi*) will be in the range (-180,180), 
     717- angular dispersion will be in the range (0,45), 
     718- polydispersity will be in the range (0,1) 
     719- other values will be in the range (0, 2\ *v*), where *v* is the value of the parameter in demo. 
     720 
     721Dispersion parameters *n*\, *sigma* and *type* will be unchanged from demo so that 
    695722run times are predictable. 
    696723 
     
    701728 
    702729 
    703 Clean Lint 
    704 ^^^^^^^^^^ 
    705  
    706 **NB: For now we are not providing pylint with SasView; unless you have a 
    707 SasView development environment available, you can ignore this section.** 
     730Clean Lint - (Developer Version Only) 
     731^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
     732 
     733**NB: For now we are not providing pylint with the installer version of SasView;  
     734so unless you have a SasView build environment available, you can ignore this section!** 
    708735 
    709736Run the lint check with:: 
     
    717744for standard model functions *Iq*, *Iqxy*, etc. 
    718745 
    719 We will have delinting sessions at the SasView code camps, where we can 
     746We will have delinting sessions at the SasView Code Camps, where we can 
    720747decide on standards for model files, parameter names, etc. 
    721748 
    722 For now, you can tell pylint to ignore things.  For example, to align you 
     749For now, you can tell pylint to ignore things.  For example, to align your 
    723750parameters in blocks:: 
    724751 
     
    738765Don't put in too many pylint statements, though, since they make the code ugly. 
    739766 
    740 Check The Docs 
    741 ^^^^^^^^^^^^^^ 
     767Check The Docs - (Developer Version Only) 
     768^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
    742769 
    743770You can get a rough idea of how the documentation will look using the 
     
    756783- `amsmath <http://www.ams.org/publications/authors/tex/amslatex>`_ 
    757784 
    758 Finally 
    759 ^^^^^^^ 
     785There is also a neat online WYSIWYG ReStructuredText editor at http://rst.ninjs.org\ . 
     786 
     787Share Your Model! 
     788^^^^^^^^^^^^^^^^^ 
    760789 
    761790Once compare and the unit test(s) pass properly and everything is done, 
    762791consider adding your model to the 
    763 `model marketplace <http://marketplace.sasview.org/>`_. 
    764  
     792`Model Marketplace <http://marketplace.sasview.org/>`_ so that others may use it! 
  • src/sas/sasgui/perspectives/fitting/pagestate.py

    r654e8e0 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 
Note: See TracChangeset for help on using the changeset viewer.