8. Model access

sasmodels.core

Core model handling routines.

class sasmodels.core.KernelModel

Bases: object

Model definition for the compute engine.

__annotations__ = {'dtype': 'np.dtype', 'info': 'ModelInfo'}
__class__

alias of type

__delattr__(name, /)

Implement delattr(self, name).

__dict__ = mappingproxy({'__module__': 'sasmodels.kernel', '__doc__': '\n    Model definition for the compute engine.\n    ', 'info': None, 'dtype': None, 'make_kernel': <function KernelModel.make_kernel>, 'release': <function KernelModel.release>, '__dict__': <attribute '__dict__' of 'KernelModel' objects>, '__weakref__': <attribute '__weakref__' of 'KernelModel' objects>, '__annotations__': {'info': 'ModelInfo', 'dtype': 'np.dtype'}})
__dir__()

Default dir() implementation.

__doc__ = '\n    Model definition for the compute engine.\n    '
__eq__(value, /)

Return self==value.

__format__(format_spec, /)

Default object formatter.

__ge__(value, /)

Return self>=value.

__getattribute__(name, /)

Return getattr(self, name).

__getstate__()

Helper for pickle.

__gt__(value, /)

Return self>value.

__hash__()

Return hash(self).

__init__()
classmethod __init_subclass__()

This method is called when a class is subclassed.

The default implementation does nothing. It may be overridden to extend subclasses.

__le__(value, /)

Return self<=value.

__lt__(value, /)

Return self<value.

__module__ = 'sasmodels.kernel'
__ne__(value, /)

Return self!=value.

classmethod __new__(*args, **kwargs)
__reduce__()

Helper for pickle.

__reduce_ex__(protocol, /)

Helper for pickle.

__repr__()

Return repr(self).

__setattr__(name, value, /)

Implement setattr(self, name, value).

__sizeof__()

Size of object in memory, in bytes.

__str__()

Return str(self).

classmethod __subclasshook__()

Abstract classes can override this to customize issubclass().

This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it overrides the normal algorithm (and the outcome is cached).

__weakref__

list of weak references to the object

dtype: np.dtype = None
info: ModelInfo = None
make_kernel(q_vectors: List[np.ndarray]) Kernel

Instantiate a kernel for evaluating the model at q_vectors.

release() None

Free resources associated with the kernel.

class sasmodels.core.ModelInfo

Bases: object

Interpret the model definition file, categorizing the parameters.

The module can be loaded with a normal python import statement if you know which module you need, or with __import__(‘sasmodels.model.’+name) if the name is in a string.

The structure should be mostly static, other than the delayed definition of Iq, Iqac and Iqabc if they need to be defined.

Imagnetic: None | str | Callable[[...], ndarray] = None

Returns I(qx, qy, a, b, …). The interface follows Iq.

Iq: None | str | Callable[[...], ndarray] = None

Returns I(q, a, b, …) for parameters a, b, etc. defined by the parameter table. Iq can be defined as a python function, or as a C function. If it is defined in C, then set Iq to the body of the C function, including the return statement. This function takes values for q and each of the parameters as separate double values (which may be converted to float or long double by sasmodels). All source code files listed in source will be loaded before the Iq function is defined. If Iq is not present, then sources should define static double Iq(double q, double a, double b, …) which will return I(q, a, b, …). Multiplicity parameters are sent as pointers to doubles. Constants in floating point expressions should include the decimal point. See generate for more details. If have_Fq is True, then Iq should return an interleaved array of \([\sum F(q_1), \sum F^2(q_1), \ldots, \sum F(q_n), \sum F^2(q_n)]\).

Iqabc: None | str | Callable[[...], ndarray] = None

Returns I(qa, qb, qc, a, b, …). The interface follows Iq.

Iqac: None | str | Callable[[...], ndarray] = None

Returns I(qab, qc, a, b, …). The interface follows Iq.

Iqxy: None | str | Callable[[...], ndarray] = None

Returns I(qx, qy, a, b, …). The interface follows Iq.

