Changeset c9e31e2 in sasmodels for sasmodels/kernelpy.py


Ignore:
Timestamp:
Mar 6, 2015 10:54:22 AM (9 years ago)
Author:
richardh
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:
9f6f2f8, ab87a12
Parents:
d60b433 (diff), 3c56da87 (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.
Message:

Merge branch 'master' of https://github.com/SasView/sasmodels

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sasmodels/kernelpy.py

    r6edb74a r3c56da87  
    11import numpy as np 
    2 from numpy import pi, sin, cos, sqrt 
    3  
    4 from .generate import F32, F64 
     2from numpy import pi, cos 
     3 
     4from .generate import F64 
     5 
     6class PyModel(object): 
     7    def __init__(self, info): 
     8        self.info = info 
     9 
     10    def __call__(self, q_input): 
     11        kernel = self.info['Iqxy'] if q_input.is_2D else self.info['Iq'] 
     12        return PyKernel(kernel, self.info, q_input) 
     13 
     14    # pylint: disable=no-self-use 
     15    def make_input(self, q_vectors): 
     16        return PyInput(q_vectors, dtype=F64) 
     17 
     18    def release(self): 
     19        pass 
    520 
    621class PyInput(object): 
     
    2742        self.dtype = dtype 
    2843        self.is_2D = (len(q_vectors) == 2) 
    29         self.q_vectors = [np.ascontiguousarray(q,self.dtype) for q in q_vectors] 
     44        self.q_vectors = [np.ascontiguousarray(q, self.dtype) for q in q_vectors] 
    3045        self.q_pointers = [q.ctypes.data for q in q_vectors] 
    3146 
     
    4156    *info* is the module information 
    4257 
    43     *input* is the DllInput q vectors at which the kernel should be 
     58    *q_input* is the DllInput q vectors at which the kernel should be 
    4459    evaluated. 
    4560 
     
    5267    Call :meth:`release` when done with the kernel instance. 
    5368    """ 
    54     def __init__(self, kernel, info, input): 
     69    def __init__(self, kernel, info, q_input): 
    5570        self.info = info 
    56         self.input = input 
    57         self.res = np.empty(input.nq, input.dtype) 
    58         dim = '2d' if input.is_2D else '1d' 
     71        self.q_input = q_input 
     72        self.res = np.empty(q_input.nq, q_input.dtype) 
     73        dim = '2d' if q_input.is_2D else '1d' 
    5974        # Loop over q unless user promises that the kernel is vectorized by 
    6075        # taggining it with vectorized=True 
     
    6277            if dim == '2d': 
    6378                def vector_kernel(qx, qy, *args): 
    64                     return np.array([kernel(qxi,qyi,*args) for qxi,qyi in zip(qx,qy)]) 
     79                    return np.array([kernel(qxi, qyi, *args) 
     80                                     for qxi, qyi in zip(qx, qy)]) 
    6581            else: 
    6682                def vector_kernel(q, *args): 
    67                     return np.array([kernel(qi,*args) for qi in q]) 
     83                    return np.array([kernel(qi, *args) 
     84                                     for qi in q]) 
    6885            self.kernel = vector_kernel 
    6986        else: 
    7087            self.kernel = kernel 
    71         fixed_pars = info['partype']['fixed-'+dim] 
    72         pd_pars = info['partype']['pd-'+dim] 
     88        fixed_pars = info['partype']['fixed-' + dim] 
     89        pd_pars = info['partype']['pd-' + dim] 
    7390        vol_pars = info['partype']['volume'] 
    7491 
    7592        # First two fixed pars are scale and background 
    7693        pars = [p[0] for p in info['parameters'][2:]] 
    77         offset = len(self.input.q_vectors) 
    78         self.args = self.input.q_vectors + [None]*len(pars) 
    79         self.fixed_index = np.array([pars.index(p)+offset for p in fixed_pars[2:] ]) 
    80         self.pd_index = np.array([pars.index(p)+offset for p in pd_pars]) 
    81         self.vol_index = np.array([pars.index(p)+offset for p in vol_pars]) 
    82         try: self.theta_index = pars.index('theta')+offset 
     94        offset = len(self.q_input.q_vectors) 
     95        self.args = self.q_input.q_vectors + [None] * len(pars) 
     96        self.fixed_index = np.array([pars.index(p) + offset 
     97                                     for p in fixed_pars[2:]]) 
     98        self.pd_index = np.array([pars.index(p) + offset 
     99                                  for p in pd_pars]) 
     100        self.vol_index = np.array([pars.index(p) + offset 
     101                                   for p in vol_pars]) 
     102        try: self.theta_index = pars.index('theta') + offset 
    83103        except ValueError: self.theta_index = -1 
    84104 
     
    94114        # First two fixed 
    95115        scale, background = fixed[:2] 
    96         for index,value in zip(self.fixed_index, fixed[2:]): 
     116        for index, value in zip(self.fixed_index, fixed[2:]): 
    97117            args[index] = float(value) 
    98         res = _loops(form, form_volume, cutoff, scale, background,  args, 
     118        res = _loops(form, form_volume, cutoff, scale, background, args, 
    99119                     pd, self.pd_index, self.vol_index, self.theta_index) 
    100120 
     
    102122 
    103123    def release(self): 
    104         self.input = None 
     124        self.q_input = None 
    105125 
    106126def _loops(form, form_volume, cutoff, scale, background, 
     
    134154    """ 
    135155 
    136     ########################################################## 
    137     #                                                        # 
    138     #   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!   # 
    139     #   !!                                              !!   # 
    140     #   !!  KEEP THIS CODE CONSISTENT WITH GENERATE.PY  !!   # 
    141     #   !!                                              !!   # 
    142     #   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!   # 
    143     #                                                        # 
    144     ########################################################## 
     156    ################################################################ 
     157    #                                                              # 
     158    #   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!   # 
     159    #   !!                                                    !!   # 
     160    #   !!  KEEP THIS CODE CONSISTENT WITH KERNEL_TEMPLATE.C  !!   # 
     161    #   !!                                                    !!   # 
     162    #   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!   # 
     163    #                                                              # 
     164    ################################################################ 
    145165 
    146166    weight = np.empty(len(pd), 'd') 
     
    164184        stride = np.array([1]) 
    165185        vol_weight_index = slice(None, None) 
     186        # keep lint happy 
     187        fast_value = [None] 
     188        fast_weight = [None] 
    166189 
    167190    ret = np.zeros_like(args[0]) 
     
    171194    for k in range(stride[-1]): 
    172195        # update polydispersity parameter values 
    173         fast_index = k%stride[0] 
     196        fast_index = k % stride[0] 
    174197        if fast_index == 0:  # bottom loop complete ... check all other loops 
    175198            if weight.size > 0: 
    176                 for i,index, in enumerate(k%stride): 
     199                for i, index, in enumerate(k % stride): 
    177200                    args[pd_index[i]] = pd[i][0][index] 
    178201                    weight[i] = pd[i][1][index] 
     
    180203            args[pd_index[0]] = fast_value[fast_index] 
    181204            weight[0] = fast_weight[fast_index] 
    182         # This computes the weight, and if it is sufficient, calls the scattering 
    183         # function and adds it to the total.  If there is a volume normalization, 
    184         # it will also be added here. 
     205        # This computes the weight, and if it is sufficient, calls the 
     206        # scattering function and adds it to the total.  If there is a volume 
     207        # normalization, it will also be added here. 
    185208        # Note: make sure this is consistent with the code in PY_LOOP_BODY!! 
    186209        # Note: can precompute w1*w2*...*wn 
     
    188211        if w > cutoff: 
    189212            I = form(*args) 
    190             positive = (I>=0.0) 
    191  
    192             # Note: can precompute spherical correction if theta_index is not the fast index 
    193             # Correction factor for spherical integration p(theta) I(q) sin(theta) dtheta 
    194             #spherical_correction = abs(sin(pi*args[theta_index])) if theta_index>=0 else 1.0 
    195             #spherical_correction = abs(cos(pi*args[theta_index]))*pi/2 if theta_index>=0 else 1.0 
    196             spherical_correction = 1.0 
    197             ret += w*I*spherical_correction*positive 
    198             norm += w*positive 
     213            positive = (I >= 0.0) 
     214 
     215            # Note: can precompute spherical correction if theta_index is not 
     216            # the fast index. Correction factor for spherical integration 
     217            #spherical_correction = abs(cos(pi*args[phi_index])) if phi_index>=0 else 1.0 
     218            spherical_correction = (abs(cos(pi * args[theta_index])) * pi / 2 
     219                                    if theta_index >= 0 else 1.0) 
     220            #spherical_correction = 1.0 
     221            ret += w * I * spherical_correction * positive 
     222            norm += w * positive 
    199223 
    200224            # Volume normalization. 
    201             # If there are "volume" polydispersity parameters, then these will be used 
    202             # to call the form_volume function from the user supplied kernel, and accumulate 
    203             # a normalized weight. 
    204             # Note: can precompute volume norm if the fast index is not a volume index 
     225            # If there are "volume" polydispersity parameters, then these 
     226            # will be used to call the form_volume function from the user 
     227            # supplied kernel, and accumulate a normalized weight. 
     228            # Note: can precompute volume norm if fast index is not a volume 
    205229            if form_volume: 
    206230                vol_args = [args[index] for index in vol_index] 
    207231                vol_weight = np.prod(weight[vol_weight_index]) 
    208                 vol += vol_weight*form_volume(*vol_args)*positive 
    209                 vol_norm += vol_weight*positive 
    210  
    211     positive = (vol*vol_norm != 0.0) 
     232                vol += vol_weight * form_volume(*vol_args) * positive 
     233                vol_norm += vol_weight * positive 
     234 
     235    positive = (vol * vol_norm != 0.0) 
    212236    ret[positive] *= vol_norm[positive] / vol[positive] 
    213     result = scale*ret/norm+background 
     237    result = scale * ret / norm + background 
    214238    return result 
Note: See TracChangeset for help on using the changeset viewer.