- Timestamp:
- May 19, 2017 10:13:16 AM (8 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:
- 487e695
- Parents:
- f102a96
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
explore/precision.py
reb2946f r5181ccc 57 57 return calculator(background=0) 58 58 59 def run(self, xrange="log", diff= True):59 def run(self, xrange="log", diff="relative"): 60 60 r""" 61 61 Compare accuracy of different methods for computing f. 62 62 63 *xrange* is log=[10^-3,10^5], linear=[1,1000], zoom[1000,1010], 64 or neg=[-100,100]. 65 66 *diff* is False if showing function value rather than relative error. 63 *xrange* is:: 64 65 log: [10^-3,10^5] 66 logq: [10^-4, 10^1] 67 linear: [1,1000] 68 zoom: [1000,1010] 69 neg: [-100,100] 70 71 *diff* is "relative", "absolute" or "none" 67 72 68 73 *x_bits* is the precision with which the x values are specified. The 69 74 default 23 should reproduce the equivalent of a single precisio 70 75 """ 71 linear = xrange != "log"76 linear = not xrange.startswith("log") 72 77 if xrange == "zoom": 73 78 lin_min, lin_max, lin_steps = 1000, 1010, 2000 74 79 elif xrange == "neg": 75 80 lin_min, lin_max, lin_steps = -100.1, 100.1, 2000 81 elif xrange == "linear": 82 lin_min, lin_max, lin_steps = 1, 1000, 2000 83 elif xrange == "log": 84 log_min, log_max, log_steps = -3, 5, 400 85 elif xrange == "logq": 86 log_min, log_max, log_steps = -4, 1, 400 76 87 else: 77 lin_min, lin_max, lin_steps = 1, 1000, 2000 78 lin_min = max(lin_min, self.limits[0]) 79 lin_max = min(lin_max, self.limits[1]) 80 log_min, log_max, log_steps = -3, 5, 400 88 raise ValueError("unknown range "+xrange) 81 89 with mp.workprec(500): 90 # Note: we make sure that we are comparing apples to apples... 91 # The x points are set using single precision so that we are 92 # examining the accuracy of the transformation from x to f(x) 93 # rather than x to f(nearest(x)) where nearest(x) is the nearest 94 # value to x in the given precision. 82 95 if linear: 96 lin_min = max(lin_min, self.limits[0]) 97 lin_max = min(lin_max, self.limits[1]) 83 98 qrf = np.linspace(lin_min, lin_max, lin_steps, dtype='single') 99 #qrf = np.linspace(lin_min, lin_max, lin_steps, dtype='double') 84 100 qr = [mp.mpf(float(v)) for v in qrf] 85 101 #qr = mp.linspace(lin_min, lin_max, lin_steps) 86 102 else: 103 log_min = np.log10(max(10**log_min, self.limits[0])) 104 log_max = np.log10(min(10**log_max, self.limits[1])) 87 105 qrf = np.logspace(log_min, log_max, log_steps, dtype='single') 106 #qrf = np.logspace(log_min, log_max, log_steps, dtype='double') 88 107 qr = [mp.mpf(float(v)) for v in qrf] 89 108 #qr = [10**v for v in mp.linspace(log_min, log_max, log_steps)] … … 98 117 pylab.suptitle(self.name + " compared to 500-bit mpmath") 99 118 100 def compare(self, x, precision, target, linear=False, diff= True):119 def compare(self, x, precision, target, linear=False, diff="relative"): 101 120 r""" 102 121 Compare the different computation methods using the given precision. … … 113 132 plotdiff(x, target, self.call_ocl(x, precision, 0), 'OpenCL '+precision, diff=diff) 114 133 pylab.xlabel(self.xaxis) 115 if diff :134 if diff == "relative": 116 135 pylab.ylabel("relative error") 136 elif diff == "absolute": 137 pylab.ylabel("absolute error") 117 138 else: 118 139 pylab.ylabel(self.name) … … 121 142 pylab.xscale('linear') 122 143 123 def plotdiff(x, target, actual, label, diff =True):144 def plotdiff(x, target, actual, label, diff): 124 145 """ 125 146 Plot the computed value. … … 127 148 Use relative error if SHOW_DIFF, otherwise just plot the value directly. 128 149 """ 129 if diff :150 if diff == "relative": 130 151 err = np.array([abs((t-a)/t) for t, a in zip(target, actual)], 'd') 131 152 #err = np.clip(err, 0, 1) 153 pylab.loglog(x, err, '-', label=label) 154 elif diff == "absolute": 155 err = np.array([abs((t-a)) for t, a in zip(target, actual)], 'd') 132 156 pylab.loglog(x, err, '-', label=label) 133 157 else: … … 289 313 qr = x * f(RADIUS)*mp.sin(theta) 290 314 qh = x * f(LENGTH)/f(2)*mp.cos(theta) 291 return (f(2)*mp.j1(qr)/qr * mp.sin(qh)/qh)**f(2) 315 be = f(2)*mp.j1(qr)/qr 316 si = mp.sin(qh)/qh 317 background = f(0) 318 #background = f(1)/f(1000) 319 volume = mp.pi*f(RADIUS)**f(2)*f(LENGTH) 320 contrast = f(5) 321 units = f(1)/f(10000) 322 #return be 323 #return si 324 return units*(volume*contrast*be*si)**f(2)/volume + background 292 325 def np_cyl(x): 293 326 f = np.float64 if x.dtype == np.float64 else np.float32 … … 295 328 qr = x * f(RADIUS)*np.sin(theta) 296 329 qh = x * f(LENGTH)/f(2)*np.cos(theta) 297 return (f(2)*scipy.special.j1(qr)/qr*np.sin(qh)/qh)**f(2) 330 be = f(2)*scipy.special.j1(qr)/qr 331 si = np.sin(qh)/qh 332 background = f(0) 333 #background = f(1)/f(1000) 334 volume = f(np.pi)*f(RADIUS)**2*f(LENGTH) 335 contrast = f(5) 336 units = f(1)/f(10000) 337 #return be 338 #return si 339 return units*(volume*contrast*be*si)**f(2)/volume + background 298 340 ocl_cyl = """\ 299 341 double THETA = %(THETA).15e*M_PI_180; 300 342 double qr = q*%(RADIUS).15e*sin(THETA); 301 343 double qh = q*0.5*%(LENGTH).15e*cos(THETA); 302 return square(sas_2J1x_x(qr)*sas_sinx_x(qh)); 344 double be = sas_2J1x_x(qr); 345 double si = sas_sinx_x(qh); 346 double background = 0; 347 //double background = 0.001; 348 double volume = M_PI*square(%(RADIUS).15e)*%(LENGTH).15e; 349 double contrast = 5.0; 350 double units = 1e-4; 351 //return be; 352 //return si; 353 return units*square(volume*contrast*be*si)/volume + background; 303 354 """%{"LENGTH":LENGTH, "RADIUS": RADIUS, "THETA": THETA} 304 355 add_function( … … 428 479 names = ", ".join(sorted(ALL_FUNCTIONS)) 429 480 print("""\ 430 usage: precision.py [-f ] [--log|--linear|--zoom|--neg] name...481 usage: precision.py [-f/a/r] [-x<range>] name... 431 482 where 432 -f indicates that the function value should be plotted rather than error, 433 --log indicates log stepping in [10^-3, 10^5] 434 --linear indicates linear stepping in [1, 1000] 435 --zoom indicates linear stepping in [1000, 1010] 436 --neg indicates linear stepping in [-100.1, 100.1] 483 -f indicates that the function value should be plotted, 484 -a indicates that the absolute error should be plotted, 485 -r indicates that the relative error should be plotted (default), 486 -x<range> indicates the steps in x, where <range> is one of the following 487 log indicates log stepping in [10^-3, 10^5] (default) 488 logq indicates log stepping in [10^-4, 10^1] 489 linear indicates linear stepping in [1, 1000] 490 zoom indicates linear stepping in [1000, 1010] 491 neg indicates linear stepping in [-100.1, 100.1] 437 492 and name is "all [first]" or one of: 438 493 """+names) … … 441 496 def main(): 442 497 import sys 443 diff = True498 diff = "relative" 444 499 xrange = "log" 445 args = sys.argv[1:] 446 if '-f' in args: 447 args.remove('-f') 448 diff = False 449 for k in "log linear zoom neg".split(): 450 if '--'+k in args: 451 args.remove('--'+k) 452 xrange = k 453 if not args: 500 options = [v for v in sys.argv[1:] if v.startswith('-')] 501 for opt in options: 502 if opt == '-f': 503 diff = "none" 504 elif opt == '-r': 505 diff = "relative" 506 elif opt == '-a': 507 diff = "absolute" 508 elif opt.startswith('-x'): 509 xrange = opt[2:] 510 else: 511 usage() 512 513 names = [v for v in sys.argv[1:] if not v.startswith('-')] 514 if not names: 454 515 usage() 455 if args[0] == "all": 456 cutoff = args[1] if len(args) > 1 else "" 457 args = list(sorted(ALL_FUNCTIONS)) 458 args = [k for k in args if k >= cutoff] 459 if any(k not in FUNCTIONS for k in args): 516 517 if names[0] == "all": 518 cutoff = names[1] if len(names) > 1 else "" 519 names = list(sorted(ALL_FUNCTIONS)) 520 names = [k for k in names if k >= cutoff] 521 if any(k not in FUNCTIONS for k in names): 460 522 usage() 461 multiple = len( args) > 1523 multiple = len(names) > 1 462 524 pylab.interactive(multiple) 463 for k in args:525 for k in names: 464 526 pylab.clf() 465 527 comparator = FUNCTIONS[k]
Note: See TracChangeset
for help on using the changeset viewer.