Changeset aa25fc7 in sasmodels


Ignore:
Timestamp:
May 23, 2018 5:55:27 PM (6 years ago)
Author:
Paul Kienzle <pkienzle@…>
Branches:
master
Children:
910c0f4
Parents:
33969b6
Message:

load user-defined weight functions from ~/.sasview/weights/*.py

Files:
4 edited

Legend:

Unmodified
Added
Removed
  • doc/guide/pd/polydispersity.rst

    r29afc50 raa25fc7  
    2828sigmas $N_\sigma$ to include from the tails of the distribution, and the 
    2929number of points used to compute the average. The center of the distribution 
    30 is set by the value of the model parameter. The meaning of a polydispersity  
    31 parameter *PD* (not to be confused with a molecular weight distributions  
    32 in polymer science) in a model depends on the type of parameter it is being  
     30is set by the value of the model parameter. The meaning of a polydispersity 
     31parameter *PD* (not to be confused with a molecular weight distributions 
     32in polymer science) in a model depends on the type of parameter it is being 
    3333applied too. 
    3434 
    35 The distribution width applied to *volume* (ie, shape-describing) parameters  
    36 is relative to the center value such that $\sigma = \mathrm{PD} \cdot \bar x$.  
    37 However, the distribution width applied to *orientation* (ie, angle-describing)  
     35The distribution width applied to *volume* (ie, shape-describing) parameters 
     36is relative to the center value such that $\sigma = \mathrm{PD} \cdot \bar x$. 
     37However, the distribution width applied to *orientation* (ie, angle-describing) 
    3838parameters is just $\sigma = \mathrm{PD}$. 
    3939 
     
    7373or angular orientations, use the Gaussian or Boltzmann distributions. 
    7474 
    75 If applying polydispersion to parameters describing angles, use the Uniform  
    76 distribution. Beware of using distributions that are always positive (eg, the  
     75If applying polydispersion to parameters describing angles, use the Uniform 
     76distribution. Beware of using distributions that are always positive (eg, the 
    7777Lognormal) because angles can be negative! 
    7878 
     
    315315.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
    316316 
     317User-defined Distributions 
     318^^^^^^^^^^^^^^^^^^^^^^^^^^ 
     319 
     320You can define your own distribution by creating a python file defining a 
     321*Distribution* object.  The distribution is parameterized by *center* 
     322(which is always zero for orientation dispersity, or parameter value for 
     323size dispersity), *sigma* (which is the distribution width in degrees for 
     324orientation parameters, or center times width for size dispersity), and 
     325bounds *lb* and *ub* (which are the bounds on the possible values of the 
     326parameter given in the model definition). 
     327 
     328For example, the following wraps the Laplace distribution from scipy stats:: 
     329 
     330    import numpy as np 
     331    from scipy.stats import laplace 
     332 
     333    from sasmodels import weights 
     334 
     335    class Dispersion(weights.Dispersion): 
     336        r""" 
     337        Laplace distribution 
     338 
     339        .. math:: 
     340 
     341            w(x) = e^{-\sigma |x - \mu|} 
     342        """ 
     343        type = "laplace" 
     344        default = dict(npts=35, width=0, nsigmas=3)  # default values 
     345        def _weights(self, center, sigma, lb, ub): 
     346            x = self._linspace(center, sigma, lb, ub) 
     347            wx = laplace.pdf(x, center, sigma) 
     348            return x, wx 
     349 
     350To see that the distribution is correct use the following:: 
     351 
     352    from numpy import inf 
     353    from matplotlib import pyplot as plt 
     354    from sasmodels import weights 
     355 
     356    # reload the user-defined weights 
     357    weights.load_weights() 
     358    x, wx = weights.get_weights('laplace', n=35, width=0.1, nsigmas=3, value=50, 
     359                                limits=[0, inf], relative=True) 
     360 
     361    # plot the weights 
     362    plt.interactive(True) 
     363    plt.plot(x, wx, 'x') 
     364 
     365Any python code can be used to define the distribution.  The distribution 
     366parameters are available as *self.npts*, *self.width* and *self.nsigmas*. 
     367Try to follow the convention of gaussian width, npts and number of sigmas 
     368in the tail, but if your distribution requires more parameters you are free 
     369to interpret them as something else.  In particular, npts allows you to 
     370trade accuracy against running time when evaluating your models.  The 
     371*self._linspace* function uses *self.npts* and *self.nsigmas* to define 
     372the set of *x* values to use for the distribution (along with the *center*, 
     373*sigma*, *lb*, and *ub* passed as parameters).  You can use an arbitrary 
     374set of *x* points. 
     375 
     376.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
     377 
    317378Note about DLS polydispersity 
    318379^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
  • sasmodels/compare.py

    r1fbadb2 raa25fc7  
    4141from . import kerneldll 
    4242from . import kernelcl 
     43from . import weights 
    4344from .data import plot_theory, empty_data1D, empty_data2D, load_data 
    4445from .direct_model import DirectModel, get_mesh 
    4546from .generate import FLOAT_RE, set_integration_size 
    46 from .weights import plot_weights 
    4747 
    4848# pylint: disable=unused-import 
     
    771771            model_info = base._kernel.info 
    772772            dim = base._kernel.dim 
    773             plot_weights(model_info, get_mesh(model_info, base_pars, dim=dim)) 
     773            weights.plot_weights(model_info, get_mesh(model_info, base_pars, dim=dim)) 
    774774    if opts['plot']: 
    775775        import matplotlib.pyplot as plt 
     
    13531353    #import pprint; pprint.pprint(model_info) 
    13541354 
     1355    # Hack to load user-defined distributions; run through all parameters 
     1356    # and make sure any pd_type parameter is a defined distribution. 
     1357    if (any(p.endswith('pd_type') and v not in weights.MODELS 
     1358            for p, v in pars.items()) or 
     1359        any(p.endswith('pd_type') and v not in weights.MODELS 
     1360            for p, v in pars2.items())): 
     1361       weights.load_weights() 
     1362 
    13551363    if opts['show_pars']: 
    13561364        if model_info.name != model_info2.name or pars != pars2: 
  • sasmodels/sasview_model.py

    rd533590 raa25fc7  
    3030from . import modelinfo 
    3131from .details import make_kernel_args, dispersion_mesh 
     32 
     33# Hack: load in any custom distributions 
     34# Uses ~/.sasview/weights/*.py unless SASMODELS_WEIGHTS is set in the environ. 
     35# Override with weights.load_weights(pattern="<weights_path>/*.py") 
     36weights.load_weights() 
    3237 
    3338# pylint: disable=unused-import 
  • sasmodels/weights.py

    r3d58247 raa25fc7  
    231231)) 
    232232 
     233SASMODELS_WEIGHTS = "~/.sasview/weights/*.py" 
     234def load_weights(pattern=None): 
     235    # type: (str) -> None 
     236    """ 
     237    Load dispersion distributions matching the given pattern 
     238    """ 
     239    import logging 
     240    import os 
     241    import os.path 
     242    import glob 
     243    import traceback 
     244    from .custom import load_custom_kernel_module 
     245    if pattern is None: 
     246        pattern = os.environ.get("SASMODELS_WEIGHTS", SASMODELS_WEIGHTS) 
     247    for filename in sorted(glob.glob(os.path.expanduser(pattern))): 
     248        try: 
     249            print("loading weights from", filename) 
     250            module = load_custom_kernel_module(filename) 
     251            MODELS[module.Dispersion.type] = module.Dispersion 
     252        except Exception as exc: 
     253            logging.error(traceback.format_exc(exc)) 
    233254 
    234255def get_weights(disperser, n, width, nsigmas, value, limits, relative): 
Note: See TracChangeset for help on using the changeset viewer.