Changeset 61a4bd4 in sasmodels for sasmodels/mixture.py


Ignore:
Timestamp:
Sep 4, 2017 12:09:27 PM (7 years ago)
Author:
lewis
Branches:
master, core_shell_microgels, costrafo411, magnetic_model, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
Children:
481ff64
Parents:
65314f7
Message:

Refactor load_model_info to parse more complex model strings

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sasmodels/mixture.py

    rfb9a3b6 r61a4bd4  
    3030    Create info block for mixture model. 
    3131    """ 
    32     flatten = [] 
    33     for part in parts: 
    34         if part.composition and part.composition[0] == 'mixture': 
    35             flatten.extend(part.composition[1]) 
    36         else: 
    37             flatten.append(part) 
    38     parts = flatten 
    39  
    4032    # Build new parameter list 
    4133    combined_pars = [] 
    4234    demo = {} 
     35 
     36    model_num = 0 
     37    all_parts = copy(parts) 
     38    is_flat = False 
     39    while not is_flat: 
     40        is_flat = True 
     41        for part in all_parts: 
     42            if part.composition and part.composition[0] == 'mixture' and \ 
     43                len(part.composition[1]) > 1: 
     44                all_parts += part.composition[1] 
     45                all_parts.remove(part) 
     46                is_flat = False 
     47 
     48    # When creating a mixture model that is a sum of product models (ie (1*2)+(3*4)) 
     49    # the parameters for models 1 & 2 will be prefixed with A & B respectively, 
     50    # but so will the parameters for models 3 & 4. We need to rename models 3 & 4 
     51    # so that they are prefixed with C & D to avoid overlap of parameter names. 
     52    used_prefixes = [] 
     53    for part in parts: 
     54        i = 0 
     55        if part.composition and part.composition[0] == 'mixture': 
     56            npars_list = [info.parameters.npars for info in part.composition[1]] 
     57            for npars in npars_list: 
     58                # List of params of one of the constituent models of part 
     59                submodel_pars = part.parameters.kernel_parameters[i:i+npars] 
     60                # Prefix of the constituent model 
     61                prefix = submodel_pars[0].name[0] 
     62                if prefix not in used_prefixes: # Haven't seen this prefix so far 
     63                    used_prefixes.append(prefix) 
     64                    i += npars 
     65                    continue 
     66                while prefix in used_prefixes: 
     67                    # This prefix has been already used, so change it to the 
     68                    # next letter that hasn't been used 
     69                    prefix = chr(ord(prefix) + 1) 
     70                used_prefixes.append(prefix) 
     71                prefix += "_" 
     72                # Update the parameters of this constituent model to use the 
     73                # new prefix 
     74                for par in submodel_pars: 
     75                    par.id = prefix + par.id[2:] 
     76                    par.name = prefix + par.name[2:] 
     77                    if par.length_control is not None: 
     78                        par.length_control = prefix + par.length_control[2:] 
     79                i += npars 
     80 
     81    model_num = len(all_parts) - len(parts) 
     82    if model_num != 0: 
     83        model_num += 1 
     84 
    4385    for k, part in enumerate(parts): 
    4486        # Parameter prefix per model, A_, B_, ... 
    4587        # Note that prefix must also be applied to id and length_control 
    4688        # to support vector parameters 
    47         prefix = chr(ord('A')+k) + '_' 
     89        prefix = chr(ord('A')+k+model_num) + '_' 
     90        if part.composition and part.composition[0] == 'mixture': 
     91            # Parameter already has a prefix as it's part of a composition model 
     92            prefix = '' 
     93            model_num -= 1 
     94             
    4895        if operation == '+': 
    4996            # If model is a sum model, each constituent model gets its own scale parameter 
    50             scale =  Parameter(prefix+'scale', default=1.0, 
     97            scale_prefix = prefix 
     98            if prefix == '' and part.operation == '*': 
     99                # `part` is a composition product model. Find the prefixes of 
     100                # it's parameters to form a new prefix for the scale, eg: 
     101                # a model with A*B*C will have ABC_scale 
     102                sub_prefixes = [] 
     103                for param in part.parameters.kernel_parameters: 
     104                    # Prefix of constituent model 
     105                    sub_prefix = param.id.split('_')[0] 
     106                    if sub_prefix not in sub_prefixes: 
     107                        sub_prefixes.append(sub_prefix) 
     108                # Concatenate sub_prefixes to form prefix for the scale 
     109                scale_prefix = ''.join(sub_prefixes) + '_' 
     110            scale =  Parameter(scale_prefix + 'scale', default=1.0, 
    51111                            description="model intensity for " + part.name) 
    52112            combined_pars.append(scale) 
     
    67127    model_info.id = operation.join(part.id for part in parts) 
    68128    model_info.operation = operation 
    69     model_info.name = operation.join(part.name for part in parts) 
     129    model_info.name = '(' + operation.join(part.name for part in parts) + ')' 
    70130    model_info.filename = None 
    71131    model_info.title = 'Mixture model with ' + model_info.name 
Note: See TracChangeset for help on using the changeset viewer.