Changeset c5a22a85 in sasview


Ignore:
Timestamp:
Nov 3, 2016 3:16:18 AM (7 years ago)
Author:
ajj
Branches:
release_4.0.1
Children:
736f27e
Parents:
ed0b796
git-author:
Andrew Jackson <andrew.jackson@…> (10/10/16 09:52:19)
git-committer:
Andrew Jackson <andrew.jackson@…> (11/03/16 03:16:18)
Message:

Updating muliplicationmodel to be correct.

Fixes #750

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/sas/sascalc/fit/MultiplicationModel.py

    rcb4ef58 rc5a22a85  
    88    r""" 
    99        Use for P(Q)\*S(Q); function call must be in the order of P(Q) and then S(Q): 
    10         The model parameters are combined from both models, P(Q) and S(Q), except 1) 'effect_radius' of S(Q) 
    11         which will be calculated from P(Q) via calculate_ER(),  
    12         and 2) 'scale' in P model which is synchronized w/ volfraction in S  
     10        The model parameters are combined from both models, P(Q) and S(Q), except 1) 'radius_effective' of S(Q) 
     11        which will be calculated from P(Q) via calculate_ER(), 
     12        and 2) 'scale' in P model which is synchronized w/ volfraction in S 
    1313        then P*S is multiplied by a new parameter, 'scale_factor'. 
    1414        The polydispersion is applicable only to P(Q), not to S(Q). 
     
    3434        ## Parameter details [units, min, max] 
    3535        self.details = {} 
    36          
    37         ##models  
     36 
     37        ## Define parameters to exclude from multiplication model 
     38        self.excluded_params={'radius_effective','scale','background'} 
     39 
     40        ##models 
    3841        self.p_model = p_model 
    39         self.s_model = s_model         
     42        self.s_model = s_model 
    4043        self.magnetic_params = [] 
    4144        ## dispersion 
     
    4548        ## New parameter:Scaling factor 
    4649        self.params['scale_factor'] = 1 
    47          
     50        self.params['background']  = 0 
     51 
    4852        ## Parameter details [units, min, max] 
    4953        self._set_details() 
    5054        self.details['scale_factor'] = ['', 0.0, numpy.inf] 
    51          
     55        self.details['background'] = ['',-numpy.inf,numpy.inf] 
     56 
    5257        #list of parameter that can be fitted 
    53         self._set_fixed_params()   
     58        self._set_fixed_params() 
    5459        ## parameters with orientation 
    5560        for item in self.p_model.orientation_params: 
    5661            self.orientation_params.append(item) 
    57         for item in self.p_model.magnetic_params:   
    58             self.magnetic_params.append(item)  
     62        for item in self.p_model.magnetic_params: 
     63            self.magnetic_params.append(item) 
    5964        for item in self.s_model.orientation_params: 
    6065            if not item in self.orientation_params: 
     
    6671            multiplicity = 1 
    6772        ## functional multiplicity of the model 
    68         self.multiplicity = multiplicity     
    69            
     73        self.multiplicity = multiplicity 
     74 
    7075        # non-fittable parameters 
    71         self.non_fittable = p_model.non_fittable   
    72         self.multiplicity_info = []  
     76        self.non_fittable = p_model.non_fittable 
     77        self.multiplicity_info = [] 
    7378        self.fun_list = {} 
    7479        if self.non_fittable > 1: 
    7580            try: 
    76                 self.multiplicity_info = p_model.multiplicity_info  
     81                self.multiplicity_info = p_model.multiplicity_info 
    7782                self.fun_list = p_model.fun_list 
    7883                self.is_multiplicity_model = True 
     
    8287            self.is_multiplicity_model = False 
    8388            self.multiplicity_info = [0] 
    84              
     89 
    8590    def _clone(self, obj): 
    8691        """ 
     
    96101        #obj = copy.deepcopy(self) 
    97102        return obj 
    98      
    99      
     103 
     104 
    100105    def _set_dispersion(self): 
    101106        """ 
     
    103108        applied to s_model 
    104109        """ 
    105         ##set dispersion only from p_model  
     110        ##set dispersion only from p_model 
    106111        for name , value in self.p_model.dispersion.iteritems(): 
    107             self.dispersion[name] = value  
    108                                        
     112            self.dispersion[name] = value 
     113 
    109114    def getProfile(self): 
    110115        """ 
    111116        Get SLD profile of p_model if exists 
    112          
     117 
    113118        :return: (r, beta) where r is a list of radius of the transition points\ 
    114119                beta is a list of the corresponding SLD values 
     
    121126            x = None 
    122127            y = None 
    123              
     128 
    124129        return x, y 
    125      
     130 
    126131    def _set_params(self): 
    127132        """ 
    128133        Concatenate the parameters of the two models to create 
    129         these model parameters  
     134        these model parameters 
    130135        """ 
    131136 
    132137        for name , value in self.p_model.params.iteritems(): 
    133             if not name in self.params.keys() and name != 'scale': 
     138            if not name in self.params.keys() and name not in self.excluded_params: 
    134139                self.params[name] = value 
    135              
     140 
    136141        for name , value in self.s_model.params.iteritems(): 
    137             #Remove the effect_radius from the (P*S) model parameters. 
    138             if not name in self.params.keys() and name != 'effect_radius': 
     142            #Remove the radius_effective from the (P*S) model parameters. 
     143            if not name in self.params.keys() and name not in self.excluded_params: 
    139144                self.params[name] = value 
    140                  
     145 
    141146        # Set "scale and effec_radius to P and S model as initializing 
    142147        # since run P*S comes from P and S separately. 
     148        self._set_backgrounds() 
    143149        self._set_scale_factor() 
    144         self._set_effect_radius()        
    145              
     150        self._set_radius_effective() 
     151 
    146152    def _set_details(self): 
    147153        """ 
    148154        Concatenate details of the two models to create 
    149         this model's details  
     155        this model's details 
    150156        """ 
    151157        for name, detail in self.p_model.details.iteritems(): 
    152             if name != 'scale': 
     158            if name not in self.excluded_params: 
    153159                self.details[name] = detail 
    154              
     160 
    155161        for name , detail in self.s_model.details.iteritems(): 
    156             if not name in self.details.keys() or name != 'effect_radius': 
     162            if not name in self.details.keys() or name not in self.exluded_params: 
    157163                self.details[name] = detail 
    158      
     164 
     165    def _set_backgrounds(self): 
     166        """ 
     167        Set component backgrounds to zero 
     168        """ 
     169        self.p_model.setParam('background',0) 
     170        self.s_model.setParam('background',0) 
     171 
     172 
    159173    def _set_scale_factor(self): 
    160174        """ 
     
    162176        """ 
    163177        value = self.params['volfraction'] 
    164         if value != None:  
     178        if value != None: 
    165179            factor = self.p_model.calculate_VR() 
    166180            if factor == None or factor == NotImplemented or factor == 0.0: 
     
    170184            self.p_model.setParam('scale', value) 
    171185            self.s_model.setParam('volfraction', val) 
    172              
    173     def _set_effect_radius(self): 
     186 
     187    def _set_radius_effective(self): 
    174188        """ 
    175189        Set effective radius to S(Q) model 
    176190        """ 
    177         if not 'effect_radius' in self.s_model.params.keys(): 
     191        if not 'radius_effective' in self.s_model.params.keys(): 
    178192            return 
    179193        effective_radius = self.p_model.calculate_ER() 
    180194        #Reset the effective_radius of s_model just before the run 
    181195        if effective_radius != None and effective_radius != NotImplemented: 
    182             self.s_model.setParam('effect_radius', effective_radius) 
    183                  
     196            self.s_model.setParam('radius_effective', effective_radius) 
     197 
    184198    def setParam(self, name, value): 
    185         """  
     199        """ 
    186200        Set the value of a model parameter 
    187          
     201 
    188202        :param name: name of the parameter 
    189203        :param value: value of the parameter 
     
    191205        # set param to P*S model 
    192206        self._setParamHelper( name, value) 
    193          
    194         ## setParam to p model  
    195         # set 'scale' in P(Q) equal to volfraction  
     207 
     208        ## setParam to p model 
     209        # set 'scale' in P(Q) equal to volfraction 
    196210        if name == 'volfraction': 
    197211            self._set_scale_factor() 
    198         elif name in self.p_model.getParamList(): 
     212        elif name in self.p_model.getParamList() and name not in self.excluded_params: 
    199213            self.p_model.setParam( name, value) 
    200          
    201         ## setParam to s model  
    202         # This is a little bit abundant: Todo: find better way          
    203         self._set_effect_radius() 
    204         if name in self.s_model.getParamList(): 
     214 
     215        ## setParam to s model 
     216        # This is a little bit abundant: Todo: find better way 
     217        self._set_radius_effective() 
     218        if name in self.s_model.getParamList() and name not in self.excluded_params: 
    205219            if name != 'volfraction': 
    206220                self.s_model.setParam( name, value) 
    207              
     221 
    208222 
    209223        #self._setParamHelper( name, value) 
    210          
     224 
    211225    def _setParamHelper(self, name, value): 
    212226        """ 
     
    228242                    self.params[item] = value 
    229243                    return 
    230              
     244 
    231245        raise ValueError, "Model does not contain parameter %s" % name 
    232               
    233     
     246 
     247 
    234248    def _set_fixed_params(self): 
    235249        """ 
     
    240254 
    241255        self.fixed.sort() 
    242                  
    243                  
     256 
     257 
    244258    def run(self, x = 0.0): 
    245         """  
     259        """ 
    246260        Evaluate the model 
    247          
     261 
    248262        :param x: input q-value (float or [float, float] as [r, theta]) 
    249263        :return: (scattering function value) 
    250264        """ 
    251265        # set effective radius and scaling factor before run 
    252         self._set_effect_radius() 
     266        self._set_radius_effective() 
    253267        self._set_scale_factor() 
    254268        return self.params['scale_factor'] * self.p_model.run(x) * \ 
    255                             self.s_model.run(x) 
     269                            self.s_model.run(x) + self.params['background'] 
    256270 
    257271    def runXY(self, x = 0.0): 
    258         """  
     272        """ 
    259273        Evaluate the model 
    260          
     274 
    261275        :param x: input q-value (float or [float, float] as [qx, qy]) 
    262276        :return: scattering function value 
    263         """   
     277        """ 
    264278        # set effective radius and scaling factor before run 
    265         self._set_effect_radius() 
     279        self._set_radius_effective() 
    266280        self._set_scale_factor() 
    267281        out = self.params['scale_factor'] * self.p_model.runXY(x) * \ 
    268                         self.s_model.runXY(x) 
     282                        self.s_model.runXY(x) + self.params['background'] 
    269283        return out 
    270      
    271     ## Now (May27,10) directly uses the model eval function  
     284 
     285    ## Now (May27,10) directly uses the model eval function 
    272286    ## instead of the for-loop in Base Component. 
    273287    def evalDistribution(self, x = []): 
    274         """  
     288        """ 
    275289        Evaluate the model in cartesian coordinates 
    276          
     290 
    277291        :param x: input q[], or [qx[], qy[]] 
    278292        :return: scattering function P(q[]) 
    279293        """ 
    280294        # set effective radius and scaling factor before run 
    281         self._set_effect_radius() 
     295        self._set_radius_effective() 
    282296        self._set_scale_factor() 
    283297        out = self.params['scale_factor'] * self.p_model.evalDistribution(x) * \ 
    284                         self.s_model.evalDistribution(x) 
     298                        self.s_model.evalDistribution(x) + self.params['background'] 
    285299        return out 
    286300 
     
    288302        """ 
    289303        Set the dispersion object for a model parameter 
    290          
     304 
    291305        :param parameter: name of the parameter [string] 
    292306        :dispersion: dispersion object of type DispersionModel 
     
    299313            return value 
    300314        except: 
    301             raise  
     315            raise 
    302316 
    303317    def fill_description(self, p_model, s_model): 
     
    306320        """ 
    307321        description = "" 
    308         description += "Note:1) The effect_radius (effective radius) of %s \n"%\ 
     322        description += "Note:1) The radius_effective (effective radius) of %s \n"%\ 
    309323                                                                (s_model.name) 
    310324        description += "             is automatically calculated " 
     
    318332        description += "        for details of individual models." 
    319333        self.description += description 
    320      
Note: See TracChangeset for help on using the changeset viewer.