Changes in / [9150036:e2da671] in sasmodels


Ignore:
Files:
5 added
4 edited

Legend:

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

    rd089a00 ra5cb9bc  
    1111-------------------------------------------- 
    1212 
    13 For some models we can calculate the average intensity for a population of  
    14 particles that possess size and/or orientational (ie, angular) distributions.  
    15 In SasView we call the former *polydispersity* but use the parameter *PD* to  
    16 parameterise both. In other words, the meaning of *PD* in a model depends on  
     13For some models we can calculate the average intensity for a population of 
     14particles that possess size and/or orientational (ie, angular) distributions. 
     15In SasView we call the former *polydispersity* but use the parameter *PD* to 
     16parameterise both. In other words, the meaning of *PD* in a model depends on 
    1717the actual parameter it is being applied too. 
    1818 
    19 The resultant intensity is then normalized by the average particle volume such  
     19The resultant intensity is then normalized by the average particle volume such 
    2020that 
    2121 
     
    2424  P(q) = \text{scale} \langle F^* F \rangle / V + \text{background} 
    2525 
    26 where $F$ is the scattering amplitude and $\langle\cdot\rangle$ denotes an  
     26where $F$ is the scattering amplitude and $\langle\cdot\rangle$ denotes an 
    2727average over the distribution $f(x; \bar x, \sigma)$, giving 
    2828 
    2929.. math:: 
    3030 
    31   P(q) = \frac{\text{scale}}{V} \int_\mathbb{R}  
     31  P(q) = \frac{\text{scale}}{V} \int_\mathbb{R} 
    3232  f(x; \bar x, \sigma) F^2(q, x)\, dx + \text{background} 
    3333 
    3434Each distribution is characterized by a center value $\bar x$ or 
    3535$x_\text{med}$, a width parameter $\sigma$ (note this is *not necessarily* 
    36 the standard deviation, so read the description of the distribution carefully),  
    37 the number of sigmas $N_\sigma$ to include from the tails of the distribution,  
    38 and the number of points used to compute the average. The center of the  
    39 distribution is set by the value of the model parameter. 
    40  
    41 The distribution width applied to *volume* (ie, shape-describing) parameters  
    42 is relative to the center value such that $\sigma = \mathrm{PD} \cdot \bar x$.  
    43 However, the distribution width applied to *orientation* parameters is just  
    44 $\sigma = \mathrm{PD}$. 
     36the standard deviation, so read the description carefully), the number of 
     37sigmas $N_\sigma$ to include from the tails of the distribution, and the 
     38number of points used to compute the average. The center of the distribution 
     39is set by the value of the model parameter. The meaning of a polydispersity 
     40parameter *PD* (not to be confused with a molecular weight distributions 
     41in polymer science) in a model depends on the type of parameter it is being 
     42applied too. 
     43 
     44The distribution width applied to *volume* (ie, shape-describing) parameters 
     45is relative to the center value such that $\sigma = \mathrm{PD} \cdot \bar x$. 
     46However, the distribution width applied to *orientation* (ie, angle-describing) 
     47parameters is just $\sigma = \mathrm{PD}$. 
    4548 
    4649$N_\sigma$ determines how far into the tails to evaluate the distribution, 
     
    5255 
    5356Users should note that the averaging computation is very intensive. Applying 
    54 polydispersion and/or orientational distributions to multiple parameters at  
    55 the same time, or increasing the number of points in the distribution, will  
    56 require patience! However, the calculations are generally more robust with  
     57polydispersion and/or orientational distributions to multiple parameters at 
     58the same time, or increasing the number of points in the distribution, will 
     59require patience! However, the calculations are generally more robust with 
    5760more data points or more angles. 
    5861 
     
    6669*  *Schulz Distribution* 
    6770*  *Array Distribution* 
     71*  *User-defined Distributions* 
    6872 
    6973These are all implemented as *number-average* distributions. 
    7074 
    71 Additional distributions are under consideration. 
    7275 
    7376**Beware: when the Polydispersity & Orientational Distribution panel in SasView is** 
     
    7578**This may not be suitable. See Suggested Applications below.** 
    7679 
    77 .. note:: In 2009 IUPAC decided to introduce the new term 'dispersity' to replace  
    78            the term 'polydispersity' (see `Pure Appl. Chem., (2009), 81(2),  
    79            351-353 <http://media.iupac.org/publications/pac/2009/pdf/8102x0351.pdf>`_  
    80            in order to make the terminology describing distributions of chemical  
    81            properties unambiguous. However, these terms are unrelated to the  
    82            proportional size distributions and orientational distributions used in  
     80.. note:: In 2009 IUPAC decided to introduce the new term 'dispersity' to replace 
     81           the term 'polydispersity' (see `Pure Appl. Chem., (2009), 81(2), 
     82           351-353 <http://media.iupac.org/publications/pac/2009/pdf/8102x0351.pdf>`_ 
     83           in order to make the terminology describing distributions of chemical 
     84           properties unambiguous. However, these terms are unrelated to the 
     85           proportional size distributions and orientational distributions used in 
    8386           SasView models. 
    8487 
     
    9295or angular orientations, consider using the Gaussian or Boltzmann distributions. 
    9396 
    94 If applying polydispersion to parameters describing angles, use the Uniform  
    95 distribution. Beware of using distributions that are always positive (eg, the  
     97If applying polydispersion to parameters describing angles, use the Uniform 
     98distribution. Beware of using distributions that are always positive (eg, the 
    9699Lognormal) because angles can be negative! 
    97100 
    98 The array distribution allows a user-defined distribution to be applied. 
     101The array distribution provides a very simple means of implementing a user- 
     102defined distribution, but without any fittable parameters. Greater flexibility 
     103is conferred by the user-defined distribution. 
    99104 
    100105.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
     
    334339.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
    335340 
     341User-defined Distributions 
     342^^^^^^^^^^^^^^^^^^^^^^^^^^ 
     343 
     344You can also define your own distribution by creating a python file defining a 
     345*Distribution* object with a *_weights* method.  The *_weights* method takes 
     346*center*, *sigma*, *lb* and *ub* as arguments, and can access *self.npts* 
     347and *self.nsigmas* from the distribution.  They are interpreted as follows: 
     348 
     349* *center* the value of the shape parameter (for size dispersity) or zero 
     350  if it is an angular dispersity.  This parameter may be fitted. 
     351 
     352* *sigma* the width of the distribution, which is the polydispersity parameter 
     353  times the center for size dispersity, or the polydispersity parameter alone 
     354  for angular dispersity.  This parameter may be fitted. 
     355 
     356* *lb*, *ub* are the parameter limits (lower & upper bounds) given in the model 
     357  definition file.  For example, a radius parameter has *lb* equal to zero.  A 
     358  volume fraction parameter would have *lb* equal to zero and *ub* equal to one. 
     359 
     360* *self.nsigmas* the distance to go into the tails when evaluating the 
     361  distribution.  For a two parameter distribution, this value could be 
     362  co-opted to use for the second parameter, though it will not be available 
     363  for fitting. 
     364 
     365* *self.npts* the number of points to use when evaluating the distribution. 
     366  The user will adjust this to trade calculation time for accuracy, but the 
     367  distribution code is free to return more or fewer, or use it for the third 
     368  parameter in a three parameter distribution. 
     369 
     370As an example, the code following wraps the Laplace distribution from scipy stats:: 
     371 
     372    import numpy as np 
     373    from scipy.stats import laplace 
     374 
     375    from sasmodels import weights 
     376 
     377    class Dispersion(weights.Dispersion): 
     378        r""" 
     379        Laplace distribution 
     380 
     381        .. math:: 
     382 
     383            w(x) = e^{-\sigma |x - \mu|} 
     384        """ 
     385        type = "laplace" 
     386        default = dict(npts=35, width=0, nsigmas=3)  # default values 
     387        def _weights(self, center, sigma, lb, ub): 
     388            x = self._linspace(center, sigma, lb, ub) 
     389            wx = laplace.pdf(x, center, sigma) 
     390            return x, wx 
     391 
     392You can plot the weights for a given value and width using the following:: 
     393 
     394    from numpy import inf 
     395    from matplotlib import pyplot as plt 
     396    from sasmodels import weights 
     397 
     398    # reload the user-defined weights 
     399    weights.load_weights() 
     400    x, wx = weights.get_weights('laplace', n=35, width=0.1, nsigmas=3, value=50, 
     401                                limits=[0, inf], relative=True) 
     402 
     403    # plot the weights 
     404    plt.interactive(True) 
     405    plt.plot(x, wx, 'x') 
     406 
     407The *self.nsigmas* and *self.npts* parameters are normally used to control 
     408the accuracy of the distribution integral. The *self._linspace* function 
     409uses them to define the *x* values (along with the *center*, *sigma*, 
     410*lb*, and *ub* which are passed as parameters).  If you repurpose npts or 
     411nsigmas you will need to generate your own *x*.  Be sure to honour the 
     412limits *lb* and *ub*, for example to disallow a negative radius or constrain 
     413the volume fraction to lie between zero and one. 
     414 
     415To activate a user-defined distribution, put it in a file such as *distname.py* 
     416in the *SAS_WEIGHTS_PATH* folder.  This is defined with an environment 
     417variable, defaulting to:: 
     418 
     419    SAS_WEIGHTS_PATH=~/.sasview/weights 
     420 
     421The weights path is loaded on startup.  To update the distribution definition 
     422in a running application you will need to enter the following python commands:: 
     423 
     424    import sasmodels.weights 
     425    sasmodels.weights.load_weights('path/to/distname.py') 
     426 
     427.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
     428 
    336429Note about DLS polydispersity 
    337430^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
    338431 
    339 Several measures of polydispersity abound in Dynamic Light Scattering (DLS) and  
    340 it should not be assumed that any of the following can be simply equated with  
     432Several measures of polydispersity abound in Dynamic Light Scattering (DLS) and 
     433it should not be assumed that any of the following can be simply equated with 
    341434the polydispersity *PD* parameter used in SasView. 
    342435 
    343 The dimensionless **Polydispersity Index (PI)** is a measure of the width of the  
    344 distribution of autocorrelation function decay rates (*not* the distribution of  
    345 particle sizes itself, though the two are inversely related) and is defined by  
     436The dimensionless **Polydispersity Index (PI)** is a measure of the width of the 
     437distribution of autocorrelation function decay rates (*not* the distribution of 
     438particle sizes itself, though the two are inversely related) and is defined by 
    346439ISO 22412:2017 as 
    347440 
     
    350443    PI = \mu_{2} / \bar \Gamma^2 
    351444 
    352 where $\mu_\text{2}$ is the second cumulant, and $\bar \Gamma^2$ is the  
     445where $\mu_\text{2}$ is the second cumulant, and $\bar \Gamma^2$ is the 
    353446intensity-weighted average value, of the distribution of decay rates. 
    354447 
     
    359452    PI = \sigma^2 / 2\bar \Gamma^2 
    360453 
    361 where $\sigma$ is the standard deviation, allowing a **Relative Polydispersity (RP)**  
     454where $\sigma$ is the standard deviation, allowing a **Relative Polydispersity (RP)** 
    362455to be defined as 
    363456 
     
    366459    RP = \sigma / \bar \Gamma = \sqrt{2 \cdot PI} 
    367460 
    368 PI values smaller than 0.05 indicate a highly monodisperse system. Values  
     461PI values smaller than 0.05 indicate a highly monodisperse system. Values 
    369462greater than 0.7 indicate significant polydispersity. 
    370463 
    371 The **size polydispersity P-parameter** is defined as the relative standard  
    372 deviation coefficient of variation   
     464The **size polydispersity P-parameter** is defined as the relative standard 
     465deviation coefficient of variation 
    373466 
    374467.. math:: 
     
    377470 
    378471where $\nu$ is the variance of the distribution and $\bar R$ is the mean 
    379 value of $R$. Here, the product $P \bar R$ is *equal* to the standard  
     472value of $R$. Here, the product $P \bar R$ is *equal* to the standard 
    380473deviation of the Lognormal distribution. 
    381474 
  • sasmodels/compare.py

    r4de14584 r4de14584  
    3939 
    4040from . import core 
     41from . import weights 
    4142from . import kerneldll 
    4243from . import kernelcl 
     
    4546from .direct_model import DirectModel, get_mesh 
    4647from .generate import FLOAT_RE, set_integration_size 
    47 from .weights import plot_weights 
    4848 
    4949# pylint: disable=unused-import 
     
    115115 
    116116    === environment variables === 
    117     -DSAS_MODELPATH=path sets directory containing custom models 
     117    -DSAS_MODELPATH=~/.sasmodels/custom_models sets path to custom models 
     118    -DSAS_WEIGHTS_PATH=~/.sasview/weights sets path to custom distributions 
    118119    -DSAS_OPENCL=vendor:device|cuda:device|none sets the target GPU device 
    119120    -DXDG_CACHE_HOME=~/.cache sets the pyopencl cache root (linux only) 
    120121    -DSAS_COMPILER=tinycc|msvc|mingw|unix sets the DLL compiler 
    121     -DSAS_OPENMP=1 turns on OpenMP for the DLLs 
    122     -DSAS_DLL_PATH=path sets the path to the compiled modules 
     122    -DSAS_OPENMP=0 set to 1 to turn on OpenMP for the DLLs 
     123    -DSAS_DLL_PATH=~/.sasmodels/compiled_models sets the DLL cache 
    123124 
    124125The interpretation of quad precision depends on architecture, and may 
     
    725726        set_integration_size(model_info, ngauss) 
    726727 
    727     if (dtype != "default" and not dtype.endswith('!')  
     728    if (dtype != "default" and not dtype.endswith('!') 
    728729            and not (kernelcl.use_opencl() or kernelcuda.use_cuda())): 
    729730        raise RuntimeError("OpenCL not available " + kernelcl.OPENCL_ERROR) 
     
    784785            model_info = base._kernel.info 
    785786            dim = base._kernel.dim 
    786             plot_weights(model_info, get_mesh(model_info, base_pars, dim=dim)) 
     787            weights.plot_weights(model_info, get_mesh(model_info, base_pars, dim=dim)) 
    787788        if opts['show_profile']: 
    788789            import pylab 
     
    14411442    #import pprint; pprint.pprint(model_info) 
    14421443 
     1444    # Hack to load user-defined distributions; run through all parameters 
     1445    # and make sure any pd_type parameter is a defined distribution. 
     1446    if (any(p.endswith('pd_type') and v not in weights.MODELS 
     1447            for p, v in pars.items()) or 
     1448        any(p.endswith('pd_type') and v not in weights.MODELS 
     1449            for p, v in pars2.items())): 
     1450       weights.load_weights() 
     1451 
    14431452    if opts['show_pars']: 
    14441453        if model_info.name != model_info2.name or pars != pars2: 
  • sasmodels/sasview_model.py

    r3a1afed r3a1afed  
    3232from .details import make_kernel_args, dispersion_mesh 
    3333from .kernelcl import reset_environment 
     34 
     35# Hack: load in any custom distributions 
     36# Uses ~/.sasview/weights/*.py unless SASMODELS_WEIGHTS is set in the environ. 
     37# Override with weights.load_weights(pattern="<weights_path>/*.py") 
     38weights.load_weights() 
    3439 
    3540# pylint: disable=unused-import 
  • sasmodels/weights.py

    re2592f0 re2592f0  
    231231)) 
    232232 
     233SAS_WEIGHTS_PATH = "~/.sasview/weights" 
     234def load_weights(pattern=None): 
     235    # type: (str) -> None 
     236    """ 
     237    Load dispersion distributions matching the given glob 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        path = os.environ.get("SAS_WEIGHTS_PATH", SAS_WEIGHTS_PATH) 
     247        pattern = os.path.join(path, "*.py") 
     248    for filename in sorted(glob.glob(os.path.expanduser(pattern))): 
     249        try: 
     250            #print("loading weights from", filename) 
     251            module = load_custom_kernel_module(filename) 
     252            MODELS[module.Dispersion.type] = module.Dispersion 
     253        except Exception as exc: 
     254            logging.error(traceback.format_exc(exc)) 
    233255 
    234256def get_weights(disperser, n, width, nsigmas, value, limits, relative): 
Note: See TracChangeset for help on using the changeset viewer.