Changeset cff6ede in sasmodels


Ignore:
Timestamp:
Jul 28, 2018 10:43:41 AM (3 weeks ago)
Author:
GitHub <noreply@…>
Parents:
581661f (diff), d0fdba2 (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:
Paul Kienzle <pkienzle@…> (07/28/18 10:43:41)
git-committer:
GitHub <noreply@…> (07/28/18 10:43:41)
Message:

Merge d0fdba2d18deb51c93a5bc2376505a4ee81ade9c into 581661fc37697834c449857993338ae5c0cbac51

Files:
2 added
7 edited

Legend:

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

    rd712a0f rf41027b  
    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, put it in a file such as *distname.py* 
     408in the *SAS_WEIGHTS_PATH* folder.  This is defined with an environment 
     409variable, defaulting to:: 
     410 
     411    SAS_WEIGHTS_PATH=~/.sasview/weights 
     412 
     413The weights path is loaded on startup.  To update the distribution definition 
     414in a running application you will need to enter the following python commands:: 
     415 
     416    import sasmodels.weights 
     417    sasmodels.weights.load_weights('path/to/distname.py') 
     418 
     419.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
     420 
    331421Note about DLS polydispersity 
    332422^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
  • sasmodels/compare.py

    raf7a97c rd0fdba2  
    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 
     
    114114 
    115115    === environment variables === 
    116     -DSAS_MODELPATH=path sets directory containing custom models 
     116    -DSAS_MODELPATH=~/.sasmodels/custom_models sets path to custom models 
     117    -DSAS_WEIGHTS_PATH=~/.sasview/weights sets path to custom distributions 
    117118    -DSAS_OPENCL=vendor:device|none sets the target OpenCL device 
    118119    -DXDG_CACHE_HOME=~/.cache sets the pyopencl cache root (linux only) 
    119120    -DSAS_COMPILER=tinycc|msvc|mingw|unix sets the DLL compiler 
    120     -DSAS_OPENMP=1 turns on OpenMP for the DLLs 
    121     -DSAS_DLL_PATH=path sets the path to the compiled modules 
     121    -DSAS_OPENMP=0 set to 1 to turn on OpenMP for the DLLs 
     122    -DSAS_DLL_PATH=~/.sasmodels/compiled_models sets the DLL cache 
    122123 
    123124The interpretation of quad precision depends on architecture, and may 
     
    783784            model_info = base._kernel.info 
    784785            dim = base._kernel.dim 
    785             plot_weights(model_info, get_mesh(model_info, base_pars, dim=dim)) 
     786            weights.plot_weights(model_info, get_mesh(model_info, base_pars, dim=dim)) 
    786787        if opts['show_profile']: 
    787788            import pylab 
     
    14391440    #import pprint; pprint.pprint(model_info) 
    14401441 
     1442    # Hack to load user-defined distributions; run through all parameters 
     1443    # and make sure any pd_type parameter is a defined distribution. 
     1444    if (any(p.endswith('pd_type') and v not in weights.MODELS 
     1445            for p, v in pars.items()) or 
     1446        any(p.endswith('pd_type') and v not in weights.MODELS 
     1447            for p, v in pars2.items())): 
     1448       weights.load_weights() 
     1449 
    14411450    if opts['show_pars']: 
    14421451        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 rf41027b  
    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): 
  • doc/guide/gpu_setup.rst

    r59485a4 r63602b1  
    139139the compiler. 
    140140 
    141 On Windows, set *SASCOMPILER=tinycc* for the tinycc compiler, 
    142 *SASCOMPILER=msvc* for the Microsoft Visual C compiler, 
    143 or *SASCOMPILER=mingw* for the MinGW compiler. If TinyCC is available 
     141On Windows, set *SAS_COMPILER=tinycc* for the tinycc compiler, 
     142*SAS_COMPILER=msvc* for the Microsoft Visual C compiler, 
     143or *SAS_COMPILER=mingw* for the MinGW compiler. If TinyCC is available 
    144144on the python path (it is provided with SasView), that will be the 
    145145default. If you want one of the other compilers, be sure to have it 
  • sasmodels/data.py

    r1a8c11c r581661f  
    504504            # and the data mask will be added to it. 
    505505            #mtheory = masked_array(theory, data.mask.copy()) 
    506             theory_x = data.x[~data.mask] 
     506            theory_x = data.x[data.mask == 0] 
    507507            mtheory = masked_array(theory) 
    508508            mtheory[~np.isfinite(mtheory)] = masked 
     
    545545 
    546546    if use_resid: 
    547         theory_x = data.x[~data.mask] 
     547        theory_x = data.x[data.mask == 0] 
    548548        mresid = masked_array(resid) 
    549549        mresid[~np.isfinite(mresid)] = masked 
  • sasmodels/model_test.py

    • Property mode changed from 100644 to 100755
    r3221de0 r012cd34  
    376376        stream.writeln(traceback.format_exc()) 
    377377        return 
    378     # Run the test suite 
    379     suite.run(result) 
    380  
    381     # Print the failures and errors 
    382     for _, tb in result.errors: 
    383         stream.writeln(tb) 
    384     for _, tb in result.failures: 
    385         stream.writeln(tb) 
    386378 
    387379    # Warn if there are no user defined tests. 
     
    393385    # iterator since we don't have direct access to the list of tests in the 
    394386    # test suite. 
     387    # In Qt5 suite.run() will clear all tests in the suite after running 
     388    # with no way of retaining them for the test below, so let's check 
     389    # for user tests before running the suite. 
    395390    for test in suite: 
    396391        if not test.info.tests: 
     
    399394    else: 
    400395        stream.writeln("Note: no test suite created --- this should never happen") 
     396 
     397    # Run the test suite 
     398    suite.run(result) 
     399 
     400    # Print the failures and errors 
     401    for _, tb in result.errors: 
     402        stream.writeln(tb) 
     403    for _, tb in result.failures: 
     404        stream.writeln(tb) 
    401405 
    402406    output = stream.getvalue() 
Note: See TracChangeset for help on using the changeset viewer.