Changeset 4d76711 in sasmodels


Ignore:
Timestamp:
Apr 5, 2016 10:33:44 AM (9 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:
3a45c2c, c4e7a5f
Parents:
cd0a808
Message:

adjust interface to sasview

Location:
sasmodels
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • sasmodels/core.py

    rb7172bb r4d76711  
    77    ] 
    88 
    9  
    109from os.path import basename, dirname, join as joinpath, splitext 
    1110from glob import glob 
    12 import imp 
    1311 
    1412import numpy as np 
     
    4038            return [np.asarray(v) for v in args] 
    4139 
     40# TODO: refactor composite model support 
     41# The current load_model_info/build_model does not reuse existing model 
     42# definitions when loading a composite model, instead reloading and 
     43# rebuilding the kernel for each component model in the expression.  This 
     44# is fine in a scripting environment where the model is built when the script 
     45# starts and is thrown away when the script ends, but may not be the best 
     46# solution in a long-lived application.  This affects the following functions: 
     47# 
     48#    load_model 
     49#    load_model_info 
     50#    build_model 
    4251 
    4352def list_models(): 
     
    6473    return build_model(load_model_info(model_name), **kw) 
    6574 
    66 def load_model_info_from_path(path): 
    67     # Pull off the last .ext if it exists; there may be others 
    68     name = basename(splitext(path)[0]) 
    69  
    70     # Not cleaning name since don't need to be able to reload this 
    71     # model later 
    72     # Should probably turf the model from sys.modules after we are done... 
    73  
    74     # Placing the model in the 'sasmodels.custom' name space, even 
    75     # though it doesn't actually exist.  imp.load_source doesn't seem 
    76     # to care. 
    77     kernel_module = imp.load_source('sasmodels.custom.'+name, path) 
    78  
    79     # Now that we have the module, we can load it as usual 
    80     model_info = generate.make_model_info(kernel_module) 
    81     return model_info 
    8275 
    8376def load_model_info(model_name): 
     
    10295        return product.make_product_info(P_info, Q_info) 
    10396 
    104     #import sys; print "\n".join(sys.path) 
    105     __import__('sasmodels.models.'+model_name) 
    106     kernel_module = getattr(models, model_name, None) 
     97    kernel_module = generate.load_kernel_module(model_name) 
    10798    return generate.make_model_info(kernel_module) 
    10899 
     
    179170 
    180171 
    181 def make_kernel(model, q_vectors): 
    182     """ 
    183     Return a computation kernel from the model definition and the q input. 
    184     """ 
    185     return model(q_vectors) 
    186  
    187172def get_weights(model_info, pars, name): 
    188173    """ 
     
    220205def call_kernel(kernel, pars, cutoff=0, mono=False): 
    221206    """ 
    222     Call *kernel* returned from :func:`make_kernel` with parameters *pars*. 
     207    Call *kernel* returned from *model.make_kernel* with parameters *pars*. 
    223208 
    224209    *cutoff* is the limiting value for the product of dispersion weights used 
     
    228213    with an error of about 1%, which is usually less than the measurement 
    229214    uncertainty. 
     215 
     216    *mono* is True if polydispersity should be set to none on all parameters. 
    230217    """ 
    231218    fixed_pars = [pars.get(name, kernel.info['defaults'][name]) 
     
    259246 
    260247 
    261 def call_ER(info, pars): 
    262     """ 
    263     Call the model ER function using *pars*. 
    264     *info* is either *model.info* if you have a loaded model, or *kernel.info* 
    265     if you have a model kernel prepared for evaluation. 
    266     """ 
    267     ER = info.get('ER', None) 
     248def call_ER(model_info, values): 
     249    """ 
     250    Call the model ER function using *values*. *model_info* is either 
     251    *model.info* if you have a loaded model, or *kernel.info* if you 
     252    have a model kernel prepared for evaluation. 
     253    """ 
     254    ER = model_info.get('ER', None) 
    268255    if ER is None: 
    269256        return 1.0 
    270257    else: 
    271         vol_pars = [get_weights(info, pars, name) 
    272                     for name in info['partype']['volume']] 
     258        vol_pars = [get_weights(model_info, values, name) 
     259                    for name in model_info['partype']['volume']] 
    273260        value, weight = dispersion_mesh(vol_pars) 
    274261        individual_radii = ER(*value) 
     
    276263        return np.sum(weight*individual_radii) / np.sum(weight) 
    277264 
    278 def call_VR(info, pars): 
     265def call_VR(model_info, values): 
    279266    """ 
    280267    Call the model VR function using *pars*. 
     
    282269    if you have a model kernel prepared for evaluation. 
    283270    """ 
    284     VR = info.get('VR', None) 
     271    VR = model_info.get('VR', None) 
    285272    if VR is None: 
    286273        return 1.0 
    287274    else: 
    288         vol_pars = [get_weights(info, pars, name) 
    289                     for name in info['partype']['volume']] 
     275        vol_pars = [get_weights(model_info, values, name) 
     276                    for name in model_info['partype']['volume']] 
    290277        value, weight = dispersion_mesh(vol_pars) 
    291278        whole, part = VR(*value) 
  • sasmodels/direct_model.py

    rea75043 r4d76711  
    2525import numpy as np 
    2626 
    27 from .core import make_kernel 
    2827from .core import call_kernel, call_ER_VR 
    2928from . import sesans 
     
    173172    def _calc_theory(self, pars, cutoff=0.0): 
    174173        if self._kernel is None: 
    175             self._kernel = make_kernel(self._model, self._kernel_inputs)  # pylint: disable=attribute-dedata_type 
    176             self._kernel_mono = (make_kernel(self._model, self._kernel_mono_inputs) 
     174            self._kernel = self._model.make_kernel(self._kernel_inputs)  # pylint: disable=attribute-dedata_type 
     175            self._kernel_mono = (self._model.make_kernel(self._kernel_mono_inputs) 
    177176                                 if self._kernel_mono_inputs else None) 
    178177 
  • sasmodels/exception.py

    r823e620 r4d76711  
    22Utility to add annotations to python exceptions. 
    33""" 
     4import sys 
    45 
    56# Platform cruft: WindowsError is only defined on Windows. 
     
    1314        pass 
    1415 
    15 def annotate_exception(exc, msg): 
     16def annotate_exception(msg, exc=None): 
    1617    """ 
    1718    Add an annotation to the current exception, which can then be forwarded 
    18     to the caller using a bare "raise" statement to reraise the annotated 
    19     exception. 
     19    to the caller using a bare "raise" statement to raise the annotated 
     20    exception.  If the exception *exc* is provided, then that exception is the 
     21    one that is annotated, otherwise *sys.exc_info* is used. 
    2022 
    2123    Example:: 
     
    2426        >>> try: 
    2527        ...    print(D['hello']) 
    26         ... except Exception as exc: 
    27         ...    annotate_exception(exc, "while accessing 'D'") 
     28        ... except: 
     29        ...    annotate_exception("while accessing 'D'") 
    2830        ...    raise 
    2931        Traceback (most recent call last): 
     
    3133        KeyError: "hello while accessing 'D'" 
    3234    """ 
     35    if not exc: 
     36        exc = sys.exc_info()[1] 
     37 
    3338    # Can't extend WindowsError exceptions; instead raise a new exception. 
    3439    # TODO: try to incorporate current stack trace in the raised exception 
  • sasmodels/generate.py

    rf247314 r4d76711  
    204204from __future__ import print_function 
    205205 
    206 # TODO: identify model files which have changed since loading and reload them. 
     206#TODO: identify model files which have changed since loading and reload them. 
     207#TODO: determine which functions are useful outside of generate 
     208#__all__ = ["model_info", "make_doc", "make_source", "convert_type"] 
    207209 
    208210import sys 
     
    216218import numpy as np 
    217219 
     220from .custom import load_custom_kernel_module 
     221 
    218222PARAMETER_FIELDS = ['name', 'units', 'default', 'limits', 'type', 'description'] 
    219223Parameter = namedtuple('Parameter', PARAMETER_FIELDS) 
    220  
    221 #TODO: determine which functions are useful outside of generate 
    222 #__all__ = ["model_info", "make_doc", "make_source", "convert_type"] 
    223224 
    224225C_KERNEL_TEMPLATE_PATH = joinpath(dirname(__file__), 'kernel_template.c') 
     
    644645        model_info['demo'] = model_info['defaults'] 
    645646    model_info['has_2d'] = partype['orientation'] or partype['magnetic'] 
     647 
     648 
     649def load_kernel_module(model_name): 
     650    if model_name.endswith('.py'): 
     651        kernel_module = load_custom_kernel_module(model_name) 
     652    else: 
     653        from sasmodels import models 
     654        __import__('sasmodels.models.'+model_name) 
     655        kernel_module = getattr(models, model_name, None) 
     656    return kernel_module 
     657 
    646658 
    647659def make_model_info(kernel_module): 
     
    769781 
    770782 
    771  
    772783def demo_time(): 
    773784    """ 
     
    789800    else: 
    790801        name = sys.argv[1] 
    791         import sasmodels.models 
    792         __import__('sasmodels.models.' + name) 
    793         model = getattr(sasmodels.models, name) 
    794         model_info = make_model_info(model) 
     802        kernel_module = load_kernel_module(name) 
     803        model_info = make_model_info(kernel_module) 
    795804        source = make_source(model_info) 
    796805        print(source) 
  • sasmodels/kernelcl.py

    r8e0d974 r4d76711  
    314314        self.program = None 
    315315 
    316     def __call__(self, q_vectors): 
     316    def make_kernel(self, q_vectors): 
    317317        if self.program is None: 
    318318            compiler = environment().compile_program 
  • sasmodels/kerneldll.py

    r6ad0e87 r4d76711  
    205205        try: 
    206206            self.dll = ct.CDLL(self.dllpath) 
    207         except Exception as exc: 
    208             annotate_exception(exc, "while loading "+self.dllpath) 
     207        except: 
     208            annotate_exception("while loading "+self.dllpath) 
    209209            raise 
    210210 
     
    229229        self.dll = None 
    230230 
    231     def __call__(self, q_vectors): 
     231    def make_kernel(self, q_vectors): 
    232232        q_input = PyInput(q_vectors, self.dtype) 
    233233        if self.dll is None: self._load_dll() 
    234234        kernel = self.Iqxy if q_input.is_2d else self.Iq 
    235235        return DllKernel(kernel, self.info, q_input) 
    236      
     236 
    237237    def release(self): 
    238238        """ 
  • sasmodels/kernelpy.py

    ra84a0ca r4d76711  
    1919        self.info = model_info 
    2020 
    21     def __call__(self, q_vectors): 
     21    def make_kernel(self, q_vectors): 
    2222        q_input = PyInput(q_vectors, dtype=F64) 
    2323        kernel = self.info['Iqxy'] if q_input.is_2d else self.info['Iq'] 
  • sasmodels/model_test.py

    ra84a0ca r4d76711  
    5151 
    5252from .core import list_models, load_model_info, build_model, HAVE_OPENCL 
    53 from .core import make_kernel, call_kernel, call_ER, call_VR 
     53from .core import call_kernel, call_ER, call_VR 
    5454from .exception import annotate_exception 
    5555 
     
    166166                    pass 
    167167 
    168             except Exception as exc: 
    169                 annotate_exception(exc, self.test_name) 
     168            except: 
     169                annotate_exception(self.test_name) 
    170170                raise 
    171171 
     
    187187                Qx, Qy = zip(*x) 
    188188                q_vectors = [np.array(Qx), np.array(Qy)] 
    189                 kernel = make_kernel(model, q_vectors) 
     189                kernel = model.make_kernel(q_vectors) 
    190190                actual = call_kernel(kernel, pars) 
    191191            else: 
    192192                q_vectors = [np.array(x)] 
    193                 kernel = make_kernel(model, q_vectors) 
     193                kernel = model.make_kernel(q_vectors) 
    194194                actual = call_kernel(kernel, pars) 
    195195 
  • sasmodels/resolution.py

    r486fcf6 r4d76711  
    477477    """ 
    478478    from sasmodels import core 
    479     kernel = core.make_kernel(form, [q]) 
     479    kernel = form.make_kernel([q]) 
    480480    theory = core.call_kernel(kernel, pars) 
    481481    kernel.release() 
     
    693693    def _eval_sphere(self, pars, resolution): 
    694694        from sasmodels import core 
    695         kernel = core.make_kernel(self.model, [resolution.q_calc]) 
     695        kernel = self.model.make_kernel([resolution.q_calc]) 
    696696        theory = core.call_kernel(kernel, pars) 
    697697        result = resolution.apply(theory) 
     
    10621062    model = core.build_model(model_info) 
    10631063 
    1064     kernel = core.make_kernel(model, [resolution.q_calc]) 
     1064    kernel = model.make_kernel([resolution.q_calc]) 
    10651065    theory = core.call_kernel(kernel, pars) 
    10661066    Iq = resolution.apply(theory) 
  • sasmodels/sasview_model.py

    rf247314 r4d76711  
    1313using :func:`sasmodels.convert.convert`. 
    1414""" 
     15from __future__ import print_function 
    1516 
    1617import math 
    1718from copy import deepcopy 
    1819import collections 
     20import traceback 
     21import logging 
    1922 
    2023import numpy as np 
    2124 
    2225from . import core 
     26from . import custom 
    2327from . import generate 
    2428 
    25 def standard_models(): 
    26     return [make_class(model_name) for model_name in core.list_models()] 
    27  
    28 # TODO: rename to make_class_from_name and update sasview 
    29 def make_class(model_name): 
    30     """ 
    31     Load the sasview model defined in *kernel_module*. 
    32  
    33     Returns a class that can be used directly as a sasview model.t 
    34     """ 
    35     model_info = core.load_model_info(model_name) 
    36     return make_class_from_info(model_info) 
    37  
    38 def make_class_from_file(path): 
    39     model_info = core.load_model_info_from_path(path) 
    40     return make_class_from_info(model_info) 
    41  
    42 def make_class_from_info(model_info): 
     29def load_standard_models(): 
     30    """ 
     31    Load and return the list of predefined models. 
     32 
     33    If there is an error loading a model, then a traceback is logged and the 
     34    model is not returned. 
     35    """ 
     36    models = [] 
     37    for name in core.list_models(): 
     38        try: 
     39            models.append(_make_standard_model(name)) 
     40        except: 
     41            logging.error(traceback.format_exc()) 
     42    return models 
     43 
     44 
     45def load_custom_model(path): 
     46    """ 
     47    Load a custom model given the model path. 
     48    """ 
     49    kernel_module = custom.load_custom_kernel_module(path) 
     50    model_info = generate.make_model_info(kernel_module) 
     51    return _make_model_from_info(model_info) 
     52 
     53 
     54def _make_standard_model(name): 
     55    """ 
     56    Load the sasview model defined by *name*. 
     57 
     58    *name* can be a standard model name or a path to a custom model. 
     59 
     60    Returns a class that can be used directly as a sasview model. 
     61    """ 
     62    kernel_module = generate.load_kernel_module(name) 
     63    model_info = generate.make_model_info(kernel_module) 
     64    return _make_model_from_info(model_info) 
     65 
     66 
     67def _make_model_from_info(model_info): 
     68    """ 
     69    Convert *model_info* into a SasView model wrapper. 
     70    """ 
    4371    def __init__(self, multfactor=1): 
    4472        SasviewModel.__init__(self) 
     
    4775    return ConstructedModel 
    4876 
     77 
    4978class SasviewModel(object): 
    5079    """ 
    5180    Sasview wrapper for opencl/ctypes model. 
    5281    """ 
     82    _model_info = {} 
    5383    def __init__(self): 
    54         self._kernel = None 
     84        self._model = None 
    5585        model_info = self._model_info 
    5686 
     
    104134    def __get_state__(self): 
    105135        state = self.__dict__.copy() 
    106         model_id = self._model_info['id'] 
    107         state.pop('_kernel') 
     136        state.pop('_model') 
    108137        # May need to reload model info on set state since it has pointers 
    109138        # to python implementations of Iq, etc. 
     
    113142    def __set_state__(self, state): 
    114143        self.__dict__ = state 
    115         self._kernel = None 
     144        self._model = None 
    116145 
    117146    def __str__(self): 
     
    202231    def getDispParamList(self): 
    203232        """ 
    204         Return a list of all available parameters for the model 
     233        Return a list of polydispersity parameters for the model 
    205234        """ 
    206235        # TODO: fix test so that parameter order doesn't matter 
     
    303332        to the card for each evaluation. 
    304333        """ 
    305         if self._kernel is None: 
    306             self._kernel = core.build_model(self._model_info) 
     334        if self._model is None: 
     335            self._model = core.build_model(self._model_info) 
    307336        q_vectors = [np.asarray(q) for q in args] 
    308         fn = self._kernel(q_vectors) 
     337        fn = self._model.make_kernel(q_vectors) 
    309338        pars = [self.params[v] for v in fn.fixed_pars] 
    310339        pd_pars = [self._get_weights(p) for p in fn.pd_pars] 
     
    384413    def _get_weights(self, par): 
    385414        """ 
    386             Return dispersion weights 
    387             :param par parameter name 
     415        Return dispersion weights for parameter 
    388416        """ 
    389417        from . import weights 
    390  
    391418        relative = self._model_info['partype']['pd-rel'] 
    392419        limits = self._model_info['limits'] 
     
    397424        return value, weight / np.sum(weight) 
    398425 
     426 
     427def test_model(): 
     428    """ 
     429    Test that a sasview model (cylinder) can be run. 
     430    """ 
     431    Cylinder = _make_standard_model('cylinder') 
     432    cylinder = Cylinder() 
     433    return cylinder.evalDistribution([0.1,0.1]) 
     434 
     435 
     436def test_model_list(): 
     437    """ 
     438    Make sure that all models build as sasview models. 
     439    """ 
     440    from .exception import annotate_exception 
     441    for name in core.list_models(): 
     442        try: 
     443            _make_standard_model(name) 
     444        except: 
     445            annotate_exception("when loading "+name) 
     446            raise 
     447 
     448if __name__ == "__main__": 
     449    print("cylinder(0.1,0.1)=%g"%test_model()) 
Note: See TracChangeset for help on using the changeset viewer.