Changeset 304c775 in sasmodels


Ignore:
Timestamp:
Oct 25, 2018 3:35:06 PM (6 years ago)
Author:
Paul Kienzle <pkienzle@…>
Branches:
master, core_shell_microgels, magnetic_model, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
Children:
39a06c9
Parents:
6d5601c
Message:

provide method for testing Fq results. Refs #1202.

Files:
22 edited

Legend:

Unmodified
Added
Removed
  • doc/guide/plugin.rst

    r31fc4ad r304c775  
    10331033          "radius": 120., "radius_pd": 0.2, "radius_pd_n":45}, 
    10341034         0.2, 0.228843], 
    1035         [{"radius": 120., "radius_pd": 0.2, "radius_pd_n":45}, "ER", 120.], 
    1036         [{"radius": 120., "radius_pd": 0.2, "radius_pd_n":45}, "VR", 1.], 
     1035        [{"radius": 120., "radius_pd": 0.2, "radius_pd_n":45}, 
     1036         0.1, None, None, 120., None, 1.],  # q, F, F^2, R_eff, V, form:shell 
    10371037    ] 
    10381038 
    10391039 
    1040 **tests=[[{parameters}, q, result], ...]** is a list of lists. 
     1040**tests=[[{parameters}, q, Iq], ...]** is a list of lists. 
    10411041Each list is one test and contains, in order: 
    10421042 
     
    10501050- input and output values can themselves be lists if you have several 
    10511051  $q$ values to test for the same model parameters. 
    1052 - for testing *ER* and *VR*, give the inputs as "ER" and "VR" respectively; 
    1053   the output for *VR* should be the sphere/shell ratio, not the individual 
    1054   sphere and shell values. 
     1052- for testing effective radius, volume and form:shell volume ratio, use the 
     1053  extended form of the tests results, with *None, None, R_eff, V, V_r* 
     1054  instead of *Iq*.  This calls the kernel *Fq* function instead of *Iq*. 
     1055- for testing F and F^2 (used for beta approximation) do the same as the 
     1056  effective radius test, but include values for the first two elements, 
     1057  $<F(q)>$ and $<F^2(q)>$. 
    10551058 
    10561059.. _Test_Your_New_Model: 
  • sasmodels/direct_model.py

    r7b9e4dd r304c775  
    6464    return calculator(call_details, values, cutoff, is_magnetic) 
    6565 
    66 def call_ER(model_info, pars): 
    67     # type: (ModelInfo, ParameterSet) -> float 
    68     """ 
    69     Call the model ER function using *values*. 
    70  
    71     *model_info* is either *model.info* if you have a loaded model, 
    72     or *kernel.info* if you have a model kernel prepared for evaluation. 
    73     """ 
    74     if model_info.ER is None: 
    75         return 1.0 
    76     elif not model_info.parameters.form_volume_parameters: 
    77         # handle the case where ER is provided but model is not polydisperse 
    78         return model_info.ER() 
    79     else: 
    80         value, weight = _vol_pars(model_info, pars) 
    81         individual_radii = model_info.ER(*value) 
    82         return np.sum(weight*individual_radii) / np.sum(weight) 
    83  
    84  
    85 def call_VR(model_info, pars): 
    86     # type: (ModelInfo, ParameterSet) -> float 
    87     """ 
    88     Call the model VR function using *pars*. 
    89  
    90     *model_info* is either *model.info* if you have a loaded model, 
    91     or *kernel.info* if you have a model kernel prepared for evaluation. 
    92     """ 
    93     if model_info.VR is None: 
    94         return 1.0 
    95     elif not model_info.parameters.form_volume_parameters: 
    96         # handle the case where ER is provided but model is not polydisperse 
    97         return model_info.VR() 
    98     else: 
    99         value, weight = _vol_pars(model_info, pars) 
    100         whole, part = model_info.VR(*value) 
    101         return np.sum(weight*part)/np.sum(weight*whole) 
    102  
     66def call_Fq(calculator, pars, cutoff=0., mono=False): 
     67    # type: (Kernel, ParameterSet, float, bool) -> np.ndarray 
     68    """ 
     69    Like :func:`call_kernel`, but returning F, F^2, R_eff, V, V_form/V_shell. 
     70    """ 
     71    R_eff_type = int(pars.pop('radius_effective_type', 1.0)) 
     72    mesh = get_mesh(calculator.info, pars, dim=calculator.dim, mono=mono) 
     73    #print("pars", list(zip(*mesh))[0]) 
     74    call_details, values, is_magnetic = make_kernel_args(calculator, mesh) 
     75    #print("values:", values) 
     76    return calculator.Fq(call_details, values, cutoff, is_magnetic, R_eff_type) 
    10377 
    10478def call_profile(model_info, **pars): 
     
    419393    model_name = sys.argv[1] 
    420394    call = sys.argv[2].upper() 
    421     if call != "ER_VR": 
    422         try: 
    423             values = [float(v) for v in call.split(',')] 
    424         except ValueError: 
    425             values = [] 
    426         if len(values) == 1: 
    427             q, = values 
    428             data = empty_data1D([q]) 
    429         elif len(values) == 2: 
    430             qx, qy = values 
    431             data = empty_data2D([qx], [qy]) 
    432         else: 
    433             print("use q or qx,qy or ER or VR") 
    434             sys.exit(1) 
     395    try: 
     396        values = [float(v) for v in call.split(',')] 
     397    except ValueError: 
     398        values = [] 
     399    if len(values) == 1: 
     400        q, = values 
     401        data = empty_data1D([q]) 
     402    elif len(values) == 2: 
     403        qx, qy = values 
     404        data = empty_data2D([qx], [qy]) 
    435405    else: 
    436         data = empty_data1D([0.001])  # Data not used in ER/VR 
     406        print("use q or qx,qy") 
     407        sys.exit(1) 
    437408 
    438409    model_info = load_model_info(model_name) 
     
    442413                for pair in sys.argv[3:] 
    443414                for k, v in [pair.split('=')]) 
    444     if call == "ER_VR": 
    445         ER = call_ER(model_info, pars) 
    446         VR = call_VR(model_info, pars) 
    447         print(ER, VR) 
    448     else: 
    449         Iq = calculator(**pars) 
    450         print(Iq[0]) 
     415    Iq = calculator(**pars) 
     416    print(Iq[0]) 
    451417 
    452418if __name__ == "__main__": 
  • sasmodels/model_test.py

    r74e9b5f r304c775  
    5959from . import core 
    6060from .core import list_models, load_model_info, build_model 
    61 from .direct_model import call_kernel, call_ER, call_VR 
     61from .direct_model import call_kernel, call_Fq 
    6262from .exception import annotate_exception 
    6363from .modelinfo import expand_pars 
     
    215215                ({}, [(0.1, 0.1)]*2, [None]*2), 
    216216                # test that ER/VR will run if they exist 
    217                 ({}, 'ER', None), 
    218                 ({}, 'VR', None), 
     217                ({}, 0.1, None, None, None, None, None), 
    219218                ] 
    220219            tests = smoke_tests 
     
    288287            # type: (KernelModel, TestCondition) -> None 
    289288            """Run a single test case.""" 
    290             user_pars, x, y = test 
     289            user_pars, x, y = test[:3] 
    291290            pars = expand_pars(self.info.parameters, user_pars) 
    292291            invalid = invalid_pars(self.info.parameters, pars) 
     
    301300            self.assertEqual(len(y), len(x)) 
    302301 
    303             if x[0] == 'ER': 
    304                 actual = np.array([call_ER(model.info, pars)]) 
    305             elif x[0] == 'VR': 
    306                 actual = np.array([call_VR(model.info, pars)]) 
    307             elif isinstance(x[0], tuple): 
     302            if isinstance(x[0], tuple): 
    308303                qx, qy = zip(*x) 
    309304                q_vectors = [np.array(qx), np.array(qy)] 
    310                 kernel = model.make_kernel(q_vectors) 
    311                 actual = call_kernel(kernel, pars) 
    312305            else: 
    313306                q_vectors = [np.array(x)] 
    314                 kernel = model.make_kernel(q_vectors) 
     307 
     308            kernel = model.make_kernel(q_vectors) 
     309            if len(test) == 3: 
    315310                actual = call_kernel(kernel, pars) 
    316  
    317             self.assertTrue(len(actual) > 0) 
    318             self.assertEqual(len(y), len(actual)) 
    319  
    320             for xi, yi, actual_yi in zip(x, y, actual): 
     311                self._check_vectors(x, y, actual, 'I') 
     312                return actual 
     313            else: 
     314                y1 = y 
     315                y2 = test[3] if not isinstance(test[3], list) else [test[3]] 
     316                F1, F2, R_eff, volume, volume_ratio = call_Fq(kernel, pars) 
     317                if F1 is not None:  # F1 is none for models with Iq instead of Fq 
     318                    self._check_vectors(x, y1, F1, 'F') 
     319                self._check_vectors(x, y2, F2, 'F^2') 
     320                self._check_scalar(test[4], R_eff, 'R_eff') 
     321                self._check_scalar(test[5], volume, 'volume') 
     322                self._check_scalar(test[6], volume_ratio, 'form:shell ratio') 
     323                return F2 
     324 
     325        def _check_scalar(self, target, actual, name): 
     326            if target is None: 
     327                # smoke test --- make sure it runs and produces a value 
     328                self.assertTrue(not np.isnan(actual), 
     329                                'invalid %s: %s' % (name, actual)) 
     330            elif np.isnan(target): 
     331                # make sure nans match 
     332                self.assertTrue(np.isnan(actual), 
     333                                '%s: expected:%s; actual:%s' 
     334                                % (name, target, actual)) 
     335            else: 
     336                # is_near does not work for infinite values, so also test 
     337                # for exact values. 
     338                self.assertTrue(target == actual or is_near(target, actual, 5), 
     339                                '%s: expected:%s; actual:%s' 
     340                                % (name, target, actual)) 
     341 
     342        def _check_vectors(self, x, target, actual, name='I'): 
     343            self.assertTrue(len(actual) > 0, 
     344                            '%s(...) expected return'%name) 
     345            if target is None: 
     346                return 
     347            self.assertEqual(len(target), len(actual), 
     348                             '%s(...) returned wrong length'%name) 
     349            for xi, yi, actual_yi in zip(x, target, actual): 
    321350                if yi is None: 
    322351                    # smoke test --- make sure it runs and produces a value 
    323352                    self.assertTrue(not np.isnan(actual_yi), 
    324                                     'invalid f(%s): %s' % (xi, actual_yi)) 
     353                                    'invalid %s(%s): %s' % (name, xi, actual_yi)) 
    325354                elif np.isnan(yi): 
     355                    # make sure nans match 
    326356                    self.assertTrue(np.isnan(actual_yi), 
    327                                     'f(%s): expected:%s; actual:%s' 
    328                                     % (xi, yi, actual_yi)) 
     357                                    '%s(%s): expected:%s; actual:%s' 
     358                                    % (name, xi, yi, actual_yi)) 
    329359                else: 
    330360                    # is_near does not work for infinite values, so also test 
    331                     # for exact values.  Note that this will not 
     361                    # for exact values. 
    332362                    self.assertTrue(yi == actual_yi or is_near(yi, actual_yi, 5), 
    333                                     'f(%s); expected:%s; actual:%s' 
    334                                     % (xi, yi, actual_yi)) 
    335             return actual 
     363                                    '%s(%s); expected:%s; actual:%s' 
     364                                    % (name, xi, yi, actual_yi)) 
    336365 
    337366    return ModelTestCase 
     
    345374    invalid = [] 
    346375    for par in sorted(pars.keys()): 
     376        # special handling of R_eff mode, which is not a usual parameter 
     377        if par == 'radius_effective_type': 
     378            continue 
    347379        parts = par.split('_pd') 
    348380        if len(parts) > 1 and parts[1] not in ("", "_n", "nsigma", "type"): 
  • sasmodels/models/_spherepy.py

    rca4444f r304c775  
    7171    return 1.333333333333333 * pi * radius ** 3 
    7272 
     73def effective_radius(mode, radius): 
     74    return radius 
     75 
    7376def Iq(q, sld, sld_solvent, radius): 
    7477    #print "q",q 
     
    105108sesans.vectorized = True  # sesans accepts an array of z values 
    106109 
    107 def ER(radius): 
    108     return radius 
    109  
    110 # VR defaults to 1.0 
    111  
    112110demo = dict(scale=1, background=0, 
    113111            sld=6, sld_solvent=1, 
  • sasmodels/models/core_shell_bicelle_elliptical.py

    ree60aa7 r304c775  
    184184 
    185185tests = [ 
    186     [{'radius': 30.0, 'x_core': 3.0, 
    187       'thick_rim': 8.0, 'thick_face': 14.0, 'length': 50.0}, 'ER', 1], 
    188     [{'radius': 30.0, 'x_core': 3.0, 
    189       'thick_rim': 8.0, 'thick_face': 14.0, 'length': 50.0}, 'VR', 1], 
     186    #[{'radius': 30.0, 'x_core': 3.0, 
     187    #  'thick_rim': 8.0, 'thick_face': 14.0, 'length': 50.0}, 'ER', 1], 
     188    #[{'radius': 30.0, 'x_core': 3.0, 
     189    #  'thick_rim': 8.0, 'thick_face': 14.0, 'length': 50.0}, 'VR', 1], 
    190190 
    191191    [{'radius': 30.0, 'x_core': 3.0, 
  • sasmodels/models/core_shell_bicelle_elliptical_belt_rough.py

    ree60aa7 r304c775  
    186186 
    187187tests = [ 
    188     [{'radius': 30.0, 'x_core': 3.0, 'thick_rim':8.0, 'thick_face':14.0, 'length':50.0}, 'ER', 1], 
    189     [{'radius': 30.0, 'x_core': 3.0, 'thick_rim':8.0, 'thick_face':14.0, 'length':50.0}, 'VR', 1], 
     188    #[{'radius': 30.0, 'x_core': 3.0, 'thick_rim':8.0, 'thick_face':14.0, 'length':50.0}, 'ER', 1], 
     189    #[{'radius': 30.0, 'x_core': 3.0, 'thick_rim':8.0, 'thick_face':14.0, 'length':50.0}, 'VR', 1], 
    190190 
    191191    [{'radius': 30.0, 'x_core': 3.0, 'thick_rim':8.0, 'thick_face':14.0, 'length':50.0, 
  • sasmodels/models/core_shell_sphere.py

    ree60aa7 r304c775  
    9696 
    9797tests = [ 
    98 #    [{'radius': 20.0, 'thickness': 10.0}, 'ER', 30.0], 
     98    [{'radius': 20.0, 'thickness': 10.0}, 0.1, None, None, 30.0, 4.*pi/3*30**3, 1.0], 
    9999 
    100100    # The SasView test result was 0.00169, with a background of 0.001 
  • sasmodels/models/cylinder.py

    ree60aa7 r304c775  
    167167            phi_pd=10, phi_pd_n=5) 
    168168 
     169# pylint: disable=bad-whitespace, line-too-long 
    169170qx, qy = 0.2 * np.cos(2.5), 0.2 * np.sin(2.5) 
    170171# After redefinition of angles, find new tests values.  Was 10 10 in old coords 
     
    180181] 
    181182del qx, qy  # not necessary to delete, but cleaner 
     183 
     184# Default radius and length 
     185radius, length = parameters[2][2], parameters[3][2] 
     186tests.extend([ 
     187    ({'radius_effective_type': 0}, 0.1, None, None, 0., pi*radius**2*length, 1.0), 
     188    ({'radius_effective_type': 1}, 0.1, None, None, (0.75*radius**2*length)**(1./3.), None, None), 
     189    ({'radius_effective_type': 2}, 0.1, None, None, radius, None, None), 
     190    ({'radius_effective_type': 3}, 0.1, None, None, length/2., None, None), 
     191    ({'radius_effective_type': 4}, 0.1, None, None, min(radius, length/2.), None, None), 
     192    ({'radius_effective_type': 5}, 0.1, None, None, max(radius, length/2.), None, None), 
     193    ({'radius_effective_type': 6}, 0.1, None, None, np.sqrt(4*radius**2 + length**2)/2., None, None), 
     194]) 
     195del radius, length 
     196# pylint: enable=bad-whitespace, line-too-long 
     197 
    182198# ADDED by:  RKH  ON: 18Mar2016 renamed sld's etc 
  • sasmodels/models/dab.py

    r2d81cfe r304c775  
    7474    return pars 
    7575 
    76 # ER defaults to 1.0 
    77  
    78 # VR defaults to 1.0 
    79  
    8076demo = dict(scale=1, background=0, cor_length=50) 
  • sasmodels/models/gaussian_peak.py

    r2d81cfe r304c775  
    5050    """ 
    5151 
    52 # VR defaults to 1.0 
    53  
    5452def random(): 
    5553    peak_pos = 10**np.random.uniform(-3, -1) 
  • sasmodels/models/hardsphere.py

    r71b751d r304c775  
    162162    return pars 
    163163 
    164 # ER defaults to 0.0 
    165 # VR defaults to 1.0 
    166  
    167164demo = dict(radius_effective=200, volfraction=0.2, 
    168165            radius_effective_pd=0.1, radius_effective_pd_n=40) 
  • sasmodels/models/hayter_msa.py

    r2d81cfe r304c775  
    8989    return 1.0; 
    9090    """ 
    91 # ER defaults to 0.0 
    92 # VR defaults to 1.0 
    9391 
    9492def random(): 
  • sasmodels/models/hollow_cylinder.py

    ree60aa7 r304c775  
    6969* **Last Reviewed by:** Paul Butler **Date:** September 06, 2018 
    7070""" 
     71from __future__ import division 
    7172 
    7273import numpy as np 
     
    132133qx = q*cos(pi/6.0) 
    133134qy = q*sin(pi/6.0) 
     135radius = parameters[0][2] 
     136thickness = parameters[1][2] 
     137length = parameters[2][2] 
    134138# Parameters for unit tests 
    135139tests = [ 
    136140    [{}, 0.00005, 1764.926], 
    137 #    [{}, 'VR', 0.55555556], 
     141    [{}, 0.1, None, None, 
     142     (3./4*(radius+thickness)**2*length)**(1./3),  # R_eff from volume 
     143     pi*((radius+thickness)**2-radius**2)*length,  # shell volume 
     144     (radius+thickness)**2/((radius+thickness)**2 - radius**2), # form:shell ratio 
     145    ], 
    138146    [{}, 0.001, 1756.76], 
    139147    [{}, (qx, qy), 2.36885476192], 
  • sasmodels/models/lamellar.py

    r2d81cfe r304c775  
    9595    return pars 
    9696 
    97 # ER defaults to 0.0 
    98 # VR defaults to 1.0 
    99  
    10097demo = dict(scale=1, background=0, 
    10198            sld=6, sld_solvent=1, 
  • sasmodels/models/lamellar_hg.py

    r2d81cfe r304c775  
    109109    return pars 
    110110 
    111 # ER defaults to 0.0 
    112 # VR defaults to 1.0 
    113  
    114111demo = dict(scale=1, background=0, 
    115112            length_tail=15, length_head=10, 
  • sasmodels/models/lamellar_hg_stack_caille.py

    r2d81cfe r304c775  
    122122    """ 
    123123 
    124 # ER defaults to 0.0 
    125 # VR defaults to 1.0 
    126  
    127124def random(): 
    128125    total_thickness = 10**np.random.uniform(2, 4.7) 
  • sasmodels/models/lamellar_stack_caille.py

    r2d81cfe r304c775  
    120120    """ 
    121121 
    122 # ER defaults to 0.0 
    123 # VR defaults to 1.0 
    124  
    125122demo = dict(scale=1, background=0, 
    126123            thickness=67., Nlayers=3.75, d_spacing=200., 
  • sasmodels/models/lamellar_stack_paracrystal.py

    r2d81cfe r304c775  
    147147    return pars 
    148148 
    149 # ER defaults to 0.0 
    150 # VR defaults to 1.0 
    151  
    152149demo = dict(scale=1, background=0, 
    153150            thickness=33, Nlayers=20, d_spacing=250, sigma_d=0.2, 
  • sasmodels/models/sphere.py

    ree60aa7 r304c775  
    8383      "radius": 120., "radius_pd": 0.2, "radius_pd_n":45}, 
    8484     0.2, 0.228843], 
    85 #    [{"radius": 120., "radius_pd": 0.2, "radius_pd_n":45}, "ER", 120.], 
    86 #    [{"radius": 120., "radius_pd": 0.2, "radius_pd_n":45}, "VR", 1.], 
     85    [{"radius": 120., "radius_pd": 0.2, "radius_pd_n":45}, 
     86     0.1, None, None, 120., None, 1.0], 
    8787] 
  • sasmodels/models/squarewell.py

    r2d81cfe r304c775  
    130130""" 
    131131 
    132 # ER defaults to 0.0 
    133 # VR defaults to 1.0 
    134  
    135132def random(): 
    136133    pars = dict( 
  • sasmodels/models/stickyhardsphere.py

    r2d81cfe r304c775  
    182182""" 
    183183 
    184 # ER defaults to 0.0 
    185 # VR defaults to 1.0 
    186  
    187184demo = dict(radius_effective=200, volfraction=0.2, perturb=0.05, 
    188185            stickiness=0.2, radius_effective_pd=0.1, radius_effective_pd_n=40) 
  • sasmodels/models/vesicle.py

    ree60aa7 r304c775  
    128128         [{}, 0.100600200401, 1.77063682331], 
    129129         [{}, 0.5, 0.00355351388906], 
    130 #         [{}, 'ER', 130.], 
    131 #         [{}, 'VR', 0.54483386436], 
     130         [{}, 0.1, None, None, 130., None, 1./0.54483386436],  # R_eff, form:shell 
    132131        ] 
Note: See TracChangeset for help on using the changeset viewer.