Changeset 0bdddc2 in sasmodels
- Timestamp:
- Jul 28, 2017 8:59:19 PM (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:
- a151caa
- Parents:
- 72be531
- Location:
- sasmodels
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/compare.py
r630156b r0bdddc2 264 264 265 265 266 def _randomize_one(model_info, p, v):266 def _randomize_one(model_info, name, value): 267 267 # type: (ModelInfo, str, float) -> float 268 268 # type: (ModelInfo, str, str) -> str … … 270 270 Randomize a single parameter. 271 271 """ 272 if any(p.endswith(s) for s in ('_pd', '_pd_n', '_pd_nsigma', '_pd_type')): 273 return v 274 275 # Find the parameter definition 276 for par in model_info.parameters.call_parameters: 277 if par.name == p: 278 break 279 else: 280 raise ValueError("unknown parameter %r"%p) 281 272 if name.endswith('_pd'): 273 par = model_info.parameters[name[:-3]] 274 if par.type == 'orientation': 275 # Let oriention variation peak around 13 degrees; 95% < 42 degrees 276 return 180*np.random.beta(2.5, 20) 277 else: 278 # Let polydispersity peak around 15%; 95% < 0.4; max=100% 279 return np.random.beta(1.5, 7) 280 281 if name.endswith('_pd_n'): 282 # let pd be selected globally rather than per parameter 283 return 0 284 285 if name.endswith('_pd_type'): 286 # Don't mess with distribution type for now 287 return 'gaussian' 288 289 if name.endswith('_pd_nsigma'): 290 # type-dependent value; for gaussian use 3. 291 return 3. 292 293 if name == 'background': 294 return np.random.uniform(0, 1) 295 296 if name == 'scale': 297 return 10**np.random.uniform(-5,0) 298 299 par = model_info.parameters[name] 282 300 if len(par.limits) > 2: # choice list 283 301 return np.random.randint(len(par.limits)) 284 302 285 limits = par.limits 286 if not np.isfinite(limits).all(): 287 low, high = parameter_range(p, v) 288 limits = (max(limits[0], low), min(limits[1], high)) 289 303 if np.isfinite(par.limits).all(): 304 return np.random.uniform(*par.limits) 305 306 if par.type == 'sld': 307 # Range of neutron SLDs 308 return np.random.uniform(-0.5, 12) 309 310 if par.type == 'volume': 311 if ('length' in par.name or 312 'radius' in par.name or 313 'thick' in par.name): 314 return 10**np.random.uniform(2,4) 315 316 low, high = parameter_range(par.name, value) 317 limits = (max(par.limits[0], low), min(par.limits[1], high)) 290 318 return np.random.uniform(*limits) 291 319 … … 301 329 :func:`constrain_pars` needs to be called afterward.. 302 330 """ 303 with push_seed(seed): 304 # Note: the sort guarantees order `of calls to random number generator 305 random_pars = dict((p, _randomize_one(model_info, p, v)) 306 for p, v in sorted(pars.items())) 331 # Note: the sort guarantees order of calls to random number generator 332 random_pars = dict((p, _randomize_one(model_info, p, v)) 333 for p, v in sorted(pars.items())) 334 if model_info.random is not None: 335 random_pars.update(model_info.random()) 336 307 337 return random_pars 308 338 … … 662 692 parameters. 663 693 """ 664 result = run_models(opts, verbose=True) 665 if opts['plot']: # Note: never called from explore 666 plot_models(opts, result, limits=limits) 694 limits = np.Inf, -np.Inf 695 for k in range(opts['sets']): 696 opts['pars'] = parse_pars(opts) 697 result = run_models(opts, verbose=True) 698 if opts['plot']: 699 limits = plot_models(opts, result, limits=limits, setnum=k) 700 if opts['plot']: 701 import matplotlib.pyplot as plt 702 plt.show() 667 703 668 704 def run_models(opts, verbose=False): … … 743 779 744 780 745 def plot_models(opts, result, limits= None):781 def plot_models(opts, result, limits=(np.Inf, -np.Inf), setnum=0): 746 782 # type: (Dict[str, Any], Dict[str, Any], Optional[Tuple[float, float]]) -> Tuple[float, float] 747 783 base_value, comp_value= result['base_value'], result['comp_value'] … … 758 794 view = opts['view'] 759 795 import matplotlib.pyplot as plt 760 if limits is None and not use_data: 761 vmin, vmax = np.Inf, -np.Inf 762 if have_base: 763 vmin = min(vmin, base_value.min()) 764 vmax = max(vmax, base_value.max()) 765 if have_comp: 766 vmin = min(vmin, comp_value.min()) 767 vmax = max(vmax, comp_value.max()) 768 limits = vmin, vmax 796 vmin, vmax = limits 797 if have_base: 798 vmin = min(vmin, base_value.min()) 799 vmax = max(vmax, base_value.max()) 800 if have_comp: 801 vmin = min(vmin, comp_value.min()) 802 vmax = max(vmax, comp_value.max()) 803 limits = vmin, vmax 769 804 770 805 if have_base: … … 813 848 plt.title('Distribution of relative error between calculation engines') 814 849 815 if not opts['explore']:816 plt.show()817 818 850 return limits 819 820 821 851 822 852 … … 841 871 VALUE_OPTIONS = [ 842 872 # Note: random is both a name option and a value option 843 'cutoff', 'random', 'nq', 'res', 'accuracy', 'title', 'data', 873 'cutoff', 'random', 'nq', 'res', 'accuracy', 'title', 'data', 'sets' 844 874 ] 845 875 … … 914 944 if not arg.startswith('-') and '=' in arg] 915 945 positional_args = [arg for arg in argv 916 if not arg.startswith('-') and '=' not in arg]946 if not arg.startswith('-') and '=' not in arg] 917 947 models = "\n ".join("%-15s"%v for v in MODELS) 918 948 if len(positional_args) == 0: … … 959 989 'title' : None, 960 990 'datafile' : None, 991 'sets' : 1, 961 992 } 962 993 engines = [] … … 976 1007 elif arg.startswith('-nq='): opts['nq'] = int(arg[4:]) 977 1008 elif arg.startswith('-res='): opts['res'] = float(arg[5:]) 1009 elif arg.startswith('-sets='): opts['sets'] = int(arg[6:]) 978 1010 elif arg.startswith('-accuracy='): opts['accuracy'] = arg[10:] 979 1011 elif arg.startswith('-cutoff='): opts['cutoff'] = float(arg[8:]) … … 1008 1040 # pylint: enable=bad-whitespace 1009 1041 1042 # Force random if more than one set 1043 if opts['sets'] > 1 and opts['seed'] < 0: 1044 opts['seed'] = np.random.randint(1000000) 1045 1010 1046 if MODEL_SPLIT in name: 1011 1047 name, name2 = name.split(MODEL_SPLIT, 2) … … 1020 1056 return None 1021 1057 1022 # Get demo parameters from model definition, or use default parameters 1023 # if model does not define demo parameters 1024 pars = get_pars(model_info, opts['use_demo']) 1025 pars2 = get_pars(model_info2, opts['use_demo']) 1026 pars2.update((k, v) for k, v in pars.items() if k in pars2) 1027 # randomize parameters 1028 #pars.update(set_pars) # set value before random to control range 1029 if opts['seed'] > -1: 1030 pars = randomize_pars(model_info, pars, seed=opts['seed']) 1031 if model_info != model_info2: 1032 pars2 = randomize_pars(model_info2, pars2, seed=opts['seed']) 1033 # Share values for parameters with the same name 1034 for k, v in pars.items(): 1035 if k in pars2: 1036 pars2[k] = v 1037 else: 1038 pars2 = pars.copy() 1039 constrain_pars(model_info, pars) 1040 constrain_pars(model_info2, pars2) 1041 print("Randomize using -random=%i"%opts['seed']) 1042 if opts['mono']: 1043 pars = suppress_pd(pars) 1044 pars2 = suppress_pd(pars2) 1045 if not opts['magnetic']: 1046 pars = suppress_magnetism(pars) 1047 pars2 = suppress_magnetism(pars2) 1048 1049 # Fill in parameters given on the command line 1050 presets = {} 1051 presets2 = {} 1052 for arg in values: 1053 k, v = arg.split('=', 1) 1054 if k not in pars and k not in pars2: 1055 # extract base name without polydispersity info 1056 s = set(p.split('_pd')[0] for p in pars) 1057 print("%r invalid; parameters are: %s"%(k, ", ".join(sorted(s)))) 1058 return None 1059 v1, v2 = v.split(MODEL_SPLIT, 2) if MODEL_SPLIT in v else (v,v) 1060 if v1 and k in pars: 1061 presets[k] = float(v1) if isnumber(v1) else v1 1062 if v2 and k in pars2: 1063 presets2[k] = float(v2) if isnumber(v2) else v2 1064 1065 # If pd given on the command line, default pd_n to 35 1066 for k, v in list(presets.items()): 1067 if k.endswith('_pd'): 1068 presets.setdefault(k+'_n', 35.) 1069 for k, v in list(presets2.items()): 1070 if k.endswith('_pd'): 1071 presets2.setdefault(k+'_n', 35.) 1072 1073 # Evaluate preset parameter expressions 1074 context = MATH.copy() 1075 context['np'] = np 1076 context.update(pars) 1077 context.update((k,v) for k,v in presets.items() if isinstance(v, float)) 1078 for k, v in presets.items(): 1079 if not isinstance(v, float) and not k.endswith('_type'): 1080 presets[k] = eval(v, context) 1081 context.update(presets) 1082 context.update((k,v) for k,v in presets2.items() if isinstance(v, float)) 1083 for k, v in presets2.items(): 1084 if not isinstance(v, float) and not k.endswith('_type'): 1085 presets2[k] = eval(v, context) 1086 1087 # update parameters with presets 1088 pars.update(presets) # set value after random to control value 1089 pars2.update(presets2) # set value after random to control value 1090 #import pprint; pprint.pprint(model_info) 1091 1092 same_model = name == name2 and pars == pars 1058 # TODO: check if presets are different when deciding if models are same 1059 same_model = name == name2 1093 1060 if len(engines) == 0: 1094 1061 if same_model: … … 1106 1073 del engines[2:] 1107 1074 1108 use_sasview = any(engine == 'sasview' and count > 01109 for engine, count in zip(engines, [n1, n2]))1110 if use_sasview:1111 constrain_new_to_old(model_info, pars)1112 constrain_new_to_old(model_info2, pars2)1113 1114 if opts['show_pars']:1115 if not same_model:1116 print("==== %s ====="%model_info.name)1117 print(str(parlist(model_info, pars, opts['is2d'])))1118 print("==== %s ====="%model_info2.name)1119 print(str(parlist(model_info2, pars2, opts['is2d'])))1120 else:1121 print(str(parlist(model_info, pars, opts['is2d'])))1122 1123 1075 # Create the computational engines 1124 1076 if opts['datafile'] is not None: … … 1142 1094 'def' : [model_info, model_info2], 1143 1095 'count' : [n1, n2], 1144 'presets' : [presets, presets2],1145 'pars' : [pars, pars2],1146 1096 'engines' : [base, comp], 1097 'values' : values, 1147 1098 }) 1148 1099 # pylint: enable=bad-whitespace 1149 1100 1150 1101 return opts 1102 1103 def parse_pars(opts): 1104 model_info, model_info2 = opts['def'] 1105 1106 # Get demo parameters from model definition, or use default parameters 1107 # if model does not define demo parameters 1108 pars = get_pars(model_info, opts['use_demo']) 1109 pars2 = get_pars(model_info2, opts['use_demo']) 1110 pars2.update((k, v) for k, v in pars.items() if k in pars2) 1111 # randomize parameters 1112 #pars.update(set_pars) # set value before random to control range 1113 if opts['seed'] > -1: 1114 pars = randomize_pars(model_info, pars) 1115 if model_info != model_info2: 1116 pars2 = randomize_pars(model_info2, pars2) 1117 # Share values for parameters with the same name 1118 for k, v in pars.items(): 1119 if k in pars2: 1120 pars2[k] = v 1121 else: 1122 pars2 = pars.copy() 1123 constrain_pars(model_info, pars) 1124 constrain_pars(model_info2, pars2) 1125 if opts['mono']: 1126 pars = suppress_pd(pars) 1127 pars2 = suppress_pd(pars2) 1128 if not opts['magnetic']: 1129 pars = suppress_magnetism(pars) 1130 pars2 = suppress_magnetism(pars2) 1131 1132 # Fill in parameters given on the command line 1133 presets = {} 1134 presets2 = {} 1135 for arg in opts['values']: 1136 k, v = arg.split('=', 1) 1137 if k not in pars and k not in pars2: 1138 # extract base name without polydispersity info 1139 s = set(p.split('_pd')[0] for p in pars) 1140 print("%r invalid; parameters are: %s"%(k, ", ".join(sorted(s)))) 1141 return None 1142 v1, v2 = v.split(MODEL_SPLIT, 2) if MODEL_SPLIT in v else (v,v) 1143 if v1 and k in pars: 1144 presets[k] = float(v1) if isnumber(v1) else v1 1145 if v2 and k in pars2: 1146 presets2[k] = float(v2) if isnumber(v2) else v2 1147 1148 # If pd given on the command line, default pd_n to 35 1149 for k, v in list(presets.items()): 1150 if k.endswith('_pd'): 1151 presets.setdefault(k+'_n', 35.) 1152 for k, v in list(presets2.items()): 1153 if k.endswith('_pd'): 1154 presets2.setdefault(k+'_n', 35.) 1155 1156 # Evaluate preset parameter expressions 1157 context = MATH.copy() 1158 context['np'] = np 1159 context.update(pars) 1160 context.update((k, v) for k, v in presets.items() if isinstance(v, float)) 1161 for k, v in presets.items(): 1162 if not isinstance(v, float) and not k.endswith('_type'): 1163 presets[k] = eval(v, context) 1164 context.update(presets) 1165 context.update((k, v) for k, v in presets2.items() if isinstance(v, float)) 1166 for k, v in presets2.items(): 1167 if not isinstance(v, float) and not k.endswith('_type'): 1168 presets2[k] = eval(v, context) 1169 1170 # update parameters with presets 1171 pars.update(presets) # set value after random to control value 1172 pars2.update(presets2) # set value after random to control value 1173 #import pprint; pprint.pprint(model_info) 1174 1175 if opts['show_pars']: 1176 if model_info.name != model_info2.name or pars != pars2: 1177 print("==== %s ====="%model_info.name) 1178 print(str(parlist(model_info, pars, opts['is2d']))) 1179 print("==== %s ====="%model_info2.name) 1180 print(str(parlist(model_info2, pars2, opts['is2d']))) 1181 else: 1182 print(str(parlist(model_info, pars, opts['is2d']))) 1183 1184 return pars, pars2 1151 1185 1152 1186 def show_docs(opts): … … 1180 1214 model = Explore(opts) 1181 1215 problem = FitProblem(model) 1182 frame = AppFrame(parent=None, title="explore", size=(1000,700)) 1183 if not is_mac: frame.Show() 1216 frame = AppFrame(parent=None, title="explore", size=(1000, 700)) 1217 if not is_mac: 1218 frame.Show() 1184 1219 frame.panel.set_model(model=problem) 1185 1220 frame.panel.Layout() … … 1191 1226 if is_mac: frame.Show() 1192 1227 # If running withing an app, start the main loop 1193 if app: app.MainLoop() 1228 if app: 1229 app.MainLoop() 1194 1230 1195 1231 class Explore(object): … … 1206 1242 config_matplotlib() 1207 1243 self.opts = opts 1244 opts['pars'] = list(opts['pars']) 1208 1245 p1, p2 = opts['pars'] 1209 1246 m1, m2 = opts['def'] … … 1226 1263 self.starting_values = dict((k, v.value) for k, v in pars.items()) 1227 1264 self.pd_types = pd_types 1228 self.limits = None1265 self.limits = np.Inf, -np.Inf 1229 1266 1230 1267 def revert_values(self): … … 1282 1319 """ 1283 1320 opts = parse_opts(argv) 1321 if opts['seed'] > -1: 1322 print("Randomize using -random=%i"%opts['seed']) 1323 np.random.seed(opts['seed']) 1284 1324 if opts is not None: 1285 1325 if opts['html']: 1286 1326 show_docs(opts) 1287 1327 elif opts['explore']: 1328 opts['pars'] = parse_pars(opts) 1288 1329 explore(opts) 1289 1330 else: -
sasmodels/modelinfo.py
r724257c r0bdddc2 467 467 if p.polydisperse and p.type not in ('orientation', 'magnetic')) 468 468 self.pd_2d = set(p.name for p in self.call_parameters if p.polydisperse) 469 470 def __getitem__(self, key): 471 # Find the parameter definition 472 for par in self.call_parameters: 473 if par.name == key: 474 break 475 else: 476 raise KeyError("unknown parameter %r"%key) 477 return par 469 478 470 479 def _set_vector_lengths(self): … … 754 763 info.opencl = getattr(kernel_module, 'opencl', not callable(info.Iq)) 755 764 info.single = getattr(kernel_module, 'single', not callable(info.Iq)) 765 info.random = getattr(kernel_module, 'random', None) 756 766 757 767 # multiplicity info -
sasmodels/models/adsorbed_layer.py
rb0c4271 r0bdddc2 94 94 Iq.vectorized = True # Iq accepts an array of q values 95 95 96 def random(): 97 # only care about the value of second_moment: 98 # curve = scale * e**(-second_moment^2 q^2)/q^2 99 # scale = 6 pi/100 (contrast/density*absorbed_amount)^2 * Vf/radius 100 # the remaining parameters can be randomly generated from zero to 101 # twice the default value. 102 import numpy as np 103 pars = dict( 104 scale=1, 105 second_moment=10**np.random.uniform(1, 3), 106 ) 107 return pars 108 96 109 # unit test values taken from SasView 3.1.2 97 110 tests = [ -
sasmodels/models/bcc_paracrystal.py
r69e1afc r0bdddc2 81 81 .. figure:: img/parallelepiped_angle_definition.png 82 82 83 Orientation of the crystal with respect to the scattering plane, when 83 Orientation of the crystal with respect to the scattering plane, when 84 84 $\theta = \phi = 0$ the $c$ axis is along the beam direction (the $z$ axis). 85 85 … … 131 131 source = ["lib/sas_3j1x_x.c", "lib/gauss150.c", "lib/sphere_form.c", "bcc_paracrystal.c"] 132 132 133 def random(): 134 import numpy as np 135 # Define lattice spacing as a multiple of the particle radius 136 # using the formulat a = 4 r/sqrt(3). Systems which are ordered 137 # are probably mostly filled, so use a distribution which goes from 138 # zero to one, but leaving 90% of them within 80% of the 139 # maximum bcc packing. Lattice distortion values are empirically 140 # useful between 0.01 and 0.7. Use an exponential distribution 141 # in this range 'cuz its easy. 142 dnn_fraction = np.random.beta(a=10, b=1) 143 pars = dict( 144 #sld=1, sld_solvent=0, scale=1, background=1e-32, 145 radius=10**np.random.uniform(1.3, 4), 146 d_factor=10**np.random.uniform(-2, -0.7), # sigma_d in 0.01-0.7 147 ) 148 pars['dnn'] = pars['radius']*4/np.sqrt(3)/dnn_fraction 149 #pars['scale'] = 1/(0.68*dnn_fraction**3) # bcc packing fraction is 0.68 150 pars['scale'] = 1 151 return pars 152 133 153 # parameters for demo 134 154 demo = dict( -
sasmodels/models/broad_peak.py
r43fe34b r0bdddc2 94 94 Iq.vectorized = True # Iq accepts an array of q values 95 95 96 def random(): 97 import numpy as np 98 pars = dict( 99 scale=1, 100 porod_scale=10**np.random.uniform(-8, -5), 101 porod_exp=np.random.uniform(1, 6), 102 lorentz_scale=10**np.random.uniform(0.3, 6), 103 lorentz_length=10**np.random.uniform(0, 2), 104 peak_pos=10**np.random.uniform(-3, -1), 105 lorentz_exp=np.random.uniform(1, 4), 106 ) 107 pars['lorentz_length'] /= pars['peak_pos'] 108 pars['lorentz_scale'] *= pars['porod_scale'] / pars['peak_pos']**pars['porod_exp'] 109 #pars['porod_scale'] = 0. 110 return pars 111 96 112 demo = dict(scale=1, background=0, 97 113 porod_scale=1.0e-05, porod_exp=3,
Note: See TracChangeset
for help on using the changeset viewer.