Changes in sasmodels/model_test.py [b297ba9:8795b6f] in sasmodels
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/model_test.py
rb297ba9 r8795b6f 240 240 s_name = pars.pop('@S') 241 241 ps_test = [pars] + list(test[1:]) 242 #print("PS TEST PARAMS!!!",ps_test) 242 243 # build the P@S model 243 244 s_info = load_model_info(s_name) … … 246 247 platform=self.platform) 247 248 # run the tests 249 #self.info = ps_model.info 250 #print("SELF.INFO PARAMS!!!",[p.id for p in self.info.parameters.call_parameters]) 251 #print("PS MODEL PARAMETERS:",[p.id for p in ps_model.info.parameters.call_parameters]) 248 252 results.append(self.run_one(ps_model, ps_test)) 249 253 … … 303 307 """Run a single test case.""" 304 308 user_pars, x, y = test[:3] 305 pars = expand_pars(self.info.parameters, user_pars) 306 invalid = invalid_pars(self.info.parameters, pars) 309 #print("PS MODEL PARAMETERS:",[p.id for p in model.info.parameters.call_parameters]) 310 pars = expand_pars(model.info.parameters, user_pars) 311 invalid = invalid_pars(model.info.parameters, pars) 307 312 if invalid: 308 313 raise ValueError("Unknown parameters in test: " + ", ".join(invalid)) … … 328 333 else: 329 334 y1 = y 330 y2 = test[3] if notisinstance(test[3], list) else [test[3]]331 F 1, F2, R_eff, volume, volume_ratio = call_Fq(kernel, pars)332 if F 1 is not None: # F1is none for models with Iq instead of Fq333 self._check_vectors(x, y1, F 1, 'F')334 self._check_vectors(x, y2, F 2, 'F^2')335 y2 = test[3] if isinstance(test[3], list) else [test[3]] 336 F, Fsq, R_eff, volume, volume_ratio = call_Fq(kernel, pars) 337 if F is not None: # F is none for models with Iq instead of Fq 338 self._check_vectors(x, y1, F, 'F') 339 self._check_vectors(x, y2, Fsq, 'F^2') 335 340 self._check_scalar(test[4], R_eff, 'R_eff') 336 341 self._check_scalar(test[5], volume, 'volume') 337 342 self._check_scalar(test[6], volume_ratio, 'form:shell ratio') 338 return F 2343 return Fsq 339 344 340 345 def _check_scalar(self, target, actual, name): 341 if target is None: 342 # smoke test --- make sure it runs and produces a value 343 self.assertTrue(not np.isnan(actual), 344 'invalid %s: %s' % (name, actual)) 345 elif np.isnan(target): 346 # make sure nans match 347 self.assertTrue(np.isnan(actual), 348 '%s: expected:%s; actual:%s' 349 % (name, target, actual)) 350 else: 351 # is_near does not work for infinite values, so also test 352 # for exact values. 353 self.assertTrue(target == actual or is_near(target, actual, 5), 354 '%s: expected:%s; actual:%s' 355 % (name, target, actual)) 346 self.assertTrue(is_near(target, actual, 5), 347 '%s: expected:%s; actual:%s' 348 % (name, target, actual)) 356 349 357 350 def _check_vectors(self, x, target, actual, name='I'): … … 363 356 '%s(...) returned wrong length'%name) 364 357 for xi, yi, actual_yi in zip(x, target, actual): 365 if yi is None: 366 # smoke test --- make sure it runs and produces a value 367 self.assertTrue(not np.isnan(actual_yi), 368 'invalid %s(%s): %s' % (name, xi, actual_yi)) 369 elif np.isnan(yi): 370 # make sure nans match 371 self.assertTrue(np.isnan(actual_yi), 372 '%s(%s): expected:%s; actual:%s' 373 % (name, xi, yi, actual_yi)) 374 else: 375 # is_near does not work for infinite values, so also test 376 # for exact values. 377 self.assertTrue(yi == actual_yi or is_near(yi, actual_yi, 5), 378 '%s(%s); expected:%s; actual:%s' 379 % (name, xi, yi, actual_yi)) 358 self.assertTrue(is_near(yi, actual_yi, 5), 359 '%s(%s): expected:%s; actual:%s' 360 % (name, xi, target, actual)) 380 361 381 362 return ModelTestCase … … 389 370 invalid = [] 390 371 for par in sorted(pars.keys()): 391 # special handling of R_eff mode, which is not a usual parameter 372 # Ignore the R_eff mode parameter when checking for valid parameters. 373 # It is an allowed parameter for a model even though it does not exist 374 # in the parameter table. The call_Fq() function pops it from the 375 # parameter list and sends it directly to kernel.Fq(). 392 376 if par == product.RADIUS_MODE_ID: 393 377 continue … … 405 389 """ 406 390 Returns true if *actual* is within *digits* significant digits of *target*. 407 """ 408 import math 409 shift = 10**math.ceil(math.log10(abs(target))) 410 return abs(target-actual)/shift < 1.5*10**-digits 391 392 *taget* zero and inf should match *actual* zero and inf. If you want to 393 accept eps for zero, choose a value such as 1e-10, which must match up to 394 +/- 1e-15 when *digits* is the default value of 5. 395 396 If *target* is None, then just make sure that *actual* is not NaN. 397 398 If *target* is NaN, make sure *actual* is NaN. 399 """ 400 if target is None: 401 # target is None => actual cannot be NaN 402 return not np.isnan(actual) 403 elif target == 0.: 404 # target is 0. => actual must be 0. 405 # Note: if small values are allowed, then use maybe test zero against eps instead? 406 return actual == 0. 407 elif np.isfinite(target): 408 shift = np.ceil(np.log10(abs(target))) 409 return abs(target-actual) < 1.5*10**(shift-digits) 410 elif target == actual: 411 # target is inf => actual must be inf of same sign 412 return True 413 else: 414 # target is NaN => actual must be NaN 415 return np.isnan(target) == np.isnan(actual) 411 416 412 417 # CRUFT: old interface; should be deprecated and removed
Note: See TracChangeset
for help on using the changeset viewer.