__annotations__ = {'Imagnetic': 'Union[None, str, Callable[[...], np.ndarray]]', 'Iq': 'Union[None, str, Callable[[...], np.ndarray]]', 'Iqabc': 'Union[None, str, Callable[[...], np.ndarray]]', 'Iqac': 'Union[None, str, Callable[[...], np.ndarray]]', 'Iqxy': 'Union[None, str, Callable[[...], np.ndarray]]', 'base': 'ParameterTable', 'basefile': 'Optional[str]', 'c_code': 'Optional[str]', 'category': 'Optional[str]', 'composition': 'Optional[tuple[str, list[ModelInfo]]]', 'description': 'str', 'docs': 'str', 'filename': 'Optional[str]', 'form_volume': 'Union[None, str, Callable[[np.ndarray], float]]', 'hidden': 'Optional[Callable[[int], set[str]]]', 'id': 'str', 'lineno': 'dict[str, int]', 'name': 'str', 'opencl': 'bool', 'parameters': 'ParameterTable', 'profile': 'Optional[Callable[[np.ndarray], None]]', 'profile_axes': 'tuple[str, str]', 'radius_effective': 'Union[None, Callable[[int, np.ndarray], float]]', 'radius_effective_modes': 'list[str]', 'random': 'Optional[Callable[[], dict[str, float]]]', 'sesans': 'Optional[Callable[[np.ndarray], np.ndarray]]', 'shell_volume': 'Union[None, str, Callable[[np.ndarray], float]]', 'single': 'bool', 'source': 'list[str]', 'structure_factor': 'bool', 'tests': 'list[TestCondition]', 'title': 'str', 'translation': 'Optional[str]', 'valid': 'str'}
__class__

alias of type

__delattr__(name, /)

Implement delattr(self, name).

__dict__ = mappingproxy({'__module__': 'sasmodels.modelinfo', '__doc__': "\n    Interpret the model definition file, categorizing the parameters.\n\n    The module can be loaded with a normal python import statement if you\n    know which module you need, or with __import__('sasmodels.model.'+name)\n    if the name is in a string.\n\n    The structure should be mostly static, other than the delayed definition\n    of *Iq*, *Iqac* and *Iqabc* if they need to be defined.\n    ", 'filename': None, 'basefile': None, 'id': None, 'name': None, 'title': None, 'description': None, 'parameters': None, 'base': None, 'translation': None, 'composition': None, 'hidden': None, 'docs': None, 'category': None, 'single': None, 'opencl': None, 'structure_factor': None, 'have_Fq': False, 'radius_effective_modes': None, 'source': None, 'c_code': None, 'valid': None, 'form_volume': None, 'shell_volume': None, 'radius_effective': None, 'Iq': None, 'Iqxy': None, 'Iqac': None, 'Iqabc': None, 'Imagnetic': None, 'profile': None, 'profile_axes': None, 'sesans': None, 'random': None, 'lineno': None, 'tests': None, '__init__': <function ModelInfo.__init__>, 'get_hidden_parameters': <function ModelInfo.get_hidden_parameters>, '__dict__': <attribute '__dict__' of 'ModelInfo' objects>, '__weakref__': <attribute '__weakref__' of 'ModelInfo' objects>, '__annotations__': {'filename': 'Optional[str]', 'basefile': 'Optional[str]', 'id': 'str', 'name': 'str', 'title': 'str', 'description': 'str', 'parameters': 'ParameterTable', 'base': 'ParameterTable', 'translation': 'Optional[str]', 'composition': 'Optional[tuple[str, list[ModelInfo]]]', 'hidden': 'Optional[Callable[[int], set[str]]]', 'docs': 'str', 'category': 'Optional[str]', 'single': 'bool', 'opencl': 'bool', 'structure_factor': 'bool', 'radius_effective_modes': 'list[str]', 'source': 'list[str]', 'c_code': 'Optional[str]', 'valid': 'str', 'form_volume': 'Union[None, str, Callable[[np.ndarray], float]]', 'shell_volume': 'Union[None, str, Callable[[np.ndarray], float]]', 'radius_effective': 'Union[None, Callable[[int, np.ndarray], float]]', 'Iq': 'Union[None, str, Callable[[...], np.ndarray]]', 'Iqxy': 'Union[None, str, Callable[[...], np.ndarray]]', 'Iqac': 'Union[None, str, Callable[[...], np.ndarray]]', 'Iqabc': 'Union[None, str, Callable[[...], np.ndarray]]', 'Imagnetic': 'Union[None, str, Callable[[...], np.ndarray]]', 'profile': 'Optional[Callable[[np.ndarray], None]]', 'profile_axes': 'tuple[str, str]', 'sesans': 'Optional[Callable[[np.ndarray], np.ndarray]]', 'random': 'Optional[Callable[[], dict[str, float]]]', 'lineno': 'dict[str, int]', 'tests': 'list[TestCondition]'}})
__dir__()

Default dir() implementation.

