Changes in / [1d9998c:7609046] in sasmodels


Ignore:
Files:
2 added
4 edited

Legend:

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

    rd712a0f r9ce5bcb  
    3333sigmas $N_\sigma$ to include from the tails of the distribution, and the 
    3434number of points used to compute the average. The center of the distribution 
    35 is set by the value of the model parameter. The meaning of a polydispersity  
    36 parameter *PD* (not to be confused with a molecular weight distributions  
    37 in polymer science) in a model depends on the type of parameter it is being  
     35is set by the value of the model parameter. The meaning of a polydispersity 
     36parameter *PD* (not to be confused with a molecular weight distributions 
     37in polymer science) in a model depends on the type of parameter it is being 
    3838applied too. 
    3939 
    40 The distribution width applied to *volume* (ie, shape-describing) parameters  
    41 is relative to the center value such that $\sigma = \mathrm{PD} \cdot \bar x$.  
    42 However, the distribution width applied to *orientation* (ie, angle-describing)  
     40The distribution width applied to *volume* (ie, shape-describing) parameters 
     41is relative to the center value such that $\sigma = \mathrm{PD} \cdot \bar x$. 
     42However, the distribution width applied to *orientation* (ie, angle-describing) 
    4343parameters is just $\sigma = \mathrm{PD}$. 
    4444 
     
    6464*  *Schulz Distribution* 
    6565*  *Array Distribution* 
     66*  *User-defined Distributions* 
    6667 
    6768These are all implemented as *number-average* distributions. 
    6869 
    69 Additional distributions are under consideration. 
    7070 
    7171.. note:: In 2009 IUPAC decided to introduce the new term 'dispersity' to replace  
     
    8787or angular orientations, use the Gaussian or Boltzmann distributions. 
    8888 
    89 If applying polydispersion to parameters describing angles, use the Uniform  
    90 distribution. Beware of using distributions that are always positive (eg, the  
     89If applying polydispersion to parameters describing angles, use the Uniform 
     90distribution. Beware of using distributions that are always positive (eg, the 
    9191Lognormal) because angles can be negative! 
    9292 
    93 The array distribution allows a user-defined distribution to be applied. 
     93The array distribution provides a very simple means of implementing a user- 
     94defined distribution, but without any fittable parameters. Greater flexibility 
     95is conferred by the user-defined distribution.  
    9496 
    9597.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
     
    329331.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
    330332 
     333User-defined Distributions 
     334^^^^^^^^^^^^^^^^^^^^^^^^^^ 
     335 
     336You can also define your own distribution by creating a python file defining a 
     337*Distribution* object with a *_weights* method.  The *_weights* method takes 
     338*center*, *sigma*, *lb* and *ub* as arguments, and can access *self.npts* 
     339and *self.nsigmas* from the distribution.  They are interpreted as follows: 
     340 
     341* *center* the value of the shape parameter (for size dispersity) or zero 
     342  if it is an angular dispersity.  This parameter may be fitted. 
     343 
     344* *sigma* the width of the distribution, which is the polydispersity parameter 
     345  times the center for size dispersity, or the polydispersity parameter alone 
     346  for angular dispersity.  This parameter may be fitted. 
     347 
     348* *lb*, *ub* are the parameter limits (lower & upper bounds) given in the model 
     349  definition file.  For example, a radius parameter has *lb* equal to zero.  A 
     350  volume fraction parameter would have *lb* equal to zero and *ub* equal to one. 
     351 
     352* *self.nsigmas* the distance to go into the tails when evaluating the 
     353  distribution.  For a two parameter distribution, this value could be 
     354  co-opted to use for the second parameter, though it will not be available 
     355  for fitting. 
     356 
     357* *self.npts* the number of points to use when evaluating the distribution. 
     358  The user will adjust this to trade calculation time for accuracy, but the 
     359  distribution code is free to return more or fewer, or use it for the third 
     360  parameter in a three parameter distribution. 
     361 
     362As an example, the code following wraps the Laplace distribution from scipy stats:: 
     363 
     364    import numpy as np 
     365    from scipy.stats import laplace 
     366 
     367    from sasmodels import weights 
     368 
     369    class Dispersion(weights.Dispersion): 
     370        r""" 
     371        Laplace distribution 
     372 
     373        .. math:: 
     374 
     375            w(x) = e^{-\sigma |x - \mu|} 
     376        """ 
     377        type = "laplace" 
     378        default = dict(npts=35, width=0, nsigmas=3)  # default values 
     379        def _weights(self, center, sigma, lb, ub): 
     380            x = self._linspace(center, sigma, lb, ub) 
     381            wx = laplace.pdf(x, center, sigma) 
     382            return x, wx 
     383 
     384You can plot the weights for a given value and width using the following:: 
     385 
     386    from numpy import inf 
     387    from matplotlib import pyplot as plt 
     388    from sasmodels import weights 
     389 
     390    # reload the user-defined weights 
     391    weights.load_weights() 
     392    x, wx = weights.get_weights('laplace', n=35, width=0.1, nsigmas=3, value=50, 
     393                                limits=[0, inf], relative=True) 
     394 
     395    # plot the weights 
     396    plt.interactive(True) 
     397    plt.plot(x, wx, 'x') 
     398 
     399The *self.nsigmas* and *self.npts* parameters are normally used to control 
     400the accuracy of the distribution integral. The *self._linspace* function 
     401uses them to define the *x* values (along with the *center*, *sigma*, 
     402*lb*, and *ub* which are passed as parameters).  If you repurpose npts or 
     403nsigmas you will need to generate your own *x*.  Be sure to honour the 
     404limits *lb* and *ub*, for example to disallow a negative radius or constrain 
     405the volume fraction to lie between zero and one. 
     406 
     407To activate a user-defined distribution, set the following environment variable: 
     408 
     409    SASMODELS_WEIGHTS=path/to/folder/name_of_distribution.py 
     410 
     411.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
     412 
    331413Note about DLS polydispersity 
    332414^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
  • sasmodels/compare.py

    raf7a97c raf7a97c  
    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 
     
    783783            model_info = base._kernel.info 
    784784            dim = base._kernel.dim 
    785             plot_weights(model_info, get_mesh(model_info, base_pars, dim=dim)) 
     785            weights.plot_weights(model_info, get_mesh(model_info, base_pars, dim=dim)) 
    786786        if opts['show_profile']: 
    787787            import pylab 
     
    14391439    #import pprint; pprint.pprint(model_info) 
    14401440 
     1441    # Hack to load user-defined distributions; run through all parameters 
     1442    # and make sure any pd_type parameter is a defined distribution. 
     1443    if (any(p.endswith('pd_type') and v not in weights.MODELS 
     1444            for p, v in pars.items()) or 
     1445        any(p.endswith('pd_type') and v not in weights.MODELS 
     1446            for p, v in pars2.items())): 
     1447       weights.load_weights() 
     1448 
    14411449    if opts['show_pars']: 
    14421450        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 r910c0f4  
    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.