Changeset fb9a3b6 in sasmodels
- Timestamp:
- Aug 31, 2017 10:07:59 AM (7 years ago)
- Branches:
- master, core_shell_microgels, costrafo411, magnetic_model, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
- Children:
- bcdd6c9
- Parents:
- 573ffab
- Location:
- sasmodels
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/core.py
r2e66ef5 rfb9a3b6 126 126 127 127 128 def load_model_info(model_name ):128 def load_model_info(model_name, force_mixture=False): 129 129 # type: (str) -> modelinfo.ModelInfo 130 130 """ … … 134 134 such as sphere*hardsphere or sphere+cylinder. 135 135 136 *force_mixture* if true, MixtureModel will be used for combining models. 137 Otherwise either MixtureModel will be used for addition and ProductModel 138 will be used for multiplication 139 136 140 This returns a handle to the module defining the model. This can be 137 141 used with functions in generate to build the docs or extract model info. … … 139 143 parts = model_name.split('+') 140 144 if len(parts) > 1: 145 # Always use MixtureModel for addition 141 146 model_info_list = [load_model_info(p) for p in parts] 142 147 return mixture.make_mixture_info(model_info_list) … … 144 149 parts = model_name.split('*') 145 150 if len(parts) > 1: 151 if force_mixture: 152 # Use MixtureModel for multiplication if forced 153 model_info_list = [load_model_info(p) for p in parts] 154 return mixture.make_mixture_info(model_info_list, operation='*') 146 155 if len(parts) > 2: 147 156 raise ValueError("use P*S to apply structure factor S to model P") 157 # Use ProductModel 148 158 P_info, Q_info = [load_model_info(p) for p in parts] 149 159 return product.make_product_info(P_info, Q_info) -
sasmodels/mixture.py
r6dc78e4 rfb9a3b6 25 25 pass 26 26 27 def make_mixture_info(parts ):27 def make_mixture_info(parts, operation='+'): 28 28 # type: (List[ModelInfo]) -> ModelInfo 29 29 """ … … 46 46 # to support vector parameters 47 47 prefix = chr(ord('A')+k) + '_' 48 scale = Parameter(prefix+'scale', default=1.0, 49 description="model intensity for " + part.name) 50 combined_pars.append(scale) 48 if operation == '+': 49 # If model is a sum model, each constituent model gets its own scale parameter 50 scale = Parameter(prefix+'scale', default=1.0, 51 description="model intensity for " + part.name) 52 combined_pars.append(scale) 51 53 for p in part.parameters.kernel_parameters: 52 54 p = copy(p) … … 63 65 64 66 model_info = ModelInfo() 65 model_info.id = '+'.join(part.id for part in parts) 66 model_info.name = ' + '.join(part.name for part in parts) 67 model_info.id = operation.join(part.id for part in parts) 68 model_info.operation = operation 69 model_info.name = operation.join(part.name for part in parts) 67 70 model_info.filename = None 68 71 model_info.title = 'Mixture model with ' + model_info.name … … 116 119 self.kernels = kernels 117 120 self.dtype = self.kernels[0].dtype 121 self.operation = model_info.operation 118 122 self.results = [] # type: List[np.ndarray] 119 123 … … 124 128 # remember the parts for plotting later 125 129 self.results = [] # type: List[np.ndarray] 126 offset = 2 # skip scale & background127 130 parts = MixtureParts(self.info, self.kernels, call_details, values) 128 131 for kernel, kernel_details, kernel_values in parts: 129 132 #print("calling kernel", kernel.info.name) 130 133 result = kernel(kernel_details, kernel_values, cutoff, magnetic) 131 #print(kernel.info.name, result) 132 total += result 134 result = np.array(result).astype(kernel.dtype) 135 # print(kernel.info.name, result) 136 if self.operation == '+': 137 total += result 138 elif self.operation == '*': 139 if np.all(total) == 0.0: 140 total = result 141 else: 142 total *= result 133 143 self.results.append(result) 134 144 … … 171 181 172 182 self.part_num += 1 173 self.par_index += info.parameters.npars + 1 183 self.par_index += info.parameters.npars 184 if self.model_info.operation == '+': 185 self.par_index += 1 # Account for each constituent model's scale param 174 186 self.mag_index += 3 * len(info.parameters.magnetism_index) 175 187 … … 182 194 # which includes the initial scale and background parameters. 183 195 # We want the index into the weight length/offset for each parameter. 184 # Exclude the initial scale and background, so subtract two, but each 185 # component has its own scale factor which we need to skip when 186 # constructing the details for the kernel, so add one, giving a 187 # net subtract one. 188 index = slice(par_index - 1, par_index - 1 + info.parameters.npars) 196 # Exclude the initial scale and background, so subtract two. If we're 197 # building an addition model, each component has its own scale factor 198 # which we need to skip when constructing the details for the kernel, so 199 # add one, giving a net subtract one. 200 diff = 1 if self.model_info.operation == '+' else 2 201 index = slice(par_index - diff, par_index - diff + info.parameters.npars) 189 202 length = full.length[index] 190 203 offset = full.offset[index] … … 196 209 def _part_values(self, info, par_index, mag_index): 197 210 # type: (ModelInfo, int, int) -> np.ndarray 198 #print(info.name, par_index, self.values[par_index:par_index + info.parameters.npars + 1]) 199 scale = self.values[par_index] 200 pars = self.values[par_index + 1:par_index + info.parameters.npars + 1] 211 # Set each constituent model's scale to 1 if this is a multiplication model 212 scale = self.values[par_index] if self.model_info.operation == '+' else 1.0 213 diff = 1 if self.model_info.operation == '+' else 0 # Skip scale if addition model 214 pars = self.values[par_index + diff:par_index + info.parameters.npars + diff] 201 215 nmagnetic = len(info.parameters.magnetism_index) 202 216 if nmagnetic:
Note: See TracChangeset
for help on using the changeset viewer.