__doc__ = "\n    Interpret the model definition file, categorizing the parameters.\n\n    The module can be loaded with a normal python import statement if you\n    know which module you need, or with __import__('sasmodels.model.'+name)\n    if the name is in a string.\n\n    The structure should be mostly static, other than the delayed definition\n    of *Iq*, *Iqac* and *Iqabc* if they need to be defined.\n    "
__eq__(value, /)

Return self==value.

__format__(format_spec, /)

Default object formatter.

__ge__(value, /)

Return self>=value.

__getattribute__(name, /)

Return getattr(self, name).

__getstate__()

Helper for pickle.

__gt__(value, /)

Return self>value.

__hash__()

Return hash(self).

__init__() None
classmethod __init_subclass__()

This method is called when a class is subclassed.

The default implementation does nothing. It may be overridden to extend subclasses.

__le__(value, /)

Return self<=value.

__lt__(value, /)

Return self<value.

__module__ = 'sasmodels.modelinfo'
__ne__(value, /)

Return self!=value.

classmethod __new__(*args, **kwargs)
__reduce__()

Helper for pickle.

__reduce_ex__(protocol, /)

Helper for pickle.

__repr__()

Return repr(self).

__setattr__(name, value, /)

Implement setattr(self, name, value).

__sizeof__()

Size of object in memory, in bytes.

__str__()

Return str(self).

classmethod __subclasshook__()

Abstract classes can override this to customize issubclass().

This is invoked early on by abc.ABCMeta.__subclasscheck__(). It should return True, False or NotImplemented. If it returns NotImplemented, the normal algorithm is used. Otherwise, it overrides the normal algorithm (and the outcome is cached).

__weakref__

list of weak references to the object

base: ParameterTable = None

For reparameterized systems, base is the base parameter table. For normal systems it is simply a copy of parameters.

basefile: str | None = None

Base file is usually filename, but not when a model has been reparameterized, in which case it is the file containing the original model definition. This is needed to signal an additional dependency for the model time stamp, and so that the compiler reports correct file for syntax errors.

c_code: str | None = None

inline source code, added after all elements of source

category: str | None = None

Location of the model description in the documentation. This takes the form of “section” or “section:subsection”. So for example, porod uses category=”shape-independent” so it is in the Shape-Independent Functions section whereas capped_cylinder uses: category=”shape:cylinder”, which puts it in the Cylinder Functions section.

composition: tuple[str, list[ModelInfo]] | None = None

Composition is None if this is an independent model, or it is a tuple with comoposition type (‘product’ or ‘misture’) and a list of ModelInfo blocks for the composed objects. This allows us to rebuild a complete mixture or product model from the info block. composition is not given in the model definition file, but instead arises when the model is constructed using names such as sphere*hardsphere or cylinder+sphere.

description: str = None

Long description of the model.

docs: str = None

Doc string from the top of the model file. This should be formatted using ReStructuredText format, with latex markup in “.. math” environments, or in dollar signs. This will be automatically extracted to a .rst file by generate.make_doc(), then converted to HTML or PDF by Sphinx.

filename: str | None = None

Full path to the file defining the kernel, if any.

form_volume: None | str | Callable[[ndarray], float] = None

Returns the form volume for python-based models. Form volume is needed for volume normalization in the polydispersity integral. If no parameters are volume parameters, then form volume is not needed. For C-based models, (with source defined, or with Iq defined using a string containing C code), form_volume must also be C code, either defined as a string, or in the sources.

get_hidden_parameters(control)

Returns the set of hidden parameters for the model. control is the value of the control parameter. Note that multiplicity models have an implicit control parameter, which is the parameter that controls the multiplicity.

have_Fq = False

True if the model defines an Fq function with signature void Fq(double q, double *F1, double *F2, ...)

hidden: Callable[[int], set[str]] | None = None

Different variants require different parameters. In order to show just the parameters needed for the variant selected, you should provide a function hidden(control) -> set([‘a’, ‘b’, …]) indicating which parameters need to be hidden. For multiplicity models, you need to use the complete name of the parameter, including its number. So for example, if variant “a” uses only sld1 and sld2, then sld3, sld4 and sld5 of multiplicity parameter sld[5] should be in the hidden set.

id: str = None

Id of the kernel used to load it from the filesystem.

lineno: dict[str, int] = None

Line numbers for symbols defining C code

name: str = None

Display name of the model, which defaults to the model id but with capitalization of the parts so for example core_shell defaults to “Core Shell”.

opencl: bool = None

True if the model can be run as an opencl model. If for some reason the model cannot be run in opencl (e.g., because the model passes functions by reference), then set this to false.

parameters: ParameterTable = None

