Changeset 0656250 in sasmodels for sasmodels/bumps_model.py
- Timestamp:
- Mar 24, 2015 4:24:43 AM (9 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:
- c210c94
- Parents:
- 33d38d5 (diff), 0a33675 (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/bumps_model.py
r33d38d5 r0656250 1 1 """ 2 Sasmodels core.2 Wrap sasmodels for direct use by bumps. 3 3 """ 4 import sys, os 4 5 5 import datetime 6 6 7 from sasmodels import sesans 7 import numpy as np 8 9 from . import sesans 8 10 9 11 # CRUFT python 2.6 10 12 if not hasattr(datetime.timedelta, 'total_seconds'): 11 def delay(dt): return dt.days*86400 + dt.seconds + 1e-6*dt.microseconds 13 def delay(dt): 14 """Return number date-time delta as number seconds""" 15 return dt.days * 86400 + dt.seconds + 1e-6 * dt.microseconds 12 16 else: 13 def delay(dt): return dt.total_seconds() 14 15 import numpy as np 16 17 try: 18 from .kernelcl import load_model as _loader 19 except RuntimeError,exc: 20 import warnings 21 warnings.warn(str(exc)) 22 warnings.warn("OpenCL not available --- using ctypes instead") 23 from .kerneldll import load_model as _loader 24 25 def load_model(modelname, dtype='single'): 26 """ 27 Load model by name. 28 """ 29 sasmodels = __import__('sasmodels.models.'+modelname) 30 module = getattr(sasmodels.models, modelname, None) 31 model = _loader(module, dtype=dtype) 32 return model 17 def delay(dt): 18 """Return number date-time delta as number seconds""" 19 return dt.total_seconds() 33 20 34 21 … … 41 28 """ 42 29 then = datetime.datetime.now() 43 return lambda: delay(datetime.datetime.now() -then)30 return lambda: delay(datetime.datetime.now() - then) 44 31 45 32 … … 52 39 data = loader.load(filename) 53 40 if data is None: 54 raise IOError("Data %r could not be loaded" %filename)41 raise IOError("Data %r could not be loaded" % filename) 55 42 return data 56 43 … … 65 52 from sas.dataloader.data_info import Data1D 66 53 67 Iq = 100 *np.ones_like(q)54 Iq = 100 * np.ones_like(q) 68 55 dIq = np.sqrt(Iq) 69 data = Data1D(q, Iq, dx=0.05 *q, dy=dIq)56 data = Data1D(q, Iq, dx=0.05 * q, dy=dIq) 70 57 data.filename = "fake data" 71 58 data.qmin, data.qmax = q.min(), q.max() … … 85 72 if qy is None: 86 73 qy = qx 87 Qx, Qy = np.meshgrid(qx,qy)88 Qx, Qy = Qx.flatten(), Qy.flatten()89 Iq = 100 *np.ones_like(Qx)74 Qx, Qy = np.meshgrid(qx, qy) 75 Qx, Qy = Qx.flatten(), Qy.flatten() 76 Iq = 100 * np.ones_like(Qx) 90 77 dIq = np.sqrt(Iq) 91 78 mask = np.ones(len(Iq), dtype='bool') … … 100 87 101 88 # 5% dQ/Q resolution 102 data.dqx_data = 0.05 *Qx103 data.dqy_data = 0.05 *Qy89 data.dqx_data = 0.05 * Qx 90 data.dqy_data = 0.05 * Qy 104 91 105 92 detector = Detector() … … 114 101 data.Q_unit = "1/A" 115 102 data.I_unit = "1/cm" 116 data.q_data = np.sqrt(Qx **2 + Qy**2)103 data.q_data = np.sqrt(Qx ** 2 + Qy ** 2) 117 104 data.xaxis("Q_x", "A^{-1}") 118 105 data.yaxis("Q_y", "A^{-1}") … … 129 116 data.mask = Ringcut(0, radius)(data) 130 117 if outer is not None: 131 data.mask += Ringcut(outer, np.inf)(data)118 data.mask += Ringcut(outer, np.inf)(data) 132 119 else: 133 data.mask = (data.x >=radius)120 data.mask = (data.x >= radius) 134 121 if outer is not None: 135 data.mask &= (data.x <outer)122 data.mask &= (data.x < outer) 136 123 137 124 … … 142 129 from sas.dataloader.manipulations import Boxcut 143 130 if half == 'right': 144 data.mask += Boxcut(x_min=-np.inf, x_max=0.0, y_min=-np.inf, y_max=np.inf)(data) 131 data.mask += \ 132 Boxcut(x_min=-np.inf, x_max=0.0, y_min=-np.inf, y_max=np.inf)(data) 145 133 if half == 'left': 146 data.mask += Boxcut(x_min=0.0, x_max=np.inf, y_min=-np.inf, y_max=np.inf)(data) 147 148 149 def set_top(data, max): 150 """ 151 Chop the top off the data, above *max*. 134 data.mask += \ 135 Boxcut(x_min=0.0, x_max=np.inf, y_min=-np.inf, y_max=np.inf)(data) 136 137 138 def set_top(data, cutoff): 139 """ 140 Chop the top off the data, above *cutoff*. 152 141 """ 153 142 from sas.dataloader.manipulations import Boxcut 154 data.mask += Boxcut(x_min=-np.inf, x_max=np.inf, y_min=-np.inf, y_max=max)(data) 155 156 157 def plot_data(data, iq, vmin=None, vmax=None, scale='log'): 143 data.mask += \ 144 Boxcut(x_min=-np.inf, x_max=np.inf, y_min=-np.inf, y_max=cutoff)(data) 145 146 147 def plot_data(data, Iq, vmin=None, vmax=None, view='log'): 158 148 """ 159 149 Plot the target value for the data. This could be the data itself, … … 162 152 *scale* can be 'log' for log scale data, or 'linear'. 163 153 """ 164 from numpy.ma import masked_array , masked154 from numpy.ma import masked_array 165 155 import matplotlib.pyplot as plt 166 156 if hasattr(data, 'qx_data'): 167 iq = iq[:] 168 valid = np.isfinite(iq) 169 if scale == 'log': 170 valid[valid] = (iq[valid] > 0) 171 iq[valid] = np.log10(iq[valid]) 172 iq[~valid|data.mask] = 0 173 #plottable = iq 174 plottable = masked_array(iq, ~valid|data.mask) 157 Iq = Iq + 0 158 valid = np.isfinite(Iq) 159 if view == 'log': 160 valid[valid] = (Iq[valid] > 0) 161 Iq[valid] = np.log10(Iq[valid]) 162 elif view == 'q4': 163 Iq[valid] = Iq*(data.qx_data[valid]**2+data.qy_data[valid]**2)**2 164 Iq[~valid | data.mask] = 0 165 #plottable = Iq 166 plottable = masked_array(Iq, ~valid | data.mask) 175 167 xmin, xmax = min(data.qx_data), max(data.qx_data) 176 168 ymin, ymax = min(data.qy_data), max(data.qy_data) 177 if vmin is None: vmin = iq[valid&~data.mask].min() 178 if vmax is None: vmax = iq[valid&~data.mask].max() 179 plt.imshow(plottable.reshape(128,128), 169 try: 170 if vmin is None: vmin = Iq[valid & ~data.mask].min() 171 if vmax is None: vmax = Iq[valid & ~data.mask].max() 172 except: 173 vmin, vmax = 0, 1 174 plt.imshow(plottable.reshape(128, 128), 180 175 interpolation='nearest', aspect=1, origin='upper', 181 176 extent=[xmin, xmax, ymin, ymax], vmin=vmin, vmax=vmax) 182 177 else: # 1D data 183 if scale == 'linear': 184 idx = np.isfinite(iq) 185 plt.plot(data.x[idx], iq[idx]) 186 else: 187 idx = np.isfinite(iq) 188 idx[idx] = (iq[idx]>0) 189 plt.loglog(data.x[idx], iq[idx]) 178 if view == 'linear' or view == 'q4': 179 #idx = np.isfinite(Iq) 180 scale = data.x**4 if view == 'q4' else 1.0 181 plt.plot(data.x, scale*Iq) #, '.') 182 else: 183 # Find the values that are finite and positive 184 idx = np.isfinite(Iq) 185 idx[idx] = (Iq[idx] > 0) 186 Iq[~idx] = np.nan 187 plt.loglog(data.x, Iq) 190 188 191 189 … … 203 201 mdata[mdata <= 0] = masked 204 202 mtheory = masked_array(theory, mdata.mask) 205 mresid = masked_array((theory-data.y)/data.dy, mdata.mask) 206 203 mresid = masked_array((theory - data.y) / data.dy, mdata.mask) 204 205 scale = data.x**4 if view == 'q4' else 1.0 207 206 plt.subplot(121) 208 plt.errorbar(data.x, mdata, yerr=data.dy)209 plt.plot(data.x, mtheory, '-', hold=True)210 plt.yscale( view)207 plt.errorbar(data.x, scale*mdata, yerr=data.dy) 208 plt.plot(data.x, scale*mtheory, '-', hold=True) 209 plt.yscale('linear' if view == 'q4' else view) 211 210 plt.subplot(122) 212 211 plt.plot(data.x, mresid, 'x') 213 #plt.axhline(1, color='black', ls='--',lw=1, hold=True) 214 #plt.axhline(0, color='black', lw=1, hold=True) 215 #plt.axhline(-1, color='black', ls='--',lw=1, hold=True) 216 212 213 # pylint: disable=unused-argument 217 214 def _plot_sesans(data, theory, view): 218 215 import matplotlib.pyplot as plt 219 resid = (theory - data.y) /data.dy216 resid = (theory - data.y) / data.dy 220 217 plt.subplot(121) 221 218 plt.errorbar(data.x, data.y, yerr=data.dy) … … 233 230 """ 234 231 import matplotlib.pyplot as plt 235 resid = (theory -data.data)/data.err_data232 resid = (theory - data.data) / data.err_data 236 233 plt.subplot(131) 237 plot_data(data, data.data, scale=view)234 plot_data(data, data.data, view=view) 238 235 plt.colorbar() 239 236 plt.subplot(132) 240 plot_data(data, theory, scale=view)237 plot_data(data, theory, view=view) 241 238 plt.colorbar() 242 239 plt.subplot(133) 243 plot_data(data, resid, scale='linear')240 plot_data(data, resid, view='linear') 244 241 plt.colorbar() 245 242 … … 250 247 *data* is the data to be fitted. 251 248 252 *model* is the SAS model , e.g., from :func:`gen.opencl_model`.249 *model* is the SAS model from :func:`core.load_model`. 253 250 254 251 *cutoff* is the integration cutoff, which avoids computing the … … 267 264 self.model = model 268 265 self.cutoff = cutoff 269 # TODO if isinstance(data,SESANSData1D)270 266 if hasattr(data, 'lam'): 271 267 self.data_type = 'sesans' … … 280 276 if self.data_type == 'sesans': 281 277 q = sesans.make_q(data.sample.zacceptance, data.Rmax) 282 self.index = slice(None, None)283 self. iq = data.y284 self.d iq = data.dy278 self.index = slice(None, None) 279 self.Iq = data.y 280 self.dIq = data.dy 285 281 self._theory = np.zeros_like(q) 286 282 q_vectors = [q] 287 283 elif self.data_type == 'Iqxy': 288 self.index = (data.mask ==0) & (~np.isnan(data.data))289 self. iq = data.data[self.index]290 self.d iq = data.err_data[self.index]284 self.index = (data.mask == 0) & (~np.isnan(data.data)) 285 self.Iq = data.data[self.index] 286 self.dIq = data.err_data[self.index] 291 287 self._theory = np.zeros_like(data.data) 292 288 if not partype['orientation'] and not partype['magnetic']: 293 q_vectors = [np.sqrt(data.qx_data **2+data.qy_data**2)]289 q_vectors = [np.sqrt(data.qx_data ** 2 + data.qy_data ** 2)] 294 290 else: 295 291 q_vectors = [data.qx_data, data.qy_data] 296 292 elif self.data_type == 'Iq': 297 self.index = (data.x >=data.qmin) & (data.x<=data.qmax) & ~np.isnan(data.y)298 self. iq = data.y[self.index]299 self.d iq = data.dy[self.index]293 self.index = (data.x >= data.qmin) & (data.x <= data.qmax) & ~np.isnan(data.y) 294 self.Iq = data.y[self.index] 295 self.dIq = data.dy[self.index] 300 296 self._theory = np.zeros_like(data.y) 301 297 q_vectors = [data.x] … … 311 307 pars = [] 312 308 for p in model.info['parameters']: 313 name, default, limits , ptype = p[0], p[2], p[3], p[4]309 name, default, limits = p[0], p[2], p[3] 314 310 value = kw.pop(name, default) 315 311 setattr(self, name, Parameter.default(value, name=name, limits=limits)) 316 312 pars.append(name) 317 313 for name in partype['pd-2d']: 318 for xpart, xdefault,xlimits in [314 for xpart, xdefault, xlimits in [ 319 315 ('_pd', 0, limits), 320 ('_pd_n', 35, (0, 1000)),316 ('_pd_n', 35, (0, 1000)), 321 317 ('_pd_nsigma', 3, (0, 10)), 322 318 ('_pd_type', 'gaussian', None), 323 319 ]: 324 xname = name +xpart320 xname = name + xpart 325 321 xvalue = kw.pop(xname, xdefault) 326 322 if xlimits is not None: … … 330 326 self._parameter_names = pars 331 327 if kw: 332 raise TypeError("unexpected parameters: %s"%(", ".join(sorted(kw.keys())))) 328 raise TypeError("unexpected parameters: %s" 329 % (", ".join(sorted(kw.keys())))) 333 330 self.update() 334 331 … … 337 334 338 335 def numpoints(self): 339 return len(self.iq) 336 """ 337 Return the number of points 338 """ 339 return len(self.Iq) 340 340 341 341 def parameters(self): 342 return dict((k,getattr(self,k)) for k in self._parameter_names) 342 """ 343 Return a dictionary of parameters 344 """ 345 return dict((k, getattr(self, k)) for k in self._parameter_names) 343 346 344 347 def theory(self): 345 348 if 'theory' not in self._cache: 346 349 if self._fn is None: 347 input = self.model.make_input(self._fn_inputs)348 self._fn = self.model( input)349 350 pars = [getattr(self,p).value for p in self._fn.fixed_pars]350 q_input = self.model.make_input(self._fn_inputs) 351 self._fn = self.model(q_input) 352 353 fixed_pars = [getattr(self, p).value for p in self._fn.fixed_pars] 351 354 pd_pars = [self._get_weights(p) for p in self._fn.pd_pars] 352 #print pars353 self._theory[self.index] = self._fn( pars, pd_pars, self.cutoff)355 #print fixed_pars,pd_pars 356 self._theory[self.index] = self._fn(fixed_pars, pd_pars, self.cutoff) 354 357 #self._theory[:] = self._fn.eval(pars, pd_pars) 355 358 if self.data_type == 'sesans': 356 P = sesans.hankel(self.data.x, self.data.lam*1e-9,357 self.data.sample.thickness/10, self._fn_inputs[0],358 self._theory)359 self._cache['theory'] = P359 result = sesans.hankel(self.data.x, self.data.lam * 1e-9, 360 self.data.sample.thickness / 10, 361 self._fn_inputs[0], self._theory) 362 self._cache['theory'] = result 360 363 else: 361 364 self._cache['theory'] = self._theory … … 364 367 def residuals(self): 365 368 #if np.any(self.err ==0): print "zeros in err" 366 return (self.theory()[self.index] -self.iq)/self.diq369 return (self.theory()[self.index] - self.Iq) / self.dIq 367 370 368 371 def nllf(self): 369 R= self.residuals()372 delta = self.residuals() 370 373 #if np.any(np.isnan(R)): print "NaN in residuals" 371 return 0.5 *np.sum(R**2)372 373 def __call__(self):374 return 2*self.nllf()/self.dof374 return 0.5 * np.sum(delta ** 2) 375 376 #def __call__(self): 377 # return 2 * self.nllf() / self.dof 375 378 376 379 def plot(self, view='log'): … … 391 394 print "noise", noise 392 395 if noise is None: 393 noise = self.d iq[self.index]394 else: 395 noise = 0.01 *noise396 self.d iq[self.index] = noise396 noise = self.dIq[self.index] 397 else: 398 noise = 0.01 * noise 399 self.dIq[self.index] = noise 397 400 y = self.theory() 398 y += y *np.random.randn(*y.shape)*noise401 y += y * np.random.randn(*y.shape) * noise 399 402 if self.data_type == 'Iq': 400 403 self.data.y[self.index] = y … … 410 413 411 414 def _get_weights(self, par): 415 """ 416 Get parameter dispersion weights 417 """ 412 418 from . import weights 413 419 414 420 relative = self.model.info['partype']['pd-rel'] 415 421 limits = self.model.info['limits'] 416 disperser,value,npts,width,nsigma = [getattr(self, par+ext) 417 for ext in ('_pd_type','','_pd_n','_pd','_pd_nsigma')] 418 v,w = weights.get_weights( 422 disperser, value, npts, width, nsigma = [ 423 getattr(self, par + ext) 424 for ext in ('_pd_type', '', '_pd_n', '_pd', '_pd_nsigma')] 425 value, weight = weights.get_weights( 419 426 disperser, int(npts.value), width.value, nsigma.value, 420 427 value.value, limits[par], par in relative) 421 return v ,w/w.max()428 return value, weight / np.sum(weight) 422 429 423 430 def __getstate__(self): … … 428 435 429 436 def __setstate__(self, state): 437 # pylint: disable=attribute-defined-outside-init 430 438 self.__dict__ = state 431 439 … … 434 442 data = load_data('DEC07086.DAT') 435 443 set_beam_stop(data, 0.004) 436 plot_data(data )444 plot_data(data, data.data) 437 445 import matplotlib.pyplot as plt; plt.show() 438 446
Note: See TracChangeset
for help on using the changeset viewer.