Changeset ce27e21 in sasmodels for sasmodels/weights.py


Ignore:
Timestamp:
Aug 24, 2014 7:18:14 PM (10 years ago)
Author:
Paul Kienzle <pkienzle@…>
Branches:
master, core_shell_microgels, costrafo411, magnetic_model, release_v0.94, release_v0.95, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
Children:
1780d59
Parents:
14de349
Message:

first pass for sasview wrapper around opencl models

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sasmodels/weights.py

    r14de349 rce27e21  
     1# TODO: include dispersion docs with the disperser models 
     2from math import sqrt 
    13import numpy as np 
     4from scipy.special import gammaln 
    25 
    3 class GaussianDispersion(object): 
    4     def __init__(self, npts=35, width=0, nsigmas=3): #number want, percent deviation, #standard deviations from mean 
    5         self.type = 'gaussian' 
    6         self.npts = npts 
    7         self.width = width 
    8         self.nsigmas = nsigmas 
     6class Dispersion(object): 
     7    """ 
     8    Base dispersion object. 
     9 
     10    Subclasses should define *_weights(center, sigma, lb, ub)* 
     11    which returns the x points and their corresponding weights. 
     12    """ 
     13    type = "base disperser" 
     14    default = dict(npts=35, width=0, nsigmas=3) 
     15    def __init__(self, npts=None, width=None, nsigmas=None): 
     16        self.npts = self.default['npts'] if npts is None else npts 
     17        self.width = self.default['width'] if width is None else width 
     18        self.nsigmas = self.default['nsigmas'] if nsigmas is None else nsigmas 
    919 
    1020    def get_pars(self): 
    11         return self.__dict__ 
     21        pars = {'type': self.type} 
     22        pars.update(self.__dict__) 
     23        return pars 
    1224 
    13     def get_weights(self, center, min, max, relative): 
    14         """ *center* is the center of the distribution 
    15         *min*,*max* are the min, max allowed values 
    16         *relative* is True if the width is relative to the center instead of absolute 
    17         For polydispersity use relative.  For orientation parameters use absolute.""" 
     25    def set_weights(self, values, weights): 
     26        raise RuntimeError("set_weights is only available for ArrayDispersion") 
     27 
     28    def get_weights(self, center, lb, ub, relative): 
     29        """ 
     30        Return the weights for the distribution. 
     31 
     32        *center* is the center of the distribution 
     33 
     34        *lb*,*ub* are the min and max allowed values 
     35 
     36        *relative* is True if the distribution width is proportional to the 
     37        center value instead of absolute.  For polydispersity use relative. 
     38        For orientation parameters use absolute. 
     39        """ 
    1840        npts, width, nsigmas = self.npts, self.width, self.nsigmas 
    19         sigma = width * center if relative else width 
     41        sigma = self.width * center if relative else self.width 
    2042        if sigma == 0: 
    21             return np.array([center],'d'), np.array([1.], 'd') 
    22         x = center + np.linspace(-nsigmas * sigma, +nsigmas * sigma, npts) 
    23         x = x[(x >= min) & (x <= max)] 
     43            return np.array([center], 'd'), np.array([1.], 'd') 
     44        return self._weights(center, sigma, lb, ub) 
     45 
     46    def _weights(self, center, sigma, lb, ub): 
     47        """actual work of computing the weights""" 
     48        raise NotImplementedError 
     49 
     50    def _linspace(self, center, sigma, lb, ub): 
     51        """helper function to provide linear spaced weight points within range""" 
     52        npts, nsigmas = self.npts, self.nsigmas 
     53        x = center + np.linspace(-nsigmas*sigma, +nsigmas*sigma, npts) 
     54        x = x[(x >= lb) & (x <= ub)] 
     55        return x 
     56 
     57 
     58class GaussianDispersion(Dispersion): 
     59    type = "gaussian" 
     60    default = dict(npts=35, width=0, nsigmas=3) 
     61    def _weights(self, center, sigma, lb, ub): 
     62        x = self._linspace(center, sigma, lb, ub) 
    2463        px = np.exp((x-center)**2 / (-2.0 * sigma * sigma)) 
    2564        return x, px 
    2665 
     66 
     67class RectangleDispersion(Dispersion): 
     68    type = "rectangle" 
     69    default = dict(npts=35, width=0, nsigmas=1.70325) 
     70    def _weights(self, center, sigma, lb, ub): 
     71        x = self._linspace(center, sigma*sqrt(3.0), lb, ub) 
     72        px = np.ones_like(x) 
     73        return x, px 
     74 
     75 
     76class LogNormalDispersion(Dispersion): 
     77    type = "lognormal" 
     78    default = dict(npts=80, width=0, nsigmas=8) 
     79    def _weights(self, center, sigma, lb, ub): 
     80        x = self._linspace(center, sigma, max(lb,1e-8), max(ub,1e-8)) 
     81        px = np.exp(-0.5*(np.log(x)-center)**2)/sigma**2/(x*sigma) 
     82        return x, px 
     83 
     84 
     85class SchulzDispersion(Dispersion): 
     86    type = "schulz" 
     87    default = dict(npts=80, width=0, nsigmas=8) 
     88    def _weights(self, center, sigma, lb, ub): 
     89        x = self._linspace(center, sigma, max(lb,1e-8), max(ub,1e-8)) 
     90        R= x/center 
     91        z = (center/sigma)**2 
     92        arg = z*np.log(z) + (z-1)*np.log(R) - R*z - np.log(center) - gammaln(z) 
     93        px = np.exp(arg) 
     94        return x, px 
     95 
     96 
     97class ArrayDispersion(Dispersion): 
     98    type = "array" 
     99    default = dict(npts=35, width=0, nsigmas=1) 
     100    def __init__(self, npts=None, width=None, nsigmas=None): 
     101        Dispersion.__init__(self, npts, width, nsigmas) 
     102        self.values = np.array([0.], 'd') 
     103        self.weights = np.array([1.], 'd') 
     104 
     105    def set_weights(self, values, weights): 
     106        self.values = np.ascontiguousarray(values, 'd') 
     107        self.weights = np.ascontiguousarray(weights, 'd') 
     108        self.npts = len(values) 
     109 
     110    def _weights(self, center, sigma, lb, ub): 
     111        # TODO: interpolate into the array dispersion using npts 
     112        x = center + self.values*sigma 
     113        idx = (x>=lb)&(x<=ub) 
     114        x = x[idx] 
     115        px = self.weights[idx] 
     116        return x, px 
     117 
     118 
     119models = dict((d.type,d) for d in ( 
     120    GaussianDispersion, RectangleDispersion, 
     121    ArrayDispersion, SchulzDispersion, LogNormalDispersion 
     122)) 
     123 
     124def get_weights(disperser, n, width, nsigma, value, limits, relative): 
     125    cls = models[disperser] 
     126    obj = cls(n, width, nsigma) 
     127    v,w = obj.get_weights(value, limits[0], limits[1], relative) 
     128    return v,w 
Note: See TracChangeset for help on using the changeset viewer.