Model parameter table. Parameters are defined using a list of parameter definitions, each of which is contains parameter name, units, default value, limits, type and description. See Parameter for details on the individual parameters. The parameters are gathered into a ParameterTable, which provides various views into the parameter list.

profile: Callable[[ndarray], None] | None = None

Returns a model profile curve x, y. If profile is defined, this curve will appear in response to the Show button in SasView. Use profile_axes to set the axis labels. Note that y values will be scaled by 1e6 before plotting.

profile_axes: tuple[str, str] = None

Axis labels for the profile plot. The default is [‘x’, ‘y’]. Only the x component is used for now.

radius_effective: None | Callable[[int, ndarray], float] = None

Computes the effective radius of the shape given the volume parameters. Only needed for models defined in python that can be used for monodisperse approximation for non-dilute solutions, P@S. The first argument is the integer effective radius mode, with default 0.

radius_effective_modes: list[str] = None

List of options for computing the effective radius of the shape, or None if the model is not usable as a form factor model.

random: Callable[[], dict[str, float]] | None = None

Returns a random parameter set for the model

sesans: Callable[[ndarray], ndarray] | None = None

Returns sesans(z, a, b, …) for models which can directly compute the SESANS correlation function. Note: not currently implemented.

shell_volume: None | str | Callable[[ndarray], float] = None

Returns the shell volume for python-based models. Form volume and shell volume are needed for volume normalization in the polydispersity integral and structure interactions for hollow shapes. If no parameters are volume parameters, then shell volume is not needed. For C-based models, (with source defined, or with Iq defined using a string containing C code), shell_volume must also be C code, either defined as a string, or in the sources.

single: bool = None

True if the model can be computed accurately with single precision. This is True by default, but models such as bcc_paracrystal set it to False because they require double precision calculations.

source: list[str] = None

List of C source files used to define the model. The source files should define the Iq function, and possibly Iqac or Iqabc if the model defines orientation parameters. Files containing the most basic functions must appear first in the list, followed by the files that use those functions.

structure_factor: bool = None

True if the model is a structure factor used to model the interaction between form factor models. This will default to False if it is not provided in the file.

tests: list[tuple[Mapping[str, float | list[float]], str | float | list[float] | tuple[float, float] | list[tuple[float, float]], float | list[float]]] = None

The set of tests that must pass. The format of the tests is described in model_test.

title: str = None

Short description of the model.

translation: str | None = None

Parameter translation code to convert from parameters table from caller to the base table used to evaluate the model.

valid: str = None

Expression which evaluates to True if the input parameters are valid and the model can be computed, or False otherwise. Invalid parameter sets will not be included in the weighted \(I(Q)\) calculation or its volume normalization. Use C syntax for the expressions, with || for or && for and and ! for not. Any non-magnetic parameter can be used.

sasmodels.core._matches(name, kind)
sasmodels.core.basename(p)

Returns the final component of a pathname

sasmodels.core.build_model(model_info: ModelInfo, dtype: str = None, platform: str = 'ocl') KernelModel

Prepare the model for the default execution platform.

This will return an OpenCL model, a DLL model or a python model depending on the model and the computing platform.

model_info is the model definition structure returned from load_model_info().

dtype indicates whether the model should use single or double precision for the calculation. Choices are ‘single’, ‘double’, ‘quad’, ‘half’, or ‘fast’. If dtype ends with ‘!’, then force the use of the DLL rather than OpenCL for the calculation.

platform should be “dll” to force the dll to be used for C models, otherwise it uses the default “ocl”.

sasmodels.core.glob(pathname, *, root_dir=None, dir_fd=None, recursive=False, include_hidden=False)

Return a list of paths matching a pathname pattern.

The pattern may contain simple shell-style wildcards a la fnmatch. Unlike fnmatch, filenames starting with a dot are special cases that are not matched by ‘*’ and ‘?’ patterns by default.

If include_hidden is true, the patterns ‘*’, ‘?’, ‘**’ will match hidden directories.

If recursive is true, the pattern ‘**’ will match any files and zero or more directories and subdirectories.

sasmodels.core.joinpath(path, *paths)
sasmodels.core.list_models(kind: str = None) list[str]

Return the list of available models on the model path.

kind can be one of the following:

  • all: all models

  • py: python models only

  • c: c models only

  • single: c models which support single precision

  • double: c models which require double precision

  • opencl: c models which run in opencl

  • dll: c models which do not run in opencl

  • 1d: models without orientation

  • 2d: models with orientation

  • magnetic: models supporting magnetic sld

  • nommagnetic: models without magnetic parameter

