Changeset 803f835 in sasmodels


Ignore:
Timestamp:
Jan 29, 2016 8:43:44 AM (8 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:
823e620
Parents:
d07c883
Message:

delint

Files:
2 edited

Legend:

Unmodified
Added
Removed
  • extra/pylint.rc

    rd4666ca r803f835  
    108108# Good variable names which should always be accepted, separated by a comma 
    109109good-names=_, 
    110     input, 
    111     h,i,j,k,n,w,x,y,z, 
    112     q,qx,qy,qz, 
    113     dt,dx,dy,dz,id, 
    114     Iq,dIq,Qx,Qy,Qz,Iqxy, 
    115     p, 
     110    input, id, 
     111    h, i, j, k, n, p, v, w, x, y, z, 
     112    q, qx, qy, qz, Q, Qx, Qy, Qz, 
     113    dt, dx, dy, dz, dq, 
     114    Iq, dIq, Iqxy, Iq_calc, 
    116115    ER, call_ER, VR, call_VR, 
    117116    Rmax, SElength, 
  • sasmodels/direct_model.py

    r9404dd3 r803f835  
    1 import warnings 
     1""" 
     2Class interface to the model calculator. 
     3 
     4Calling a model is somewhat non-trivial since the functions called depend 
     5on the data type.  For 1D data the *Iq* kernel needs to be called, for 
     62D data the *Iqxy* kernel needs to be called, and for SESANS data the 
     7*Iq* kernel needs to be called followed by a Hankel transform.  Before 
     8the kernel is called an appropriate *q* calculation vector needs to be 
     9constructed.  This is not the simple *q* vector where you have measured 
     10the data since the resolution calculation will require values beyond the 
     11range of the measured data.  After the calculation the resolution calculator 
     12must be called to return the predicted value for each measured data point. 
     13 
     14:class:`DirectModel` is a callable object that takes *parameter=value* 
     15keyword arguments and returns the appropriate theory values for the data. 
     16 
     17:class:`DataMixin` does the real work of interpreting the data and calling 
     18the model calculator.  This is used by :class:`DirectModel`, which uses 
     19direct parameter values and by :class:`bumps_model.Experiment` which wraps 
     20the parameter values in boxes so that the user can set fitting ranges, etc. 
     21on the individual parameters and send the model to the Bumps optimizers. 
     22""" 
     23from __future__ import print_function 
    224 
    325import numpy as np 
     
    1941    currently used by :class:`sasview_model.SasviewModel` since this will 
    2042    require a number of changes to SasView before we can do it. 
     43 
     44    :meth:`_interpret_data` initializes the data structures necessary 
     45    to manage the calculations.  This sets attributes in the child class 
     46    such as *data_type* and *resolution*. 
     47 
     48    :meth:`_calc_theory` evaluates the model at the given control values. 
     49 
     50    :meth:`_set_data` sets the intensity data in the data object, 
     51    possibly with random noise added.  This is useful for simulating a 
     52    dataset with the results from :meth:`_calc_theory`. 
    2153    """ 
    2254    def _interpret_data(self, data, model): 
     55        # pylint: disable=attribute-defined-outside-init 
     56 
    2357        self._data = data 
    2458        self._model = model 
     
    3670        if self.data_type == 'sesans': 
    3771            q = sesans.make_q(data.sample.zacceptance, data.Rmax) 
    38             self.index = slice(None, None) 
     72            index = slice(None, None) 
     73            res = None 
    3974            if data.y is not None: 
    40                 self.Iq = data.y 
    41                 self.dIq = data.dy 
     75                Iq, dIq = data.y, data.dy 
     76            else: 
     77                Iq, dIq = None, None 
    4278            #self._theory = np.zeros_like(q) 
    4379            q_vectors = [q] 
     
    4985            qmax = getattr(data, 'qmax', np.inf) 
    5086            accuracy = getattr(data, 'accuracy', 'Low') 
    51             self.index = ~data.mask & (q >= qmin) & (q <= qmax) 
     87            index = ~data.mask & (q >= qmin) & (q <= qmax) 
    5288            if data.data is not None: 
    53                 self.index &= ~np.isnan(data.data) 
    54                 self.Iq = data.data[self.index] 
    55                 self.dIq = data.err_data[self.index] 
    56             self.resolution = resolution2d.Pinhole2D(data=data, index=self.index, 
    57                                                      nsigma=3.0, accuracy=accuracy) 
     89                index &= ~np.isnan(data.data) 
     90                Iq = data.data[index] 
     91                dIq = data.err_data[index] 
     92            else: 
     93                Iq, dIq = None, None 
     94            res = resolution2d.Pinhole2D(data=data, index=index, 
     95                                         nsigma=3.0, accuracy=accuracy) 
    5896            #self._theory = np.zeros_like(self.Iq) 
    59             q_vectors = self.resolution.q_calc 
     97            q_vectors = res.q_calc 
    6098        elif self.data_type == 'Iq': 
    61             self.index = (data.x >= data.qmin) & (data.x <= data.qmax) 
     99            index = (data.x >= data.qmin) & (data.x <= data.qmax) 
    62100            if data.y is not None: 
    63                 self.index &= ~np.isnan(data.y) 
    64                 self.Iq = data.y[self.index] 
    65                 self.dIq = data.dy[self.index] 
     101                index &= ~np.isnan(data.y) 
     102                Iq = data.y[index] 
     103                dIq = data.dy[index] 
     104            else: 
     105                Iq, dIq = None, None 
    66106            if getattr(data, 'dx', None) is not None: 
    67                 q, dq = data.x[self.index], data.dx[self.index] 
    68                 if (dq>0).any(): 
    69                     self.resolution = resolution.Pinhole1D(q, dq) 
     107                q, dq = data.x[index], data.dx[index] 
     108                if (dq > 0).any(): 
     109                    res = resolution.Pinhole1D(q, dq) 
    70110                else: 
    71                     self.resolution = resolution.Perfect1D(q) 
    72             elif (getattr(data, 'dxl', None) is not None and 
    73                           getattr(data, 'dxw', None) is not None): 
    74                 self.resolution = resolution.Slit1D(data.x[self.index], 
    75                                                     width=data.dxh[self.index], 
    76                                                     height=data.dxw[self.index]) 
    77             else: 
    78                 self.resolution = resolution.Perfect1D(data.x[self.index]) 
     111                    res = resolution.Perfect1D(q) 
     112            elif (getattr(data, 'dxl', None) is not None 
     113                  and getattr(data, 'dxw', None) is not None): 
     114                res = resolution.Slit1D(data.x[index], 
     115                                        width=data.dxh[index], 
     116                                        height=data.dxw[index]) 
     117            else: 
     118                res = resolution.Perfect1D(data.x[index]) 
    79119 
    80120            #self._theory = np.zeros_like(self.Iq) 
    81             q_vectors = [self.resolution.q_calc] 
     121            q_vectors = [res.q_calc] 
    82122        else: 
    83123            raise ValueError("Unknown data type") # never gets here 
     
    87127        self._kernel_inputs = [v for v in q_vectors] 
    88128        self._kernel = None 
     129        self.Iq, self.dIq, self.index = Iq, dIq, index 
     130        self.resolution = res 
    89131 
    90132    def _set_data(self, Iq, noise=None): 
     133        # pylint: disable=attribute-defined-outside-init 
    91134        if noise is not None: 
    92135            self.dIq = Iq*noise*0.01 
     
    107150        if self._kernel is None: 
    108151            q_input = self._model.make_input(self._kernel_inputs) 
    109             self._kernel = self._model(q_input) 
     152            self._kernel = self._model(q_input)  # pylint: disable=attribute-defined-outside-init 
    110153 
    111154        Iq_calc = call_kernel(self._kernel, pars, cutoff=cutoff) 
     
    120163 
    121164class DirectModel(DataMixin): 
     165    """ 
     166    Create a calculator object for a model. 
     167 
     168    *data* is 1D SAS, 2D SAS or SESANS data 
     169 
     170    *model* is a model calculator return from :func:`generate.load_model` 
     171 
     172    *cutoff* is the polydispersity weight cutoff. 
     173    """ 
    122174    def __init__(self, data, model, cutoff=1e-5): 
    123175        self.model = model 
    124176        self.cutoff = cutoff 
     177        # Note: _interpret_data defines the model attributes 
    125178        self._interpret_data(data, model) 
    126179        self.kernel = make_kernel(self.model, self._kernel_inputs) 
     180 
    127181    def __call__(self, **pars): 
    128182        return self._calc_theory(pars, cutoff=self.cutoff) 
     183 
    129184    def ER(self, **pars): 
     185        """ 
     186        Compute the equivalent radius for the model. 
     187 
     188        Return 0. if not defined. 
     189        """ 
    130190        return call_ER(self.model.info, pars) 
     191 
    131192    def VR(self, **pars): 
     193        """ 
     194        Compute the equivalent volume for the model, including polydispersity 
     195        effects. 
     196 
     197        Return 1. if not defined. 
     198        """ 
    132199        return call_VR(self.model.info, pars) 
     200 
    133201    def simulate_data(self, noise=None, **pars): 
     202        """ 
     203        Generate simulated data for the model. 
     204        """ 
    134205        Iq = self.__call__(**pars) 
    135206        self._set_data(Iq, noise=noise) 
    136207 
    137 def demo(): 
     208def main(): 
     209    """ 
     210    Program to evaluate a particular model at a set of q values. 
     211    """ 
    138212    import sys 
    139213    from .data import empty_data1D, empty_data2D 
     
    144218    model_name = sys.argv[1] 
    145219    call = sys.argv[2].upper() 
    146     if call not in ("ER","VR"): 
     220    if call not in ("ER", "VR"): 
    147221        try: 
    148222            values = [float(v) for v in call.split(',')] 
     
    153227            data = empty_data1D([q]) 
    154228        elif len(values) == 2: 
    155             qx,qy = values 
    156             data = empty_data2D([qx],[qy]) 
     229            qx, qy = values 
     230            data = empty_data2D([qx], [qy]) 
    157231        else: 
    158232            print("use q or qx,qy or ER or VR") 
     
    164238    model = load_model(model_definition, dtype='single') 
    165239    calculator = DirectModel(data, model) 
    166     pars = dict((k,float(v)) 
     240    pars = dict((k, float(v)) 
    167241                for pair in sys.argv[3:] 
    168                 for k,v in [pair.split('=')]) 
     242                for k, v in [pair.split('=')]) 
    169243    if call == "ER": 
    170244        print(calculator.ER(**pars)) 
     
    176250 
    177251if __name__ == "__main__": 
    178     demo() 
     252    main() 
Note: See TracChangeset for help on using the changeset viewer.