Changeset 8803a38 in sasmodels
- Timestamp:
- Dec 13, 2018 11:08:39 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:
- f9014c7
- Parents:
- 2c4a190 (diff), 899e050 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/guide/plugin.rst
r57c609b r9d8a027 272 272 structure factor to account for interactions between particles. See 273 273 `Form_Factors`_ for more details. 274 275 **model_info = ...** lets you define a model directly, for example, by 276 loading and modifying existing models. This is done implicitly by 277 :func:`sasmodels.core.load_model_info`, which can create a mixture model 278 from a pair of existing models. For example:: 279 280 from sasmodels.core import load_model_info 281 model_info = load_model_info('sphere+cylinder') 282 283 See :class:`sasmodels.modelinfo.ModelInfo` for details about the model 284 attributes that are defined. 274 285 275 286 Model Parameters -
sasmodels/sasview_model.py
rce1eed5 ra4f1a73 25 25 from . import core 26 26 from . import custom 27 from . import kernelcl 27 28 from . import product 28 29 from . import generate … … 30 31 from . import modelinfo 31 32 from .details import make_kernel_args, dispersion_mesh 33 from .kernelcl import reset_environment 32 34 33 35 # pylint: disable=unused-import … … 68 70 #: has changed since we last reloaded. 69 71 _CACHED_MODULE = {} # type: Dict[str, "module"] 72 73 def reset_environment(): 74 # type: () -> None 75 """ 76 Clear the compute engine context so that the GUI can change devices. 77 78 This removes all compiled kernels, even those that are active on fit 79 pages, but they will be restored the next time they are needed. 80 """ 81 kernelcl.reset_environment() 82 for model in MODELS.values(): 83 model._model = None 70 84 71 85 def find_model(modelname): … … 680 694 def _calculate_Iq(self, qx, qy=None): 681 695 if self._model is None: 682 self._model = core.build_model(self._model_info) 696 # Only need one copy of the compiled kernel regardless of how many 697 # times it is used, so store it in the class. Also, to reset the 698 # compute engine, need to clear out all existing compiled kernels, 699 # which is much easier to do if we store them in the class. 700 self.__class__._model = core.build_model(self._model_info) 683 701 if qy is not None: 684 702 q_vectors = [np.asarray(qx), np.asarray(qy)] -
example/multiscatfit.py
r49d1f8b8 r2c4a190 15 15 16 16 # Show the model without fitting 17 PYTHONPATH=..:../ explore:../../bumps:../../sasview/src python multiscatfit.py17 PYTHONPATH=..:../../bumps:../../sasview/src python multiscatfit.py 18 18 19 19 # Run the fit 20 PYTHONPATH=..:../ explore:../../bumps:../../sasview/src ../../bumps/run.py \20 PYTHONPATH=..:../../bumps:../../sasview/src ../../bumps/run.py \ 21 21 multiscatfit.py --store=/tmp/t1 22 22 … … 55 55 ) 56 56 57 # Tie the model to the data 58 M = Experiment(data=data, model=model) 59 60 # Stack mulitple scattering on top of the existing resolution function. 61 M.resolution = MultipleScattering(resolution=M.resolution, probability=0.) 62 57 63 # SET THE FITTING PARAMETERS 58 64 model.radius_polar.range(15, 3000) … … 65 71 model.scale.range(0, 0.1) 66 72 67 # Mulitple scattering probability parameter 68 # HACK: the probability is stuffed in as an extra parameter to the experiment. 69 probability = Parameter(name="probability", value=0.0) 70 probability.range(0.0, 0.9) 73 # The multiple scattering probability parameter is in the resolution function 74 # instead of the scattering function, so access it through M.resolution 75 M.scattering_probability.range(0.0, 0.9) 71 76 72 M = Experiment(data=data, model=model, extra_pars={'probability': probability}) 73 74 # Stack mulitple scattering on top of the existing resolution function. 75 # Because resolution functions in sasview don't have fitting parameters, 76 # we instead allow the multiple scattering calculator to take a function 77 # instead of a probability. This function returns the current value of 78 # the parameter. ** THIS IS TEMPORARY ** when multiple scattering is 79 # properly integrated into sasmodels and sasview, its fittable parameter 80 # will be treated like the model parameters. 81 M.resolution = MultipleScattering(resolution=M.resolution, 82 probability=lambda: probability.value, 83 ) 84 M._kernel_inputs = M.resolution.q_calc 77 # Let bumps know that we are fitting this experiment 85 78 problem = FitProblem(M) 86 79 -
sasmodels/bumps_model.py
r49d1f8b8 r2c4a190 35 35 # when bumps is not on the path. 36 36 from bumps.names import Parameter # type: ignore 37 from bumps.parameter import Reference # type: ignore 37 38 except ImportError: 38 39 pass … … 139 140 def __init__(self, data, model, cutoff=1e-5, name=None, extra_pars=None): 140 141 # type: (Data, Model, float) -> None 142 # Allow resolution function to define fittable parameters. We do this 143 # by creating reference parameters within the resolution object rather 144 # than modifying the object itself to use bumps parameters. We need 145 # to reset the parameters each time the object has changed. These 146 # additional parameters need to be returned from the fitting engine. 147 # To make them available to the user, they are added as top-level 148 # attributes to the experiment object. The only change to the 149 # resolution function is that it needs an optional 'fittable' attribute 150 # which maps the internal name to the user visible name for the 151 # for the parameter. 152 self._resolution = None 153 self._resolution_pars = {} 141 154 # remember inputs so we can inspect from outside 142 155 self.name = data.filename if name is None else name … … 145 158 self._interpret_data(data, model.sasmodel) 146 159 self._cache = {} 160 # CRUFT: no longer need extra parameters 161 # Multiple scattering probability is now retrieved directly from the 162 # multiple scattering resolution function. 147 163 self.extra_pars = extra_pars 148 164 … … 162 178 return len(self.Iq) 163 179 180 @property 181 def resolution(self): 182 return self._resolution 183 184 @resolution.setter 185 def resolution(self, value): 186 self._resolution = value 187 188 # Remove old resolution fitting parameters from experiment 189 for name in self._resolution_pars: 190 delattr(self, name) 191 192 # Create new resolution fitting parameters 193 res_pars = getattr(self._resolution, 'fittable', {}) 194 self._resolution_pars = { 195 name: Reference(self._resolution, refname, name=name) 196 for refname, name in res_pars.items() 197 } 198 199 # Add new resolution fitting parameters as experiment attributes 200 for name, ref in self._resolution_pars.items(): 201 setattr(self, name, ref) 202 164 203 def parameters(self): 165 204 # type: () -> Dict[str, Parameter] … … 168 207 """ 169 208 pars = self.model.parameters() 170 if self.extra_pars :209 if self.extra_pars is not None: 171 210 pars.update(self.extra_pars) 211 pars.update(self._resolution_pars) 172 212 return pars 173 213 -
sasmodels/direct_model.py
r7b9e4dd r2c4a190 242 242 else: 243 243 Iq, dIq = None, None 244 #self._theory = np.zeros_like(q)245 q_vectors = [res.q_calc]246 244 elif self.data_type == 'Iqxy': 247 245 #if not model.info.parameters.has_2d: … … 260 258 res = resolution2d.Pinhole2D(data=data, index=index, 261 259 nsigma=3.0, accuracy=accuracy) 262 #self._theory = np.zeros_like(self.Iq)263 q_vectors = res.q_calc264 260 elif self.data_type == 'Iq': 265 261 index = (data.x >= data.qmin) & (data.x <= data.qmax) … … 286 282 else: 287 283 res = resolution.Perfect1D(data.x[index]) 288 289 #self._theory = np.zeros_like(self.Iq)290 q_vectors = [res.q_calc]291 284 elif self.data_type == 'Iq-oriented': 292 285 index = (data.x >= data.qmin) & (data.x <= data.qmax) … … 304 297 qx_width=data.dxw[index], 305 298 qy_width=data.dxl[index]) 306 q_vectors = res.q_calc307 299 else: 308 300 raise ValueError("Unknown data type") # never gets here … … 310 302 # Remember function inputs so we can delay loading the function and 311 303 # so we can save/restore state 312 self._kernel_inputs = q_vectors313 304 self._kernel = None 314 305 self.Iq, self.dIq, self.index = Iq, dIq, index … … 347 338 # type: (ParameterSet, float) -> np.ndarray 348 339 if self._kernel is None: 349 self._kernel = self._model.make_kernel(self._kernel_inputs) 340 # TODO: change interfaces so that resolution returns kernel inputs 341 # Maybe have resolution always return a tuple, or maybe have 342 # make_kernel accept either an ndarray or a pair of ndarrays. 343 kernel_inputs = self.resolution.q_calc 344 if isinstance(kernel_inputs, np.ndarray): 345 kernel_inputs = (kernel_inputs,) 346 self._kernel = self._model.make_kernel(kernel_inputs) 350 347 351 348 # Need to pull background out of resolution for multiple scattering -
sasmodels/multiscat.py
rb3703f5 r2c4a190 342 342 343 343 *probability* is related to the expected number of scattering 344 events in the sample $\lambda$ as $p = 1 = e^{-\lambda}$. As a 345 hack to allow probability to be a fitted parameter, the "value" 346 can be a function that takes no parameters and returns the current 347 value of the probability. *coverage* determines how many scattering 348 steps to consider. The default is 0.99, which sets $n$ such that 349 $1 \ldots n$ covers 99% of the Poisson probability mass function. 344 events in the sample $\lambda$ as $p = 1 - e^{-\lambda}$. 345 *coverage* determines how many scattering steps to consider. The 346 default is 0.99, which sets $n$ such that $1 \ldots n$ covers 99% 347 of the Poisson probability mass function. 350 348 351 349 *is2d* is True then 2D scattering is used, otherwise it accepts … … 399 397 self.qmin = qmin 400 398 self.nq = nq 401 self.probability = probability399 self.probability = 0. if probability is None else probability 402 400 self.coverage = coverage 403 401 self.is2d = is2d … … 456 454 self.Iqxy = None # type: np.ndarray 457 455 456 # Label probability as a fittable parameter, and give its external name 457 # Note that the external name must be a valid python identifier, since 458 # is will be set as an experiment attribute. 459 self.fittable = {'probability': 'scattering_probability'} 460 458 461 def apply(self, theory): 459 462 if self.is2d: … … 463 466 Iq_calc = Iq_calc.reshape(self.nq, self.nq) 464 467 468 # CRUFT: don't need probability as a function anymore 465 469 probability = self.probability() if callable(self.probability) else self.probability 466 470 coverage = self.coverage
Note: See TracChangeset
for help on using the changeset viewer.