Changeset 6e7ba14 in sasmodels for sasmodels/product.py
- Timestamp:
- Aug 20, 2018 8:52:21 AM (6 years ago)
- Branches:
- master, core_shell_microgels, magnetic_model, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
- Children:
- aa44a6a
- Parents:
- bad3093
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/product.py
r6d90684 r6e7ba14 35 35 #] 36 36 37 ER_ID = "radius_effective" 38 VF_ID = "volfraction" 39 BETA_DEFINITION = ("beta_mode", "", 0, [["P*S"],["P*(1+beta*(S-1))"]], "", 40 "Structure factor dispersion calculation mode") 37 RADIUS_ID = "radius_effective" 38 VOLFRAC_ID = "volfraction" 39 def make_extra_pars(p_info): 40 pars = [] 41 if p_info.have_Fq: 42 par = Parameter("structure_factor_mode", "", 0, [["P*S","P*(1+beta*(S-1))"]], "", 43 "Structure factor calculation") 44 pars.append(par) 45 if p_info.effective_radius_type is not None: 46 par = Parameter("radius_effective_mode", "", 0, 47 [["unconstrained"] + p_info.effective_radius_type], 48 "", "Effective radius calculation") 49 pars.append(par) 50 return pars 41 51 42 52 # TODO: core_shell_sphere model has suppressed the volume ratio calculation … … 52 62 # have any magnetic parameters 53 63 if not len(s_info.parameters.kernel_parameters) >= 2: 54 raise TypeError("S needs {} and {} as its first parameters".format( ER_ID, VF_ID))55 if not s_info.parameters.kernel_parameters[0].id == ER_ID:56 raise TypeError("S needs {} as first parameter".format( ER_ID))57 if not s_info.parameters.kernel_parameters[1].id == V F_ID:58 raise TypeError("S needs {} as second parameter".format(V F_ID))64 raise TypeError("S needs {} and {} as its first parameters".format(RADIUS_ID, VOLFRAC_ID)) 65 if not s_info.parameters.kernel_parameters[0].id == RADIUS_ID: 66 raise TypeError("S needs {} as first parameter".format(RADIUS_ID)) 67 if not s_info.parameters.kernel_parameters[1].id == VOLFRAC_ID: 68 raise TypeError("S needs {} as second parameter".format(VOLFRAC_ID)) 59 69 if not s_info.parameters.magnetism_index == []: 60 70 raise TypeError("S should not have SLD parameters") … … 62 72 s_id, s_name, s_pars = s_info.id, s_info.name, s_info.parameters 63 73 64 # Create list of parameters for the combined model. Skip the first 65 # parameter of S, which we verified above is effective radius. If there 74 # Create list of parameters for the combined model. If there 66 75 # are any names in P that overlap with those in S, modify the name in S 67 76 # to distinguish it. 68 77 p_set = set(p.id for p in p_pars.kernel_parameters) 69 78 s_list = [(_tag_parameter(par) if par.id in p_set else par) 70 for par in s_pars.kernel_parameters [1:]]79 for par in s_pars.kernel_parameters] 71 80 # Check if still a collision after renaming. This could happen if for 72 81 # example S has volfrac and P has both volfrac and volfrac_S. … … 74 83 raise TypeError("name collision: P has P.name and P.name_S while S has S.name") 75 84 85 # make sure effective radius is not a polydisperse parameter in product 86 s_list[0] = copy(s_list[0]) 87 s_list[0].polydisperse = False 88 76 89 translate_name = dict((old.id, new.id) for old, new 77 in zip(s_pars.kernel_parameters[1:], s_list)) 78 beta = [Parameter(*BETA_DEFINITION)] if p_info.have_Fq else [] 79 combined_pars = p_pars.kernel_parameters + s_list + beta 90 in zip(s_pars.kernel_parameters, s_list)) 91 combined_pars = p_pars.kernel_parameters + s_list + make_extra_pars(p_info) 80 92 parameters = ParameterTable(combined_pars) 81 93 parameters.max_pd = p_pars.max_pd + s_pars.max_pd 82 94 def random(): 83 95 combined_pars = p_info.random() 84 s_names = set(par.id for par in s_pars.kernel_parameters [1:])96 s_names = set(par.id for par in s_pars.kernel_parameters) 85 97 combined_pars.update((translate_name[k], v) 86 98 for k, v in s_info.random().items() … … 225 237 p_values = np.hstack(p_values).astype(self.p_kernel.dtype) 226 238 227 # Call ER and VR for P since these are needed for S.228 p_er, p_vr = calc_er_vr(p_info, p_details, p_values)229 s_vr = (volfrac/p_vr if p_vr != 0. else volfrac)230 #print("volfrac:%g p_er:%g p_vr:%g s_vr:%g"%(volfrac,p_er,p_vr,s_vr))231 232 239 # Construct the calling parameters for S. 233 # The effective radius is not in the combined parameter list, so 234 # the number of 'S' parameters is one less than expected. The 235 # computed effective radius needs to be added into the weights 236 # vector, especially since it is a polydisperse parameter in the 237 # stand-alone structure factor models. We will added it at the 238 # end so the remaining offsets don't need to change. 239 s_npars = s_info.parameters.npars-1 240 s_npars = s_info.parameters.npars 240 241 s_length = call_details.length[p_npars:p_npars+s_npars] 241 242 s_offset = call_details.offset[p_npars:p_npars+s_npars] … … 243 244 s_offset = np.hstack((nweights, s_offset)) 244 245 s_details = make_details(s_info, s_length, s_offset, nweights+1) 245 v, w = weights[:nweights], weights[nweights:]246 246 s_values = [ 247 # scale=1, background=0, radius_effective=p_er, volfraction=s_vr 248 [1., 0., p_er, s_vr], 249 # structure factor parameters start after scale, background and 250 # all the form factor parameters. Skip the volfraction parameter 251 # as well, since it is computed elsewhere, and go to the end of the 252 # parameter list. 253 values[2+p_npars+1:2+p_npars+s_npars], 254 # no magnetism parameters to include for S 255 # add er into the (value, weights) pairs 256 v, [p_er], w, [1.0] 247 # scale=1, background=0, 248 [1., 0.], 249 values[2+p_npars:2+p_npars+s_npars], 250 weights, 257 251 ] 258 252 spacer = (32 - sum(len(v) for v in s_values)%32)%32 … … 261 255 262 256 # beta mode is the first parameter after the structure factor pars 263 beta_index = 2+p_npars+s_npars 264 beta_mode = values[beta_index] 257 extra_offset = 2+p_npars+s_npars 258 if p_info.have_Fq: 259 beta_mode = values[extra_offset] 260 extra_offset += 1 261 else: 262 beta_mode = 0 263 if p_info.effective_radius_type is not None: 264 effective_radius_type = values[extra_offset] 265 extra_offset += 1 266 else: 267 effective_radius_type = 0 265 268 266 269 # Call the kernels 267 s_result = self.s_kernel.Iq(s_details, s_values, cutoff, False)268 270 scale, background = values[0], values[1] 269 271 if beta_mode: 270 F1, F2, volume_avg = self.p_kernel.beta(p_details, p_values, cutoff, magnetic) 272 F1, F2, volume_avg, effective_radius = self.p_kernel.beta( 273 p_details, p_values, cutoff, magnetic, effective_radius_type) 274 if effective_radius_type > 0: 275 s_values[2] = s_values[2+s_npars+s_offset[0]] = effective_radius 276 s_result = self.s_kernel.Iq(s_details, s_values, cutoff, False) 271 277 combined_scale = scale*volfrac/volume_avg 272 278 # Define lazy results based on intermediate values. … … 297 303 final_result = combined_scale*(F2 + (F1**2)*(s_result - 1)) + background 298 304 else: 299 p_result = self.p_kernel.Iq(p_details, p_values, cutoff, magnetic) 305 p_result, effective_radius = self.p_kernel.Pq_Reff( 306 p_details, p_values, cutoff, magnetic, effective_radius_type) 307 if effective_radius_type > 0: 308 s_values[2] = s_values[2+s_npars+s_offset[0]] = effective_radius 309 s_result = self.s_kernel.Iq(s_details, s_values, cutoff, False) 300 310 # remember the parts for plotting later 301 311 self.results = [p_result, s_result]
Note: See TracChangeset
for help on using the changeset viewer.