Changeset bb39b4a in sasmodels
- Timestamp:
- Aug 6, 2017 11:36:58 AM (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:
- 97d89af
- Parents:
- 232bb12
- Location:
- sasmodels
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/compare.py
r232bb12 rbb39b4a 56 56 57 57 USAGE = """ 58 usage: compare.py model N1 N2 [options...] [key=val] 59 60 Compare the speed and value for a model between the SasView original and the 61 sasmodels rewrite. 58 usage: sascomp model [options...] [key=val] 59 60 Generate and compare SAS models. If a single model is specified it shows 61 a plot of that model. Different models can be compared, or the same model 62 with different parameters. The same model with the same parameters can 63 be compared with different calculation engines to see the effects of precision 64 on the resultant values. 62 65 63 66 model or model1,model2 are the names of the models to compare (see below). 64 N1 is the number of times to run sasmodels (default=1).65 N2 is the number times to run sasview (default=1).66 67 67 68 Options (* for default): 68 69 69 -plot*/-noplot plots or suppress the plot of the model 70 === data generation === 71 -data="path" uses q, dq from the data file 72 -noise=0 sets the measurement error dI/I 73 -res=0 sets the resolution width dQ/Q if calculating with resolution 70 74 -lowq*/-midq/-highq/-exq use q values up to 0.05, 0.2, 1.0, 10.0 71 75 -nq=128 sets the number of Q points in the data set 76 -1d*/-2d computes 1d or 2d data 72 77 -zero indicates that q=0 should be included 73 -1d*/-2d computes 1d or 2d data 78 79 === model parameters === 74 80 -preset*/-random[=seed] preset or random parameters 81 -sets=n generates n random datasets, with the seed given by -random=seed 82 -pars/-nopars* prints the parameter set or not 83 -default/-demo* use demo vs default parameters 84 85 === calculation options === 75 86 -mono*/-poly force monodisperse or allow polydisperse demo parameters 87 -cutoff=1e-5* cutoff value for including a point in polydispersity 76 88 -magnetic/-nonmagnetic* suppress magnetism 77 -cutoff=1e-5* cutoff value for including a point in polydispersity78 -pars/-nopars* prints the parameter set or not79 -abs/-rel* plot relative or absolute error80 -linear/-log*/-q4 intensity scaling81 -hist/-nohist* plot histogram of relative error82 -res=0 sets the resolution width dQ/Q if calculating with resolution83 89 -accuracy=Low accuracy of the resolution calculation Low, Mid, High, Xhigh 84 -edit starts the parameter explorer 85 -default/-demo* use demo vs default parameters 86 -help/-html shows the model docs instead of running the model 87 -title="note" adds note to the plot title, after the model name 88 -data="path" uses q, dq from the data file 89 90 Any two calculation engines can be selected for comparison: 91 90 91 === precision options === 92 -calc=default uses the default calcution precision 92 93 -single/-double/-half/-fast sets an OpenCL calculation engine 93 94 -single!/-double!/-quad! sets an OpenMP calculation engine 94 95 -sasview sets the sasview calculation engine 95 96 96 The default is -single -double. Note that the interpretation of quad 97 precision depends on architecture, and may vary from 64-bit to 128-bit, 98 with 80-bit floats being common (1e-19 precision). 97 === plotting === 98 -plot*/-noplot plots or suppress the plot of the model 99 -linear/-log*/-q4 intensity scaling on plots 100 -hist/-nohist* plot histogram of relative error 101 -abs/-rel* plot relative or absolute error 102 -title="note" adds note to the plot title, after the model name 103 104 === output options === 105 -edit starts the parameter explorer 106 -help/-html shows the model docs instead of running the model 107 108 The interpretation of quad precision depends on architecture, and may 109 vary from 64-bit to 128-bit, with 80-bit floats being common (1e-19 precision). 110 On unix and mac you may need single quotes around the DLL computation 111 engines, such as -calc='single!,double!' since !, is treated as a history 112 expansion request in the shell. 99 113 100 114 Key=value pairs allow you to set specific values for the model parameters. 101 Key=value1,value2 to compare different values of the same parameter. 102 value can be an expression including other parameters 115 Key=value1,value2 to compare different values of the same parameter. The 116 value can be an expression including other parameters. 117 118 Items later on the command line override those that appear earlier. 119 120 Examples: 121 122 # compare single and double precision calculation for a barbell 123 sascomp barbell -calc=single,double 124 125 # generate 10 random lorentz models, with seed=27 126 sascomp lorentz -sets=10 -seed=27 127 128 # compare ellipsoid with R = R_polar = R_equatorial to sphere of radius R 129 sascomp sphere,ellipsoid radius_polar=radius radius_equatorial=radius 130 131 # model timing test requires multiple evals to perform the estimate 132 sascomp pringle -calc=single,double -timing=100,100 -noplot 103 133 """ 104 134 … … 111 141 ------------------- 112 142 113 """ 114 + USAGE) 143 """ + USAGE) 115 144 116 145 kerneldll.ALLOW_SINGLE_PRECISION_DLLS = True … … 775 804 # type: (Dict[str, Any]) -> Dict[str, Any] 776 805 777 n_base, n_comp = opts['count'] 778 pars, pars2 = opts['pars'] 806 base, comp = opts['engines'] 807 base_n, comp_n = opts['count'] 808 base_pars, comp_pars = opts['pars'] 779 809 data = opts['data'] 780 810 781 # silence the linter 782 base = opts['engines'][0] if n_base else None 783 comp = opts['engines'][1] if n_comp else None 811 comparison = comp is not None 784 812 785 813 base_time = comp_time = None … … 787 815 788 816 # Base calculation 789 if n_base > 0: 817 try: 818 base_raw, base_time = time_calculation(base, base_pars, base_n) 819 base_value = np.ma.masked_invalid(base_raw) 820 if verbose: 821 print("%s t=%.2f ms, intensity=%.0f" 822 % (base.engine, base_time, base_value.sum())) 823 _show_invalid(data, base_value) 824 except ImportError: 825 traceback.print_exc() 826 827 # Comparison calculation 828 if comparison: 790 829 try: 791 base_raw, base_time = time_calculation(base, pars, n_base) 792 base_value = np.ma.masked_invalid(base_raw) 793 if verbose: 794 print("%s t=%.2f ms, intensity=%.0f" 795 % (base.engine, base_time, base_value.sum())) 796 _show_invalid(data, base_value) 797 except ImportError: 798 traceback.print_exc() 799 n_base = 0 800 801 # Comparison calculation 802 if n_comp > 0: 803 try: 804 comp_raw, comp_time = time_calculation(comp, pars2, n_comp) 830 comp_raw, comp_time = time_calculation(comp, comp_pars, comp_n) 805 831 comp_value = np.ma.masked_invalid(comp_raw) 806 832 if verbose: … … 810 836 except ImportError: 811 837 traceback.print_exc() 812 n_comp = 0813 838 814 839 # Compare, but only if computing both forms 815 if n_base > 0 and n_comp > 0:840 if comparison: 816 841 resid = (base_value - comp_value) 817 842 relerr = resid/np.where(comp_value != 0., abs(comp_value), 1.0) … … 856 881 857 882 have_base, have_comp = (base_value is not None), (comp_value is not None) 858 base = opts['engines'][0] if have_base else None 859 comp = opts['engines'][1] if have_comp else None 883 base, comp = opts['engines'] 860 884 data = opts['data'] 861 885 use_data = (opts['datafile'] is not None) and (have_base ^ have_comp) … … 874 898 875 899 if have_base: 876 if have_comp: plt.subplot(131) 900 if have_comp: 901 plt.subplot(131) 877 902 plot_theory(data, base_value, view=view, use_data=use_data, limits=limits) 878 903 plt.title("%s t=%.2f ms"%(base.engine, base_time)) 879 904 #cbar_title = "log I" 880 905 if have_comp: 881 if have_base: plt.subplot(132) 906 if have_base: 907 plt.subplot(132) 882 908 if not opts['is2d'] and have_base: 883 909 plot_theory(data, base_value, view=view, use_data=use_data, limits=limits) … … 894 920 sorted = np.sort(err.flatten()) 895 921 cutoff = sorted[int(sorted.size*0.95)] 896 err[err >cutoff] = cutoff922 err[err > cutoff] = cutoff 897 923 #err,errstr = base/comp,"ratio" 898 924 plot_theory(data, None, resid=err, view=errview, use_data=use_data) … … 923 949 # =========================================================================== 924 950 # 925 NAME_OPTIONS = set([ 951 952 # Set of command line options. 953 # Normal options such as -plot/-noplot are specified as 'name'. 954 # For options such as -nq=500 which require a value use 'name='. 955 # 956 OPTIONS = [ 957 # Plotting 926 958 'plot', 'noplot', 927 'half', 'fast', 'single', 'double', 928 'single!', 'double!', 'quad!', 'sasview', 929 'lowq', 'midq', 'highq', 'exq', 'zero', 959 'linear', 'log', 'q4', 960 'rel', 'abs', 961 'hist', 'nohist', 962 'title=', 963 964 # Data generation 965 'data=', 'noise=', 'res=', 966 'nq=', 'lowq', 'midq', 'highq', 'exq', 'zero', 930 967 '2d', '1d', 931 'preset', 'random', 932 'poly', 'mono', 968 969 # Parameter set 970 'preset', 'random', 'random=', 'sets=', 971 'demo', 'default', # TODO: remove demo/default 972 'nopars', 'pars', 973 974 # Calculation options 975 'poly', 'mono', 'cutoff=', 933 976 'magnetic', 'nonmagnetic', 934 ' nopars', 'pars',935 'rel', 'abs', 936 'linear', 'log', 'q4',937 ' hist', 'nohist',938 ' edit', 'html', 'help',939 ' demo', 'default',940 ])941 VALUE_OPTIONS = [ 942 # Note: random is both a name option and a value option943 ' cutoff', 'random', 'nq', 'res', 'accuracy', 'title', 'data', 'sets'977 'accuracy=', 978 979 # Precision options 980 'calc=', 981 'half', 'fast', 'single', 'double', 'single!', 'double!', 'quad!', 982 'sasview', # TODO: remove sasview 3.x support 983 'timing=', 984 985 # Output options 986 'help', 'html', 'edit', 944 987 ] 988 989 NAME_OPTIONS = set(k for k in OPTIONS if not k.endswith('=')) 990 VALUE_OPTIONS = [k[:-1] for k in OPTIONS if k.endswith('=')] 991 945 992 946 993 def columnize(items, indent="", width=79): … … 1002 1049 # not sure about brackets [] {} 1003 1050 # maybe one of the following @ ? ^ ! , 1004 MODEL_SPLIT = ','1051 PAR_SPLIT = ',' 1005 1052 def parse_opts(argv): 1006 1053 # type: (List[str]) -> Dict[str, Any] … … 1021 1068 print(columnize(MODELS, indent=" ")) 1022 1069 return None 1023 if len(positional_args) > 3:1024 print("expected parameters: model N1 N2")1025 1070 1026 1071 invalid = [o[1:] for o in flags … … 1031 1076 return None 1032 1077 1033 name = positional_args[0] 1034 n1 = int(positional_args[1]) if len(positional_args) > 1 else 1 1035 n2 = int(positional_args[2]) if len(positional_args) > 2 else 1 1078 name = positional_args[-1] 1036 1079 1037 1080 # pylint: disable=bad-whitespace … … 1044 1087 'nq' : 128, 1045 1088 'res' : 0.0, 1089 'noise' : 0.0, 1046 1090 'accuracy' : 'Low', 1047 'cutoff' : 0.0,1091 'cutoff' : '0.0', 1048 1092 'seed' : -1, # default to preset 1049 1093 'mono' : True, … … 1060 1104 'datafile' : None, 1061 1105 'sets' : 1, 1106 'engine' : 'default', 1107 'evals' : '1', 1062 1108 } 1063 engines = []1064 1109 for arg in flags: 1065 1110 if arg == '-noplot': opts['plot'] = False … … 1077 1122 elif arg.startswith('-nq='): opts['nq'] = int(arg[4:]) 1078 1123 elif arg.startswith('-res='): opts['res'] = float(arg[5:]) 1124 elif arg.startswith('-noise='): opts['noise'] = float(arg[7:]) 1079 1125 elif arg.startswith('-sets='): opts['sets'] = int(arg[6:]) 1080 1126 elif arg.startswith('-accuracy='): opts['accuracy'] = arg[10:] 1081 elif arg.startswith('-cutoff='): opts['cutoff'] = float(arg[8:])1127 elif arg.startswith('-cutoff='): opts['cutoff'] = arg[8:] 1082 1128 elif arg.startswith('-random='): opts['seed'] = int(arg[8:]) 1083 1129 elif arg.startswith('-title='): opts['title'] = arg[7:] 1084 1130 elif arg.startswith('-data='): opts['datafile'] = arg[6:] 1131 elif arg.startswith('-calc='): opts['engine'] = arg[6:] 1132 elif arg.startswith('-neval='): opts['evals'] = arg[7:] 1085 1133 elif arg == '-random': opts['seed'] = np.random.randint(1000000) 1086 1134 elif arg == '-preset': opts['seed'] = -1 … … 1095 1143 elif arg == '-rel': opts['rel_err'] = True 1096 1144 elif arg == '-abs': opts['rel_err'] = False 1097 elif arg == '-half': engines.append(arg[1:])1098 elif arg == '-fast': engines.append(arg[1:])1099 elif arg == '-single': engines.append(arg[1:])1100 elif arg == '-double': engines.append(arg[1:])1101 elif arg == '-single!': engines.append(arg[1:])1102 elif arg == '-double!': engines.append(arg[1:])1103 elif arg == '-quad!': engines.append(arg[1:])1104 elif arg == '-sasview': engines.append(arg[1:])1145 elif arg == '-half': opts['engine'] = 'half' 1146 elif arg == '-fast': opts['engine'] = 'fast' 1147 elif arg == '-single': opts['engine'] = 'single' 1148 elif arg == '-double': opts['engine'] = 'double' 1149 elif arg == '-single!': opts['engine'] = 'single!' 1150 elif arg == '-double!': opts['engine'] = 'double!' 1151 elif arg == '-quad!': opts['engine'] = 'quad!' 1152 elif arg == '-sasview': opts['engine'] = 'sasview' 1105 1153 elif arg == '-edit': opts['explore'] = True 1106 1154 elif arg == '-demo': opts['use_demo'] = True … … 1114 1162 opts['seed'] = np.random.randint(1000000) 1115 1163 1116 if MODEL_SPLIT in name:1117 name, name2 = name.split(MODEL_SPLIT, 2)1118 else:1119 name2 = name1120 try:1121 model_info = core.load_model_info(name)1122 model_info2 = core.load_model_info(name2) if name2 != name else model_info1123 except ImportError as exc:1124 print(str(exc))1125 print("Could not find model; use one of:\n " + models)1126 return None1127 1128 # TODO: check if presets are different when deciding if models are same1129 same_model = name == name21130 if len(engines) == 0:1131 if same_model:1132 engines.extend(['single', 'double'])1133 else:1134 engines.extend(['single', 'single'])1135 elif len(engines) == 1:1136 if not same_model:1137 engines.append(engines[0])1138 elif engines[0] == 'double':1139 engines.append('single')1140 else:1141 engines.append('double')1142 elif len(engines) > 2:1143 del engines[2:]1144 1145 1164 # Create the computational engines 1146 1165 if opts['datafile'] is not None: … … 1148 1167 else: 1149 1168 data, _ = make_data(opts) 1150 if n1: 1151 base = make_engine(model_info, data, engines[0], opts['cutoff']) 1169 1170 comparison = any(PAR_SPLIT in v for v in values) 1171 if PAR_SPLIT in name: 1172 names = name.split(PAR_SPLIT, 2) 1173 comparison = True 1152 1174 else: 1153 base = None 1154 if n2: 1155 comp = make_engine(model_info2, data, engines[1], opts['cutoff']) 1175 names = [name]*2 1176 try: 1177 model_info = [core.load_model_info(k) for k in names] 1178 except ImportError as exc: 1179 print(str(exc)) 1180 print("Could not find model; use one of:\n " + models) 1181 return None 1182 1183 if PAR_SPLIT in opts['engine']: 1184 engine_types = opts['engine'].split(PAR_SPLIT, 2) 1185 comparison = True 1186 else: 1187 engine_types = [opts['engine']]*2 1188 1189 if PAR_SPLIT in opts['evals']: 1190 evals = [int(k) for k in opts['evals'].split(PAR_SPLIT, 2)] 1191 comparison = True 1192 else: 1193 evals = [int(opts['evals'])]*2 1194 1195 if PAR_SPLIT in opts['cutoff']: 1196 cutoff = [float(k) for k in opts['cutoff'].split(PAR_SPLIT, 2)] 1197 comparison = True 1198 else: 1199 cutoff = [float(opts['cutoff'])]*2 1200 1201 base = make_engine(model_info[0], data, engine_types[0], cutoff[0]) 1202 if comparison: 1203 comp = make_engine(model_info[1], data, engine_types[1], cutoff[1]) 1156 1204 else: 1157 1205 comp = None … … 1161 1209 opts.update({ 1162 1210 'data' : data, 1163 'name' : [name, name2],1164 'def' : [model_info, model_info2],1165 'count' : [n1, n2],1211 'name' : names, 1212 'def' : model_info, 1213 'count' : evals, 1166 1214 'engines' : [base, comp], 1167 1215 'values' : values, … … 1210 1258 print("%r invalid; parameters are: %s"%(k, ", ".join(sorted(s)))) 1211 1259 return None 1212 v1, v2 = v.split( MODEL_SPLIT, 2) if MODEL_SPLIT in v else (v,v)1260 v1, v2 = v.split(PAR_SPLIT, 2) if PAR_SPLIT in v else (v,v) 1213 1261 if v1 and k in pars: 1214 1262 presets[k] = float(v1) if isnumber(v1) else v1 -
sasmodels/core.py
r650c6d2 rbb39b4a 253 253 254 254 # Convert dtype string to numpy dtype. 255 if dtype is None :255 if dtype is None or dtype == "default": 256 256 numpy_dtype = (generate.F32 if platform == "ocl" and model_info.single 257 257 else generate.F64) -
sasmodels/models/ellipsoid.py
r31df0c9 rbb39b4a 111 111 *Structure Analysis by Small-Angle X-Ray and Neutron Scattering*, 112 112 Plenum Press, New York, 1987. 113 114 A. Isihara. J. Chem. Phys. 18(1950) 1446-1449 113 115 114 116 Authorship and Verification … … 162 164 def ER(radius_polar, radius_equatorial): 163 165 import numpy as np 164 # see equation (26) in A.Isihara, J.Chem.Phys. 18(1950)1446-1449166 # see equation (26) in A.Isihara, J.Chem.Phys. 18(1950)1446-1449 165 167 ee = np.empty_like(radius_polar) 166 168 idx = radius_polar > radius_equatorial
Note: See TracChangeset
for help on using the changeset viewer.