source: sasmodels/sasmodels/convert.py @ 17bbadd

core_shell_microgelscostrafo411magnetic_modelrelease_v0.94release_v0.95ticket-1257-vesicle-productticket_1156ticket_1265_superballticket_822_more_unit_tests
Last change on this file since 17bbadd was 17bbadd, checked in by Paul Kienzle <pkienzle@…>, 8 years ago

refactor so all model defintion queries use model_info; better documentation of model_info structure; initial implementation of product model (broken)

  • Property mode set to 100644
File size: 5.9 KB
Line 
1"""
2Convert models to and from sasview.
3"""
4import warnings
5
6STRUCTURE_FACTORS = [
7    'hardsphere',
8    'stickyhardsphere',
9    'squarewell',
10    'HayterMSAsq'
11]
12# List of models which SasView versions don't contain the explicit 'scale' argument.
13# When converting such a model, please update this list.
14MODELS_WITHOUT_SCALE = STRUCTURE_FACTORS + [
15    'teubner_strey',
16    'broad_peak',
17    'two_lorentzian',
18    "two_power_law",
19    'gel_fit',
20    'gauss_lorentz_gel',
21    'be_polyelectrolyte',
22    'correlation_length',
23    'fractal_core_shell'
24    'binary_hard_sphere',
25]
26
27# List of models which SasView versions don't contain the explicit 'background' argument.
28# When converting such a model, please update this list.
29MODELS_WITHOUT_BACKGROUND = STRUCTURE_FACTORS + [
30    'guinier',
31]
32
33PD_DOT = [
34    ("", ""),
35    ("_pd", ".width"),
36    ("_pd_n", ".npts"),
37    ("_pd_nsigma", ".nsigmas"),
38    ("_pd_type", ".type"),
39    ]
40def _convert_pars(pars, mapping):
41    """
42    Rename the parameters and any associated polydispersity attributes.
43    """
44    newpars = pars.copy()
45    for new, old in mapping.items():
46        if old == new: continue
47        for pd, dot in PD_DOT:
48            if old+dot in newpars:
49                if new is not None:
50                    newpars[new+pd] = pars[old+dot]
51                del newpars[old+dot]
52    return newpars
53
54def _rescale_sld(pars):
55    """
56    rescale all sld parameters in the new model definition by 1e6 so the
57    numbers are nicer.  Relies on the fact that all sld parameters in the
58    new model definition end with sld.
59    """
60    return dict((p, (v*1e6 if p.endswith('sld')
61                     else v*1e-15 if 'ndensity' in p
62                     else v))
63                for p, v in pars.items())
64
65def convert_model(name, pars):
66    """
67    Convert model from old style parameter names to new style.
68    """
69    _, _ = name, pars # lint
70    raise NotImplementedError
71    # need to load all new models in order to determine old=>new
72    # model name mapping
73
74def _unscale_sld(pars):
75    """
76    rescale all sld parameters in the new model definition by 1e6 so the
77    numbers are nicer.  Relies on the fact that all sld parameters in the
78    new model definition end with sld.
79    """
80    return dict((p, (v*1e-6 if p.endswith('sld')
81                     else v*1e15 if 'ndensity' in p
82                     else v))
83                for p, v in pars.items())
84
85def _remove_pd(pars, key, name):
86    """
87    Remove polydispersity from the parameter list.
88
89    Note: operates in place
90    """
91    # Bumps style parameter names
92    pd = pars.pop(key+".width", 0.0)
93    pd_n = pars.pop(key+".npts", 0)
94    if pd != 0.0 and pd_n != 0:
95        warnings.warn("parameter %s not polydisperse in sasview %s"%(key, name))
96    pars.pop(key+".nsigmas", None)
97    pars.pop(key+".type", None)
98    return pars
99
100def _revert_pars(pars, mapping):
101    """
102    Rename the parameters and any associated polydispersity attributes.
103    """
104    newpars = pars.copy()
105
106    for new, old in mapping.items():
107        for pd, dot in PD_DOT:
108            if old and old+pd == new+dot:
109                continue
110            if new+pd in newpars:
111                if old is not None:
112                    newpars[old+dot] = pars[new+pd]
113                del newpars[new+pd]
114    for k in list(newpars.keys()):
115        for pd, dot in PD_DOT[1:]:  # skip "" => ""
116            if k.endswith(pd):
117                newpars[k[:-len(pd)]+dot] = newpars[k]
118                del newpars[k]
119    return newpars
120
121def revert_pars(model_info, pars):
122    """
123    Convert model from new style parameter names to old style.
124    """
125    mapping = model_info['oldpars']
126    oldpars = _revert_pars(_unscale_sld(pars), mapping)
127
128    # Note: update compare.constrain_pars to match
129    name = model_info['id']
130    if name in MODELS_WITHOUT_SCALE:
131        if oldpars.pop('scale', 1.0) != 1.0:
132            warnings.warn("parameter scale not used in sasview %s"%name)
133    if name in MODELS_WITHOUT_BACKGROUND:
134        if oldpars.pop('background', 0.0) != 0.0:
135            warnings.warn("parameter background not used in sasview %s"%name)
136
137    # If it is a product model P*S, then check the individual forms for special
138    # cases.  Note: despite the structure factor alone not having scale or
139    # background, the product model does, so this is below the test for
140    # models without scale or background.
141    namelist = name.split('*') if '*' in name else [name]
142    for name in namelist:
143        if name == 'pearl_necklace':
144            _remove_pd(oldpars, 'num_pearls', name)
145            _remove_pd(oldpars, 'thick_string', name)
146        elif name == 'core_shell_parallelepiped':
147            _remove_pd(oldpars, 'rimA', name)
148            _remove_pd(oldpars, 'rimB', name)
149            _remove_pd(oldpars, 'rimC', name)
150        elif name == 'rpa':
151            # convert scattering lengths from femtometers to centimeters
152            for p in "La", "Lb", "Lc", "Ld":
153                if p in oldpars: oldpars[p] *= 1e-13
154
155    return oldpars
156
157def constrain_new_to_old(model_info, pars):
158    """
159    Restrict parameter values to those that will match sasview.
160    """
161    name = model_info['id']
162    # Note: update convert.revert_model to match
163    if name in MODELS_WITHOUT_SCALE:
164        pars['scale'] = 1
165    if name in MODELS_WITHOUT_BACKGROUND:
166        pars['background'] = 0
167
168    # If it is a product model P*S, then check the individual forms for special
169    # cases.  Note: despite the structure factor alone not having scale or
170    # background, the product model does, so this is below the test for
171    # models without scale or background.
172    namelist = name.split('*') if '*' in name else [name]
173    for name in namelist:
174        if name == 'pearl_necklace':
175            pars['string_thickness_pd_n'] = 0
176            pars['number_of_pearls_pd_n'] = 0
177        elif name == 'line':
178            pars['scale'] = 1
179            pars['background'] = 0
180        elif name == 'rpa':
181            pars['case_num'] = int(pars['case_num'])
Note: See TracBrowser for help on using the repository browser.