For multiple conditions, combine with plus. For example, c+single+2d would return all oriented models implemented in C which can be computed accurately with single precision arithmetic.

sasmodels.core.list_models_main() int

Run list_models as a main program. See list_models() for the kinds of models that can be requested on the command line.

sasmodels.core.load_model(model_name: str, dtype: str = None, platform: str = 'ocl') KernelModel

Load model info and build model.

model_name is the name of the model, or perhaps a model expression such as sphere*hardsphere or sphere+cylinder.

dtype and platform are given by build_model().

sasmodels.core.load_model_info(model_string: str) ModelInfo

Load a model definition given the model name.

model_string is the name of the model, or perhaps a model expression such as sphere*cylinder or sphere+cylinder. Use ‘@’ for a structure factor product, e.g. sphere@hardsphere. Custom models can be specified by prefixing the model name with ‘custom.’, e.g. ‘custom.MyModel+sphere’.

This returns a handle to the module defining the model. This can be used with functions in generate to build the docs or extract model info.

sasmodels.core.merge_deps(old, new)

Merge two dependency lists. The lists are partially ordered, with all dependents coming after the items they depend on, but otherwise order doesn’t matter. The merged list preserves the partial ordering. So if old and new both include the item “c”, then all items that come before “c” in old and new will come before “c” in the result, and all items that come after “c” in old and new will come after “c” in the result.

sasmodels.core.parse_dtype(model_info: ModelInfo, dtype: str = None, platform: str = None) tuple[dtype, bool, str]

Interpret dtype string, returning np.dtype, fast flag and platform.

Possible types include ‘half’, ‘single’, ‘double’ and ‘quad’. If the type is ‘fast’, then this is equivalent to dtype ‘single’ but using fast native functions rather than those with the precision level guaranteed by the OpenCL standard. ‘default’ will choose the appropriate default for the model and platform.

Platform preference can be specfied (“ocl”, “cuda”, “dll”), with the default being OpenCL or CUDA if available, otherwise DLL. If the dtype name ends with ‘!’ then platform is forced to be DLL rather than GPU. The default platform is set by the environment variable SAS_OPENCL, SAS_OPENCL=driver:device for OpenCL, SAS_OPENCL=cuda:device for CUDA or SAS_OPENCL=none for DLL.

This routine ignores the preferences within the model definition. This is by design. It allows us to test models in single precision even when we have flagged them as requiring double precision so we can easily check the performance on different platforms without having to change the model definition.

sasmodels.core.precompile_dlls(path: str, dtype: str = 'double') list[str]

Precompile the dlls for all builtin models, returning a list of dll paths.

path is the directory in which to save the dlls. It will be created if it does not already exist.

This can be used when build the windows distribution of sasmodels which may be missing the OpenCL driver and the dll compiler.

sasmodels.core.reparameterize(base, parameters, translation, filename=None, title=None, insert_after=None, docs=None, name=None, source=None)

Reparameterize an existing model.

base is the original modelinfo. This cannot be a reparameterized model; only one level of reparameterization is supported.

parameters are the new parameter definitions that will be included in the model info.

translation is a string each line containing var = expr. The variable var can be a new intermediate value, or it can be a parameter from the base model that will be replace by the expression. The expression expr can be any C99 expression, including C-style if-expressions condition ? value1 : value2. Expressions can use any new or existing parameter that is not being replaced including intermediate values that are previously defined. Parameters can only be assigned once, never updated. C99 math functions are available, as well as any functions defined in the base model or included in source (see below).

filename is the filename for the replacement model. This is usually __file__, giving the path to the model file, but it could also be a nominal filename for translations defined on-the-fly.

title is the model title, which defaults to base.title plus “ (reparameterized)”.

insert_after controls parameter placement. By default, the new parameters replace the old parameters in their original position. Instead, you can provide a dictionary {‘par’: ‘newpar1,newpar2’} indicating that new parameters named newpar1 and newpar2 should be included in the table after the existing parameter par, or at the beginning if par is the empty string.

docs constains the doc string for the translated model, which by default references the base model and gives the translation text.

name is the model name (default = "constrained_" + base.name).

source is a list any additional C source files that should be included to define functions and constants used in the translation expressions. This will be included after all sources for the base model. Sources will only be included once, even if they are listed in both places, so feel free to list all dependencies for the helper function, such as “lib/polevl.c”.

sasmodels.core.test_composite() None

Check that model load works

sasmodels.core.test_composite_order()

Check that mixture models produce the same result independent of ordder.