Changeset 765d025 in sasmodels for sasmodels/modelinfo.py


Ignore:
Timestamp:
Oct 30, 2018 10:05:27 AM (5 years ago)
Author:
Paul Kienzle <pkienzle@…>
Children:
646eeaa
Parents:
1662ebe (diff), aa8c6e0 (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 remote-tracking branch 'upstream/beta_approx'

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sasmodels/modelinfo.py

    r1662ebe r765d025  
    5050# Note that scale and background cannot be coordinated parameters whose value 
    5151# depends on the some polydisperse parameter with the current implementation 
     52DEFAULT_BACKGROUND = 1e-3 
    5253COMMON_PARAMETERS = [ 
    5354    ("scale", "", 1, (0.0, np.inf), "", "Source intensity"), 
    54     ("background", "1/cm", 1e-3, (-np.inf, np.inf), "", "Source background"), 
     55    ("background", "1/cm", DEFAULT_BACKGROUND, (-np.inf, np.inf), "", "Source background"), 
    5556] 
    5657assert (len(COMMON_PARAMETERS) == 2 
     
    168169    parameter.length = length 
    169170    parameter.length_control = control 
    170  
    171171    return parameter 
    172172 
     
    269269    will have a magnitude and a direction, which may be different from 
    270270    other sld parameters. The volume parameters are used for calls 
    271     to form_volume within the kernel (required for volume normalization) 
    272     and for calls to ER and VR for effective radius and volume ratio 
    273     respectively. 
     271    to form_volume within the kernel (required for volume normalization), 
     272    to shell_volume (for hollow shapes), and to effective_radius (for 
     273    structure factor interactions) respectively. 
    274274 
    275275    *description* is a short description of the parameter.  This will 
     
    428428        self.kernel_parameters = parameters 
    429429        self._set_vector_lengths() 
    430  
    431430        self.npars = sum(p.length for p in self.kernel_parameters) 
    432431        self.nmagnetic = sum(p.length for p in self.kernel_parameters 
     
    435434        if self.nmagnetic: 
    436435            self.nvalues += 3 + 3*self.nmagnetic 
    437  
    438436        self.call_parameters = self._get_call_parameters() 
    439437        self.defaults = self._get_defaults() 
     
    470468        self.is_asymmetric = any(p.name == 'psi' for p in self.kernel_parameters) 
    471469        self.magnetism_index = [k for k, p in enumerate(self.call_parameters) 
    472                                 if p.id.startswith('M0:')] 
     470                                if p.id.endswith('_M0')] 
    473471 
    474472        self.pd_1d = set(p.name for p in self.call_parameters 
     
    590588        if self.nmagnetic > 0: 
    591589            full_list.extend([ 
    592                 Parameter('up:frac_i', '', 0., [0., 1.], 
     590                Parameter('up_frac_i', '', 0., [0., 1.], 
    593591                          'magnetic', 'fraction of spin up incident'), 
    594                 Parameter('up:frac_f', '', 0., [0., 1.], 
     592                Parameter('up_frac_f', '', 0., [0., 1.], 
    595593                          'magnetic', 'fraction of spin up final'), 
    596                 Parameter('up:angle', 'degress', 0., [0., 360.], 
     594                Parameter('up_angle', 'degrees', 0., [0., 360.], 
    597595                          'magnetic', 'spin up angle'), 
    598596            ]) 
     
    600598            for p in slds: 
    601599                full_list.extend([ 
    602                     Parameter('M0:'+p.id, '1e-6/Ang^2', 0., [-np.inf, np.inf], 
     600                    Parameter(p.id+'_M0', '1e-6/Ang^2', 0., [-np.inf, np.inf], 
    603601                              'magnetic', 'magnetic amplitude for '+p.description), 
    604                     Parameter('mtheta:'+p.id, 'degrees', 0., [-90., 90.], 
     602                    Parameter(p.id+'_mtheta', 'degrees', 0., [-90., 90.], 
    605603                              'magnetic', 'magnetic latitude for '+p.description), 
    606                     Parameter('mphi:'+p.id, 'degrees', 0., [-180., 180.], 
     604                    Parameter(p.id+'_mphi', 'degrees', 0., [-180., 180.], 
    607605                              'magnetic', 'magnetic longitude for '+p.description), 
    608606                ]) 
     
    644642 
    645643        Parameters marked as sld will automatically have a set of associated 
    646         magnetic parameters (m0:p, mtheta:p, mphi:p), as well as polarization 
    647         information (up:theta, up:frac_i, up:frac_f). 
     644        magnetic parameters (p_M0, p_mtheta, p_mphi), as well as polarization 
     645        information (up_theta, up_frac_i, up_frac_f). 
    648646        """ 
    649647        # control parameters go first 
     
    672670            result.append(expanded_pars[name]) 
    673671            if is2d: 
    674                 for tag in 'M0:', 'mtheta:', 'mphi:': 
    675                     if tag+name in expanded_pars: 
    676                         result.append(expanded_pars[tag+name]) 
     672                for tag in '_M0', '_mtheta', '_mphi': 
     673                    if name+tag in expanded_pars: 
     674                        result.append(expanded_pars[name+tag]) 
    677675 
    678676        # Gather the user parameters in order 
     
    707705                append_group(p.id) 
    708706 
    709         if is2d and 'up:angle' in expanded_pars: 
     707        if is2d and 'up_angle' in expanded_pars: 
    710708            result.extend([ 
    711                 expanded_pars['up:frac_i'], 
    712                 expanded_pars['up:frac_f'], 
    713                 expanded_pars['up:angle'], 
     709                expanded_pars['up_frac_i'], 
     710                expanded_pars['up_frac_f'], 
     711                expanded_pars['up_angle'], 
    714712            ]) 
    715713 
     
    726724 
    727725#: Set of variables defined in the model that might contain C code 
    728 C_SYMBOLS = ['Imagnetic', 'Iq', 'Iqxy', 'Iqac', 'Iqabc', 'form_volume', 'c_code'] 
     726C_SYMBOLS = ['Imagnetic', 'Iq', 'Iqxy', 'Iqac', 'Iqabc', 'form_volume', 'shell_volume', 'c_code'] 
    729727 
    730728def _find_source_lines(model_info, kernel_module): 
     
    775773        # Custom sum/multi models 
    776774        return kernel_module.model_info 
     775 
    777776    info = ModelInfo() 
    778777    #print("make parameter table", kernel_module.parameters) 
     
    796795    info.category = getattr(kernel_module, 'category', None) 
    797796    info.structure_factor = getattr(kernel_module, 'structure_factor', False) 
     797    # TODO: find Fq by inspection 
     798    info.effective_radius_type = getattr(kernel_module, 'effective_radius_type', None) 
     799    info.have_Fq = getattr(kernel_module, 'have_Fq', False) 
    798800    info.profile_axes = getattr(kernel_module, 'profile_axes', ['x', 'y']) 
     801    # Note: custom.load_custom_kernel_module assumes the C sources are defined 
     802    # by this attribute. 
    799803    info.source = getattr(kernel_module, 'source', []) 
    800804    info.c_code = getattr(kernel_module, 'c_code', None) 
     805    info.effective_radius = getattr(kernel_module, 'effective_radius', None) 
    801806    # TODO: check the structure of the tests 
    802807    info.tests = getattr(kernel_module, 'tests', []) 
    803     info.ER = getattr(kernel_module, 'ER', None) # type: ignore 
    804     info.VR = getattr(kernel_module, 'VR', None) # type: ignore 
    805808    info.form_volume = getattr(kernel_module, 'form_volume', None) # type: ignore 
     809    info.shell_volume = getattr(kernel_module, 'shell_volume', None) # type: ignore 
    806810    info.Iq = getattr(kernel_module, 'Iq', None) # type: ignore 
    807811    info.Iqxy = getattr(kernel_module, 'Iqxy', None) # type: ignore 
     
    811815    info.profile = getattr(kernel_module, 'profile', None) # type: ignore 
    812816    info.sesans = getattr(kernel_module, 'sesans', None) # type: ignore 
    813     # Default single and opencl to True for C models.  Python models have callable Iq. 
    814817    info.random = getattr(kernel_module, 'random', None) 
    815818 
     
    824827    if getattr(kernel_module, 'py2c', False): 
    825828        try: 
    826             autoc.convert(info, kernel_module) 
     829            warnings = autoc.convert(info, kernel_module) 
    827830        except Exception as exc: 
    828             logger.warn(str(exc) + " while converting %s from C to python"%name) 
    829  
     831            warnings = [str(exc)] 
     832        if warnings: 
     833            warnings.append("while converting %s from C to python"%name) 
     834            if len(warnings) > 2: 
     835                warnings = "\n".join(warnings) 
     836            else: 
     837                warnings = " ".join(warnings) 
     838            logger.warn(warnings) 
     839 
     840    # Default single and opencl to True for C models.  Python models have callable Iq. 
    830841    # Needs to come after autoc.convert since the Iq symbol may have been 
    831842    # converted from python to C 
     
    928939    #: provided in the file. 
    929940    structure_factor = None # type: bool 
     941    #: True if the model defines an Fq function with signature 
     942    #: void Fq(double q, double *F1, double *F2, ...) 
     943    have_Fq = False 
     944    #: List of options for computing the effective radius of the shape, 
     945    #: or None if the model is not usable as a form factor model. 
     946    effective_radius_type = None   # type: List[str] 
    930947    #: List of C source files used to define the model.  The source files 
    931948    #: should define the *Iq* function, and possibly *Iqac* or *Iqabc* if the 
    932949    #: model defines orientation parameters. Files containing the most basic 
    933950    #: functions must appear first in the list, followed by the files that 
    934     #: use those functions.  Form factors are indicated by providing 
    935     #: an :attr:`ER` function. 
     951    #: use those functions. 
    936952    source = None           # type: List[str] 
    937     #: The set of tests that must pass.  The format of the tests is described 
    938     #: in :mod:`model_test`. 
    939     tests = None            # type: List[TestCondition] 
    940     #: Returns the effective radius of the model given its volume parameters. 
    941     #: The presence of *ER* indicates that the model is a form factor model 
    942     #: that may be used together with a structure factor to form an implicit 
    943     #: multiplication model. 
    944     #: 
    945     #: The parameters to the *ER* function must be marked with type *volume*. 
    946     #: in the parameter table.  They will appear in the same order as they 
    947     #: do in the table.  The values passed to *ER* will be vectors, with one 
    948     #: value for each polydispersity condition.  For example, if the model 
    949     #: is polydisperse over both length and radius, then both length and 
    950     #: radius will have the same number of values in the vector, with one 
    951     #: value for each *length X radius*.  If only *radius* is polydisperse, 
    952     #: then the value for *length* will be repeated once for each value of 
    953     #: *radius*.  The *ER* function should return one effective radius for 
    954     #: each parameter set.  Multiplicity parameters will be received as 
    955     #: arrays, with one row per polydispersity condition. 
    956     ER = None               # type: Optional[Callable[[np.ndarray], np.ndarray]] 
    957     #: Returns the occupied volume and the total volume for each parameter set. 
    958     #: See :attr:`ER` for details on the parameters. 
    959     VR = None               # type: Optional[Callable[[np.ndarray], Tuple[np.ndarray, np.ndarray]]] 
    960     #: Arbitrary C code containing supporting functions, etc., to be inserted 
    961     #: after everything in source.  This can include Iq and Iqxy functions with 
    962     #: the full function signature, including all parameters. 
    963     c_code = None 
     953    #: inline source code, added after all elements of source 
     954    c_code = None           # type: Optional[str] 
    964955    #: Returns the form volume for python-based models.  Form volume is needed 
    965956    #: for volume normalization in the polydispersity integral.  If no 
     
    969960    #: C code, either defined as a string, or in the sources. 
    970961    form_volume = None      # type: Union[None, str, Callable[[np.ndarray], float]] 
     962    #: Returns the shell volume for python-based models.  Form volume and 
     963    #: shell volume are needed for volume normalization in the polydispersity 
     964    #: integral and structure interactions for hollow shapes.  If no 
     965    #: parameters are *volume* parameters, then shell volume is not needed. 
     966    #: For C-based models, (with :attr:`sources` defined, or with :attr:`Iq` 
     967    #: defined using a string containing C code), shell_volume must also be 
     968    #: C code, either defined as a string, or in the sources. 
     969    shell_volume = None      # type: Union[None, str, Callable[[np.ndarray], float]] 
    971970    #: Returns *I(q, a, b, ...)* for parameters *a*, *b*, etc. defined 
    972971    #: by the parameter table.  *Iq* can be defined as a python function, or 
     
    10031002    #: Line numbers for symbols defining C code 
    10041003    lineno = None           # type: Dict[str, int] 
     1004    #: The set of tests that must pass.  The format of the tests is described 
     1005    #: in :mod:`model_test`. 
     1006    tests = None            # type: List[TestCondition] 
    10051007 
    10061008    def __init__(self): 
     
    10261028                         for k in range(control+1, p.length+1) 
    10271029                         if p.length > 1) 
     1030            for p in self.parameters.kernel_parameters: 
     1031                if p.length > 1 and p.type == "sld": 
     1032                    for k in range(control+1, p.length+1): 
     1033                        base = p.id+str(k) 
     1034                        hidden.update((base+"_M0", base+"_mtheta", base+"_mphi")) 
    10281035        return hidden 
Note: See TracChangeset for help on using the changeset viewer.