Changeset 6dc78e4 in sasmodels
- Timestamp:
- Aug 17, 2016 5:12:51 PM (8 years ago)
- Branches:
- master, core_shell_microgels, costrafo411, magnetic_model, release_v0.94, release_v0.95, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
- Children:
- deb854f, 300a2f7
- Parents:
- 6b7e2f7
- Location:
- sasmodels
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/convert.py
r40a87fa r6dc78e4 180 180 composition_type, parts = model_info.composition 181 181 if composition_type == 'product': 182 oldpars= {'scale':'scale_factor'}183 oldpars.update(_get_old_pars(parts[0]))184 oldpars.update(_get_old_pars(parts[1]))182 translation = {'scale':'scale_factor'} 183 translation.update(_get_translation_table(parts[0])) 184 translation.update(_get_translation_table(parts[1])) 185 185 else: 186 186 raise NotImplementedError("cannot convert to sasview sum") 187 187 else: 188 188 translation = _get_translation_table(model_info) 189 190 189 oldpars = _revert_pars(_unscale_sld(model_info, pars), translation) 190 oldpars = _trim_vectors(model_info, pars, oldpars) 191 191 192 192 # Make sure the control parameter is an integer -
sasmodels/details.py
r725ee36 r6dc78e4 177 177 178 178 def make_details(model_info, length, offset, num_weights): 179 # type: (ModelInfo, np.ndarray, np.ndarray, int) -> CallDetails 179 180 """ 180 181 Return a :class:`CallDetails` object for a polydisperse calculation … … 186 187 array. 187 188 """ 188 # type: (ModelInfo, np.ndarray, np.ndarray, int) -> CallDetails189 189 #pars = model_info.parameters.call_parameters[2:model_info.parameters.npars+2] 190 190 #print(", ".join(str(i)+"-"+p.id for i,p in enumerate(pars))) … … 275 275 """ 276 276 value, weight = zip(*pars) 277 weight = [w if welse [1.] for w in weight]277 #weight = [w if len(w)>0 else [1.] for w in weight] 278 278 weight = np.vstack([v.flatten() for v in meshgrid(*weight)]) 279 279 weight = np.prod(weight, axis=0) -
sasmodels/mixture.py
rfe496dd r6dc78e4 116 116 self.kernels = kernels 117 117 self.dtype = self.kernels[0].dtype 118 self.results = [] # type: List[np.ndarray] 118 119 119 120 def __call__(self, call_details, values, cutoff, magnetic): … … 122 123 total = 0.0 123 124 # remember the parts for plotting later 124 self.results = [] 125 self.results = [] # type: List[np.ndarray] 125 126 offset = 2 # skip scale & background 126 127 parts = MixtureParts(self.info, self.kernels, call_details, values) -
sasmodels/product.py
r9eb3632 r6dc78e4 9 9 10 10 To use it, first load form factor P and structure factor S, then create 11 * ProductModel(P, S)*.11 *make_product_info(P, S)*. 12 12 """ 13 from __future__ import print_function, division 14 15 from copy import copy 13 16 import numpy as np # type: ignore 14 17 15 from .modelinfo import suffix_parameter, ParameterTable, ModelInfo18 from .modelinfo import Parameter, ParameterTable, ModelInfo 16 19 from .kernel import KernelModel, Kernel 17 from .details import dispersion_mesh20 from .details import make_details, dispersion_mesh 18 21 19 22 try: 20 23 from typing import Tuple 21 from .modelinfo import ParameterSet22 from .details import CallDetails23 24 except ImportError: 24 25 pass … … 26 27 # TODO: make estimates available to constraints 27 28 #ESTIMATED_PARAMETERS = [ 28 # ["est_ effect_radius", "A", 0.0, [0, np.inf], "", "Estimated effective radius"],29 # ["est_radius_effective", "A", 0.0, [0, np.inf], "", "Estimated effective radius"], 29 30 # ["est_volume_ratio", "", 1.0, [0, np.inf], "", "Estimated volume ratio"], 30 31 #] 32 33 ER_ID = "radius_effective" 34 VF_ID = "volfraction" 31 35 32 36 # TODO: core_shell_sphere model has suppressed the volume ratio calculation … … 37 41 Create info block for product model. 38 42 """ 43 # Make sure effective radius is the first parameter and 44 # make sure volume fraction is the second parameter of the 45 # structure factor calculator. Structure factors should not 46 # have any magnetic parameters 47 assert(s_info.parameters.kernel_parameters[0].id == ER_ID) 48 assert(s_info.parameters.kernel_parameters[1].id == VF_ID) 49 assert(s_info.parameters.magnetism_index == []) 39 50 p_id, p_name, p_pars = p_info.id, p_info.name, p_info.parameters 40 51 s_id, s_name, s_pars = s_info.id, s_info.name, s_info.parameters … … 44 55 if p_set & s_set: 45 56 # there is some overlap between the parameter names; tag the 46 # overlapping S parameters with name_S 47 s_list = [(suffix_parameter(par, "_S") if par.id in p_set else par)48 for par in s_pars.kernel_parameters]49 combined_pars = p_pars.kernel_parameters + s_list57 # overlapping S parameters with name_S. 58 # Skip the first parameter of s, which is effective radius 59 s_list = [(suffix_parameter(par) if par.id in p_set else par) 60 for par in s_pars.kernel_parameters[1:]] 50 61 else: 51 combined_pars = p_pars.kernel_parameters + s_pars.kernel_parameters 62 # Skip the first parameter of s, which is effective radius 63 s_list = s_pars.kernel_parameters[1:] 64 translate_name = dict((old.id, new.id) for old, new 65 in zip(s_pars.kernel_parameters[1:], s_list)) 66 demo = {} 67 demo.update((k, v) for k, v in p_info.demo.items() 68 if k not in ("background", "scale")) 69 demo.update((translate_name[k], v) for k, v in s_info.demo.items() 70 if k not in ("background", "scale") and not k.startswith(ER_ID)) 71 combined_pars = p_pars.kernel_parameters + s_list 52 72 parameters = ParameterTable(combined_pars) 73 parameters.max_pd = p_pars.max_pd + s_pars.max_pd 53 74 54 75 model_info = ModelInfo() 55 76 model_info.id = '*'.join((p_id, s_id)) 56 model_info.name = ' X'.join((p_name, s_name))77 model_info.name = '*'.join((p_name, s_name)) 57 78 model_info.filename = None 58 79 model_info.title = 'Product of %s and %s'%(p_name, s_name) … … 67 88 #model_info.source = [] 68 89 # Iq, Iqxy, form_volume, ER, VR and sesans 90 # Remember the component info blocks so we can build the model 69 91 model_info.composition = ('product', [p_info, s_info]) 92 model_info.demo = {} 70 93 return model_info 94 95 def suffix_parameter(par, suffix): 96 par = copy(par) 97 par.name = par.name + " S" 98 par.id = par.id + "_S" 99 return par 71 100 72 101 class ProductModel(KernelModel): … … 77 106 self.S = S 78 107 79 def __call__(self, q_vectors):108 def make_kernel(self, q_vectors): 80 109 # type: (List[np.ndarray]) -> Kernel 81 110 # Note: may be sending the q_vectors to the GPU twice even though they … … 104 133 self.p_kernel = p_kernel 105 134 self.s_kernel = s_kernel 106 107 def __call__(self, details, weights, values, cutoff): 108 # type: (CallDetails, np.ndarray, np.ndarray, float) -> np.ndarray 109 effect_radius, vol_ratio = call_ER_VR(self.p_kernel.info, vol_pars) 110 111 p_details, s_details = details.parts 112 p_res = self.p_kernel(p_details, weights, values, cutoff) 113 s_res = self.s_kernel(s_details, weights, values, cutoff) 114 #print s_fixed, s_pd, p_fixed, p_pd 115 116 return values[0]*(p_res*s_res) + values[1] 135 self.dtype = p_kernel.dtype 136 self.results = [] # type: List[np.ndarray] 137 138 def __call__(self, call_details, values, cutoff, magnetic): 139 # type: (CallDetails, np.ndarray, float, bool) -> np.ndarray 140 p_info, s_info = self.info.composition[1] 141 142 # if there are magnetic parameters, they will only be on the 143 # form factor P, not the structure factor S. 144 nmagnetic = len(self.info.parameters.magnetism_index) 145 if nmagnetic: 146 spin_index = self.info.parameters.npars + 2 147 magnetism = values[spin_index: spin_index+3+3*nmagnetic] 148 else: 149 magnetism = [] 150 nvalues = self.info.parameters.nvalues 151 nweights = call_details.num_weights 152 weights = values[nvalues:nvalues + 2*nweights] 153 154 # Construct the calling parameters for P. 155 p_npars = p_info.parameters.npars 156 p_length = call_details.length[:p_npars] 157 p_offset = call_details.offset[:p_npars] 158 p_details = make_details(p_info, p_length, p_offset, nweights) 159 # Set p scale to the volume fraction in s, which is the first of the 160 # 'S' parameters in the parameter list, or 2+np in 0-origin. 161 volfrac = values[2+p_npars] 162 p_values = [[volfrac, 0.0], values[2:2+p_npars], magnetism, weights] 163 spacer = (32 - sum(len(v) for v in p_values)%32)%32 164 p_values.append([0.]*spacer) 165 p_values = np.hstack(p_values).astype(self.p_kernel.dtype) 166 167 # Call ER and VR for P since these are needed for S. 168 p_er, p_vr = calc_er_vr(p_info, p_details, p_values) 169 s_vr = (volfrac/p_vr if p_vr != 0. else volfrac) 170 #print("volfrac:%g p_er:%g p_vr:%g s_vr:%g"%(volfrac,p_er,p_vr,s_vr)) 171 172 # Construct the calling parameters for S. 173 # The effective radius is not in the combined parameter list, so 174 # the number of 'S' parameters is one less than expected. The 175 # computed effective radius needs to be added into the weights 176 # vector, especially since it is a polydisperse parameter in the 177 # stand-alone structure factor models. We will added it at the 178 # end so the remaining offsets don't need to change. 179 s_npars = s_info.parameters.npars-1 180 s_length = call_details.length[p_npars:p_npars+s_npars] 181 s_offset = call_details.offset[p_npars:p_npars+s_npars] 182 s_length = np.hstack((1, s_length)) 183 s_offset = np.hstack((nweights, s_offset)) 184 s_details = make_details(s_info, s_length, s_offset, nweights+1) 185 v, w = weights[:nweights], weights[nweights:] 186 s_values = [[1., 0., p_er, s_vr], 187 # er and vf already included, so start one past the 188 # volfrac parameter, and go two less than the number 189 # of S parameters. 190 values[2+p_npars+2:2+p_npars+s_npars-1], 191 # no magnetism parameters to include for S 192 # add er into the (value, weights) pairs 193 v, [p_er], w, [1.0]] 194 spacer = (32 - sum(len(v) for v in s_values)%32)%32 195 s_values.append([0.]*spacer) 196 s_values = np.hstack(s_values).astype(self.s_kernel.dtype) 197 198 # Call the kernels 199 p_result = self.p_kernel(p_details, p_values, cutoff, magnetic) 200 s_result = self.s_kernel(s_details, s_values, cutoff, False) 201 202 #call_details.show(values) 203 #print("values", values) 204 #p_details.show(p_values) 205 #print("=>", p_result) 206 #print("p val", s_values) 207 #s_details.show(s_values) 208 #print("=>", s_result) 209 210 # remember the parts for plotting later 211 self.results = [p_result, s_result] 212 213 #import pylab as plt 214 #plt.subplot(211); plt.loglog(self.p_kernel.q_input.q, p_result, '-') 215 #plt.subplot(212); plt.loglog(self.s_kernel.q_input.q, s_result, '-') 216 #plt.figure() 217 218 return values[0]*(p_result*s_result) + values[1] 117 219 118 220 def release(self): … … 121 223 self.s_kernel.release() 122 224 123 def call_ER_VR(model_info, pars): 124 """ 125 Return effect radius and volume ratio for the model.126 """ 225 226 def calc_er_vr(model_info, call_details, values): 227 # type: (ModelInfo, ParameterSet) -> Tuple[float, float] 228 127 229 if model_info.ER is None and model_info.VR is None: 128 230 return 1.0, 1.0 129 231 130 value, weight = _vol_pars(model_info, pars) 232 nvalues = model_info.parameters.nvalues 233 value = values[nvalues:nvalues + call_details.num_weights] 234 weight = values[nvalues + call_details.num_weights: nvalues + 2*call_details.num_weights] 235 npars = model_info.parameters.npars 236 pairs = [(value[offset:offset+length], weight[offset:offset+length]) 237 for p, offset, length 238 in zip(model_info.parameters.call_parameters[2:2+npars], 239 call_details.offset, 240 call_details.length) 241 if p.type == 'volume'] 242 value, weight = dispersion_mesh(model_info, pairs) 131 243 132 244 if model_info.ER is not None: 133 245 individual_radii = model_info.ER(*value) 134 effect_radius= np.sum(weight*individual_radii) / np.sum(weight)246 radius_effective = np.sum(weight*individual_radii) / np.sum(weight) 135 247 else: 136 effect_radius= 1.0248 radius_effective = 1.0 137 249 138 250 if model_info.VR is not None: … … 142 254 volume_ratio = 1.0 143 255 144 return effect_radius, volume_ratio 145 146 def _vol_pars(model_info, pars): 147 # type: (ModelInfo, ParameterSet) -> Tuple[np.ndarray, np.ndarray] 148 vol_pars = [get_weights(p, pars) 149 for p in model_info.parameters.call_parameters 150 if p.type == 'volume'] 151 value, weight = dispersion_mesh(model_info, vol_pars) 152 return value, weight 153 256 return radius_effective, volume_ratio
Note: See TracChangeset
for help on using the changeset viewer.