Changes in / [0c2da4b:d3e3f756] in sasmodels
- Files:
-
- 1 deleted
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/conversion_table.py
rd3e3f756 rd3e3f756 5 5 names for each parameter in sasmodels. This is used by :mod:`convert` to 6 6 determine the equivalent parameter set when comparing a sasmodels model to 7 the models defined in previous versions of SasView and sasmodels. This is now 8 versioned based on the version number of SasView. 9 10 When any sasmodels parameter or model name is changed, this must be modified to 11 account for that. 12 13 Usage: 14 <old_Sasview_version> : { 15 <new_model_name> : [ 16 <old_model_name> , 17 { 18 <new_param_name_1> : <old_param_name_1>, 19 ... 20 <new_param_name_n> : <old_param_name_n> 21 } 22 ] 23 } 24 25 Any future parameter and model name changes can and should be given in this 26 table for future compatibility. 7 the models defined in SasView 3.1. 27 8 """ 28 9 10 29 11 CONVERSION_TABLE = { 30 (3,1,2) : {31 12 "adsorbed_layer": [ 32 13 "Core2ndMomentModel", … … 230 211 ], 231 212 "correlation_length": [ 232 "CorrLength ",213 "CorrLengthModel", 233 214 { 234 215 "porod_scale": "scale_p", … … 237 218 "lorentz_exp": "exponent_l", 238 219 "cor_length": "length_l" 239 }, 240 "CorrLengthModel" 220 } 241 221 ], 242 222 "cylinder": [ … … 319 299 ], 320 300 "fractal_core_shell": [ 321 "FractalCoreShell ",301 "FractalCoreShellModel", 322 302 { 323 303 "sld_core": "core_sld", … … 329 309 "cor_length": "cor_length", 330 310 "volfraction": "volfraction", 331 }, 332 "FractalCoreShellModel" 311 } 333 312 ], 334 313 "fuzzy_sphere": [ … … 342 321 ], 343 322 "gauss_lorentz_gel": [ 344 "GaussLorentzGel ",323 "GaussLorentzGelModel", 345 324 { 346 325 "gauss_scale": "scale_g", … … 349 328 "background": "background", 350 329 "lorentz_scale": "scale_l" 351 }, 352 "GaussLorentzGelModel" 330 } 353 331 ], 354 332 "gaussian_peak": [ 355 "Peak GaussModel",333 "PeakGaussModel", 356 334 { 357 335 "peak_pos": "q0", 358 336 "sigma": "B", 359 }, 360 "PeakGaussModel", 337 } 361 338 ], 362 339 "gel_fit": [ … … 366 343 "lorentz_scale": "lScale", 367 344 "guinier_scale": "gScale", 368 "fractal_dim": " FractalExp",345 "fractal_dim": "scale", 369 346 "cor_length": "zeta", 370 347 } 371 348 ], 372 349 "guinier": [ 373 "Guinier ",350 "GuinierModel", 374 351 { 375 352 "rg": "rg" 376 }, 377 "GuinierModel", 353 } 378 354 ], 379 355 "guinier_porod": [ 380 "GuinierPorod ",356 "GuinierPorodModel", 381 357 { 382 358 "s": "dim", … … 385 361 "scale": "scale", 386 362 "background": "background" 387 }, 388 "GuinierPorodModel", 363 } 389 364 ], 390 365 "hardsphere": [ … … 479 454 "d_spacing": "spacing", 480 455 "Caille_parameter": "caille", 481 "Nlayers": " n_plates",456 "Nlayers": "N_plates", 482 457 } 483 458 ], … … 511 486 ], 512 487 "lorentz": [ 513 "Lorentz ",488 "LorentzModel", 514 489 { 515 490 "cor_length": "length" 516 }, 517 "LorentzModel", 491 } 518 492 ], 519 493 "mass_fractal": [ … … 536 510 ], 537 511 "mono_gauss_coil": [ 538 "Debye ",512 "DebyeModel", 539 513 { 540 514 "rg": "rg", 541 515 "i_zero": "scale", 542 516 "background": "background", 543 }, 544 "DebyeModel", 517 } 545 518 ], 546 519 "multilayer_vesicle": [ … … 591 564 ], 592 565 "peak_lorentz": [ 593 "Peak LorentzModel",566 "PeakLorentzModel", 594 567 { 595 568 "peak_pos": "q0", 596 569 "peak_hwhm": "B" 597 }, 598 "PeakLorentzModel", 570 } 599 571 ], 600 572 "pearl_necklace": [ … … 830 802 ], 831 803 "two_lorentzian": [ 832 "TwoLorentzian ",804 "TwoLorentzianModel", 833 805 { 834 806 "lorentz_scale_1": "scale_1", … … 839 811 "lorentz_length_1": "length_1", 840 812 "background": "background" 841 }, 842 "TwoLorentzianModel", 813 } 843 814 ], 844 815 "two_power_law": [ 845 "TwoPowerLaw ",816 "TwoPowerLawModel", 846 817 { 847 818 "coefficent_1": "coef_A", … … 850 821 "background": "background", 851 822 "crossover": "qc" 852 }, 853 "TwoPowerLawModel", 823 } 854 824 ], 855 825 "unified_power_Rg": [ 856 "UnifiedPowerRg",857 dict(((field_new+str(index), field_old+str(index))858 for field_new, field_old in [("rg", "Rg"),859 ("power", "power"),860 ("G", "G"),861 ("B", "B"),]862 for index in range(11)),863 **{864 "background": "background",865 "scale": "scale",866 }),867 826 "UnifiedPowerRgModel", 827 { 828 } 868 829 ], 869 830 "vesicle": [ … … 874 835 } 875 836 ] 876 }877 837 } -
sasmodels/convert.py
r07c8d46 rf80f334 53 53 ("_pd_nsigma", ".nsigmas"), 54 54 ("_pd_type", ".type"), 55 (".lower", ".lower"),56 (".upper", ".upper"),57 (".fittable", ".fittable"),58 (".std", ".std"),59 (".units", ".units"),60 ("", "")61 55 ] 62 56 … … 70 64 if id.startswith('M0:'): 71 65 return True 66 if id.startswith('volfraction') or id.startswith('radius_effective'): 67 return False 72 68 if '_pd' in id or '.' in id: 73 69 return False … … 79 75 if p.id == id: 80 76 return p.type == 'sld' 81 r eturn False77 raise ValueError("unknown parameter %r in conversion"%id) 82 78 83 79 def _rescale_sld(model_info, pars, scale): … … 92 88 93 89 94 def _get_translation_table(model_info , version=(3,1,2)):95 conv_param = CONVERSION_TABLE.get(version, {}).get(model_info.id, [None, {}])96 translation = conv_param[1].copy()90 def _get_translation_table(model_info): 91 _, translation = CONVERSION_TABLE.get(model_info.id, [None, {}]) 92 translation = translation.copy() 97 93 for p in model_info.parameters.kernel_parameters: 98 94 if p.length > 1: … … 123 119 def _pd_to_underscores(pars): 124 120 return dict((_dot_pd_to_underscore_pd(k), v) for k, v in pars.items()) 121 122 def _convert_name(conv_dict, pars): 123 """ 124 Renames parameter values (upper, lower, etc) to v4.0 names 125 :param conv_dict: conversion dictionary mapping new name : old name 126 :param pars: parameters to convert 127 :return: 128 """ 129 new_pars = {} 130 i = 0 131 j = 0 132 for key_par, value_par in pars.iteritems(): 133 j += 1 134 for key_conv, value_conv in conv_dict.iteritems(): 135 if re.search(value_conv, key_par): 136 new_pars[key_par.replace(value_conv, key_conv)] = value_par 137 i += 1 138 break 139 elif re.search("background", key_par) or re.search("scale", key_par): 140 new_pars[key_par] = value_par 141 i += 1 142 break 143 if i != j: 144 new_pars[key_par] = value_par 145 i += 1 146 return new_pars 125 147 126 148 def _convert_pars(pars, mapping): … … 145 167 return newpars 146 168 147 def _conversion_target(model_name, version=(3,1,2)): 169 170 def _conversion_target(model_name): 148 171 """ 149 172 Find the sasmodel name which translates into the sasview name. … … 153 176 two variants in sasview. 154 177 """ 155 for sasmodels_name, sasview_dict in \ 156 CONVERSION_TABLE.get(version, {}).items(): 157 if sasview_dict[0] == model_name: 178 for sasmodels_name, [sasview_name, _] in CONVERSION_TABLE.items(): 179 if sasview_name == model_name: 158 180 return sasmodels_name 159 181 return None 160 182 161 def _hand_convert(name, oldpars, version=(3,1,2)): 162 if version == (3,1,2): 163 oldpars = _hand_convert_3_1_2_to_4_1(name, oldpars) 164 return oldpars 165 166 def _hand_convert_3_1_2_to_4_1(name, oldpars): 183 184 def _hand_convert(name, oldpars): 167 185 if name == 'core_shell_parallelepiped': 168 186 # Make sure pd on rim parameters defaults to zero … … 197 215 pd = oldpars['radius.width']*oldpars['radius']/thickness 198 216 oldpars['radius.width'] = pd 199 elif name == 'multilayer_vesicle':200 if 'scale' in oldpars:201 oldpars['volfraction'] = oldpars['scale']202 oldpars['scale'] = 1.0203 if 'scale.lower' in oldpars:204 oldpars['volfraction.lower'] = oldpars['scale.lower']205 if 'scale.upper' in oldpars:206 oldpars['volfraction.upper'] = oldpars['scale.upper']207 if 'scale.fittable' in oldpars:208 oldpars['volfraction.fittable'] = oldpars['scale.fittable']209 if 'scale.std' in oldpars:210 oldpars['volfraction.std'] = oldpars['scale.std']211 if 'scale.units' in oldpars:212 oldpars['volfraction.units'] = oldpars['scale.units']213 217 elif name == 'pearl_necklace': 214 218 pass … … 232 236 oldpars[p + ".upper"] /= 1e-13 233 237 elif name == 'spherical_sld': 234 j = 0 235 while "func_inter" + str(j) in oldpars: 236 name = "func_inter" + str(j) 237 new_name = "shape" + str(j + 1) 238 if oldpars[name] == 'Erf(|nu|*z)': 239 oldpars[new_name] = int(0) 240 elif oldpars[name] == 'RPower(z^|nu|)': 241 oldpars[new_name] = int(1) 242 elif oldpars[name] == 'LPower(z^|nu|)': 243 oldpars[new_name] = int(2) 244 elif oldpars[name] == 'RExp(-|nu|*z)': 245 oldpars[new_name] = int(3) 246 elif oldpars[name] == 'LExp(-|nu|*z)': 247 oldpars[new_name] = int(4) 248 else: 249 oldpars[new_name] = int(0) 250 oldpars.pop(name) 251 oldpars['n_shells'] = str(j + 1) 252 j += 1 238 oldpars["CONTROL"] += 1 253 239 elif name == 'teubner_strey': 254 240 # basically undoing the entire Teubner-Strey calculations here. … … 295 281 return oldpars 296 282 297 def convert_model(name, pars, use_underscore=False , model_version=(3,1,2)):283 def convert_model(name, pars, use_underscore=False): 298 284 """ 299 285 Convert model from old style parameter names to new style. 300 286 """ 301 newpars = pars 302 keys = sorted(CONVERSION_TABLE.keys()) 303 for i, version in enumerate(keys): 304 # Don't allow indices outside list 305 next_i = i + 1 306 if next_i == len(keys): 307 next_i = i 308 # If the save state is from a later version, skip the check 309 if model_version <= keys[next_i]: 310 newname = _conversion_target(name, version) 311 else: 312 newname = None 313 # If no conversion is found, move on 314 if newname is None: 315 newname = name 316 continue 317 if ':' in newname: # core_shell_ellipsoid:1 318 model_info = load_model_info(newname[:-2]) 319 # Know the table exists and isn't multiplicity so grab it directly 320 # Can't use _get_translation_table since that will return the 'bare' 321 # version. 322 translation = CONVERSION_TABLE.get(version, {})[newname][1] 323 else: 324 model_info = load_model_info(newname) 325 translation = _get_translation_table(model_info, version) 326 newpars = _hand_convert(newname, newpars, version) 327 newpars = _convert_pars(newpars, translation) 328 # TODO: Still not convinced this is the best check 329 if not model_info.structure_factor and version == (3,1,2): 330 newpars = _rescale_sld(model_info, newpars, 1e6) 331 newpars.setdefault('scale', 1.0) 332 newpars.setdefault('background', 0.0) 333 if use_underscore: 334 newpars = _pd_to_underscores(newpars) 335 name = newname 287 newname = _conversion_target(name) 288 if newname is None: 289 return name, pars 290 if ':' in newname: # core_shell_ellipsoid:1 291 model_info = load_model_info(newname[:-2]) 292 # Know that the table exists and isn't multiplicity so grab it directly 293 # Can't use _get_translation_table since that will return the 'bare' 294 # version. 295 translation = CONVERSION_TABLE[newname][1] 296 else: 297 model_info = load_model_info(newname) 298 translation = _get_translation_table(model_info) 299 newpars = _hand_convert(newname, pars.copy()) 300 newpars = _convert_name(translation, newpars) 301 newpars = _convert_pars(newpars, translation) 302 if not model_info.structure_factor: 303 newpars = _rescale_sld(model_info, newpars, 1e6) 304 newpars.setdefault('scale', 1.0) 305 newpars.setdefault('background', 0.0) 306 if use_underscore: 307 newpars = _pd_to_underscores(newpars) 336 308 return newname, newpars 309 337 310 338 311 # ========= BACKWARD CONVERSION sasmodels => sasview 3.x =========== -
sasmodels/kernelcl.py
rb8ddf2e r7fcdc9f 465 465 # architectures tested so far. 466 466 if self.is_2d: 467 # Note: 16 rather than 15 because result is 1 longer than input. 468 width = ((self.nq+16)//16)*16 467 # Note: 17 rather than 15 because results is 2 elements 468 # longer than input. 469 width = ((self.nq+17)//16)*16 469 470 self.q = np.empty((width, 2), dtype=dtype) 470 471 self.q[:self.nq, 0] = q_vectors[0] 471 472 self.q[:self.nq, 1] = q_vectors[1] 472 473 else: 473 # Note: 32 rather than 31 because result is 1 longer than input. 474 width = ((self.nq+32)//32)*32 474 # Note: 33 rather than 31 because results is 2 elements 475 # longer than input. 476 width = ((self.nq+33)//32)*32 475 477 self.q = np.empty(width, dtype=dtype) 476 478 self.q[:self.nq] = q_vectors[0] … … 522 524 self.dim = '2d' if q_input.is_2d else '1d' 523 525 # plus three for the normalization values 524 self.result = np.empty(q_input.nq+ 1, dtype)526 self.result = np.empty(q_input.nq+3, dtype) 525 527 526 528 # Inputs and outputs for each kernel call -
sasmodels/models/ellipsoid.c
r130d4c7 r925ad6e 4 4 double radius_polar, double radius_equatorial, double theta, double phi); 5 5 6 static double 7 _ellipsoid_kernel(double q, double radius_polar, double radius_equatorial, double cos_alpha)6 double _ellipsoid_kernel(double q, double radius_polar, double radius_equatorial, double sin_alpha); 7 double _ellipsoid_kernel(double q, double radius_polar, double radius_equatorial, double sin_alpha) 8 8 { 9 9 double ratio = radius_polar/radius_equatorial; 10 // Using ratio v = Rp/Re, we can expand the following to match the 11 // form given in Guinier (1955) 12 // r = Re * sqrt(1 + cos^2(T) (v^2 - 1)) 13 // = Re * sqrt( (1 - cos^2(T)) + v^2 cos^2(T) ) 14 // = Re * sqrt( sin^2(T) + v^2 cos^2(T) ) 15 // = sqrt( Re^2 sin^2(T) + Rp^2 cos^2(T) ) 16 // 10 // Given the following under the radical: 11 // 1 + sin^2(T) (v^2 - 1) 12 // we can expand to match the form given in Guinier (1955) 13 // = (1 - sin^2(T)) + v^2 sin^2(T) = cos^2(T) + sin^2(T) 17 14 // Instead of using pythagoras we could pass in sin and cos; this may be 18 15 // slightly better for 2D which has already computed it, but it introduces … … 20 17 // leave it as is. 21 18 const double r = radius_equatorial 22 * sqrt(1.0 + cos_alpha*cos_alpha*(ratio*ratio - 1.0));19 * sqrt(1.0 + sin_alpha*sin_alpha*(ratio*ratio - 1.0)); 23 20 const double f = sas_3j1x_x(q*r); 24 21 … … 42 39 double total = 0.0; 43 40 for (int i=0;i<76;i++) { 44 //const double cos_alpha = (Gauss76Z[i]*(upper-lower) + upper + lower)/2;45 const double cos_alpha = Gauss76Z[i]*zm + zb;46 total += Gauss76Wt[i] * _ellipsoid_kernel(q, radius_polar, radius_equatorial, cos_alpha);41 //const double sin_alpha = (Gauss76Z[i]*(upper-lower) + upper + lower)/2; 42 const double sin_alpha = Gauss76Z[i]*zm + zb; 43 total += Gauss76Wt[i] * _ellipsoid_kernel(q, radius_polar, radius_equatorial, sin_alpha); 47 44 } 48 45 // translate dx in [-1,1] to dx in [lower,upper] … … 62 59 double q, sin_alpha, cos_alpha; 63 60 ORIENT_SYMMETRIC(qx, qy, theta, phi, q, sin_alpha, cos_alpha); 64 const double form = _ellipsoid_kernel(q, radius_polar, radius_equatorial, cos_alpha);61 const double form = _ellipsoid_kernel(q, radius_polar, radius_equatorial, sin_alpha); 65 62 const double s = (sld - sld_solvent) * form_volume(radius_polar, radius_equatorial); 66 63 -
sasmodels/models/hayter_msa.c
r3fc5d27 r4962519 70 70 SofQ=sqhcal(Qdiam, gMSAWave); 71 71 }else{ 72 SofQ=NAN; 72 //SofQ=NaN; 73 SofQ=-1.0; 73 74 // print "Error Level = ",ierr 74 75 // print "Please report HPMSA problem with above error code" -
sasmodels/models/rpa.c
racfb094 r6351bfa 39 39 double S31,S32,S33,S34,S41,S42,S43,S44; 40 40 double Lad,Lbd,Lcd,Nav,Intg; 41 42 // Set values for non existent parameters (eg. no A or B in case 0 and 1 etc) 41 43 42 //icase was shifted to N-1 from the original code 44 43 if (icase <= 1){ … … 58 57 Kab = Kac = Kad = -0.0004; 59 58 } 60 61 // Set volume fraction of component D based on constraint that sum of vol frac =1 62 Phi[3]=1.0-Phi[0]-Phi[1]-Phi[2]; 63 64 //set up values for cross terms in case of block copolymers (1,3,4,6,7,8,9) 59 65 60 Nab=sqrt(N[0]*N[1]); 66 61 Nac=sqrt(N[0]*N[2]); … … 84 79 Phicd=sqrt(Phi[2]*Phi[3]); 85 80 86 // Calculate Q^2 * Rg^2 for each homopolymer assuming random walk87 81 Xa=q*q*b[0]*b[0]*N[0]/6.0; 88 82 Xb=q*q*b[1]*b[1]*N[1]/6.0; … … 90 84 Xd=q*q*b[3]*b[3]*N[3]/6.0; 91 85 92 //calculate all partial structure factors Pij and normalize n^2 93 Paa=2.0*(exp(-Xa)-1.0+Xa)/(Xa*Xa); // free A chain form factor 94 S0aa=N[0]*Phi[0]*v[0]*Paa; // Phi * Vp * P(Q)= I(Q0)/delRho^2 95 Pab=((1.0-exp(-Xa))/Xa)*((1.0-exp(-Xb))/Xb); //AB diblock (anchored Paa * anchored Pbb) partial form factor 86 Paa=2.0*(exp(-Xa)-1.0+Xa)/(Xa*Xa); 87 S0aa=N[0]*Phi[0]*v[0]*Paa; 88 Pab=((1.0-exp(-Xa))/Xa)*((1.0-exp(-Xb))/Xb); 96 89 S0ab=(Phiab*vab*Nab)*Pab; 97 Pac=((1.0-exp(-Xa))/Xa)*exp(-Xb)*((1.0-exp(-Xc))/Xc); //ABC triblock AC partial form factor90 Pac=((1.0-exp(-Xa))/Xa)*exp(-Xb)*((1.0-exp(-Xc))/Xc); 98 91 S0ac=(Phiac*vac*Nac)*Pac; 99 Pad=((1.0-exp(-Xa))/Xa)*exp(-Xb-Xc)*((1.0-exp(-Xd))/Xd); //ABCD four block92 Pad=((1.0-exp(-Xa))/Xa)*exp(-Xb-Xc)*((1.0-exp(-Xd))/Xd); 100 93 S0ad=(Phiad*vad*Nad)*Pad; 101 94 102 95 S0ba=S0ab; 103 Pbb=2.0*(exp(-Xb)-1.0+Xb)/(Xb*Xb); // free B chain96 Pbb=2.0*(exp(-Xb)-1.0+Xb)/(Xb*Xb); 104 97 S0bb=N[1]*Phi[1]*v[1]*Pbb; 105 Pbc=((1.0-exp(-Xb))/Xb)*((1.0-exp(-Xc))/Xc); // BC diblock98 Pbc=((1.0-exp(-Xb))/Xb)*((1.0-exp(-Xc))/Xc); 106 99 S0bc=(Phibc*vbc*Nbc)*Pbc; 107 Pbd=((1.0-exp(-Xb))/Xb)*exp(-Xc)*((1.0-exp(-Xd))/Xd); // BCD triblock100 Pbd=((1.0-exp(-Xb))/Xb)*exp(-Xc)*((1.0-exp(-Xd))/Xd); 108 101 S0bd=(Phibd*vbd*Nbd)*Pbd; 109 102 110 103 S0ca=S0ac; 111 104 S0cb=S0bc; 112 Pcc=2.0*(exp(-Xc)-1.0+Xc)/(Xc*Xc); // Free C chain105 Pcc=2.0*(exp(-Xc)-1.0+Xc)/(Xc*Xc); 113 106 S0cc=N[2]*Phi[2]*v[2]*Pcc; 114 Pcd=((1.0-exp(-Xc))/Xc)*((1.0-exp(-Xd))/Xd); // CD diblock107 Pcd=((1.0-exp(-Xc))/Xc)*((1.0-exp(-Xd))/Xd); 115 108 S0cd=(Phicd*vcd*Ncd)*Pcd; 116 109 … … 118 111 S0db=S0bd; 119 112 S0dc=S0cd; 120 Pdd=2.0*(exp(-Xd)-1.0+Xd)/(Xd*Xd); // free D chain113 Pdd=2.0*(exp(-Xd)-1.0+Xd)/(Xd*Xd); 121 114 S0dd=N[3]*Phi[3]*v[3]*Pdd; 122 123 // Reset all unused partial structure factors to 0 (depends on case)124 115 //icase was shifted to N-1 from the original code 125 116 switch(icase){ … … 202 193 S0dc=S0cd; 203 194 204 // self chi parameter is 0 ... of course205 195 Kaa=0.0; 206 196 Kbb=0.0; … … 253 243 ZZ=S0ad*(T11*S0ad+T12*S0bd+T13*S0cd)+S0bd*(T21*S0ad+T22*S0bd+T23*S0cd)+S0cd*(T31*S0ad+T32*S0bd+T33*S0cd); 254 244 255 // D is considered the matrix or background component so enters here256 245 m=1.0/(S0dd-ZZ); 257 246 … … 308 297 S44=S11+S22+S33+2.0*S12+2.0*S13+2.0*S23; 309 298 310 //calculate contrast where L[i] is the scattering length of i and D is the matrix311 //need to verify why the sqrt of Nav rather than just Nav (assuming v is molar volume)312 299 Nav=6.022045e+23; 313 300 Lad=(L[0]/v[0]-L[3]/v[3])*sqrt(Nav); … … 316 303 317 304 Intg=Lad*Lad*S11+Lbd*Lbd*S22+Lcd*Lcd*S33+2.0*Lad*Lbd*S12+2.0*Lbd*Lcd*S23+2.0*Lad*Lcd*S13; 318 319 //rescale for units of Lij^2 (in 10e-12 m^2 to m^2 ?)320 Intg *= 1.0e-24;321 305 322 306 return Intg; -
sasmodels/models/rpa.py
rbb73096 r40a87fa 107 107 108 108 control = "case_num" 109 HIDE_ ALL = set("Phi4".split())110 HIDE_A = set("N1 Phi1 v1 L1 b1 K12 K13 K14".split()) .union(HIDE_ALL)109 HIDE_NONE = set() 110 HIDE_A = set("N1 Phi1 v1 L1 b1 K12 K13 K14".split()) 111 111 HIDE_AB = set("N2 Phi2 v2 L2 b2 K23 K24".split()).union(HIDE_A) 112 112 def hidden(case_num): … … 119 119 return HIDE_A 120 120 else: 121 return HIDE_ ALL121 return HIDE_NONE 122 122 -
sasmodels/sasview_model.py
r749a7d4 r64614ad 16 16 import logging 17 17 from os.path import basename, splitext 18 import thread19 18 20 19 import numpy as np # type: ignore … … 40 39 pass 41 40 42 calculation_lock = thread.allocate_lock()43 44 41 SUPPORT_OLD_STYLE_PLUGINS = True 45 42 … … 60 57 import sas.models 61 58 from sasmodels.conversion_table import CONVERSION_TABLE 62 for new_name, conversion in CONVERSION_TABLE. get((3,1,2), {}).items():59 for new_name, conversion in CONVERSION_TABLE.items(): 63 60 # CoreShellEllipsoidModel => core_shell_ellipsoid:1 64 61 new_name = new_name.split(':')[0] 65 old_name = conversion[0] if len(conversion) < 3 else conversion[2]62 old_name = conversion[0] 66 63 module_attrs = {old_name: find_model(new_name)} 67 64 ConstructedModule = type(old_name, (), module_attrs) … … 608 605 to the card for each evaluation. 609 606 """ 610 ## uncomment the following when trying to debug the uncoordinated calls611 ## to calculate_Iq612 #if calculation_lock.locked():613 # logging.info("calculation waiting for another thread to complete")614 # logging.info("\n".join(traceback.format_stack()))615 616 with calculation_lock:617 return self._calculate_Iq(qx, qy)618 619 def _calculate_Iq(self, qx, qy=None):620 607 #core.HAVE_OPENCL = False 621 608 if self._model is None: … … 734 721 return [self.params[par.name]], [1.0] 735 722 736 def test_ cylinder():723 def test_model(): 737 724 # type: () -> float 738 725 """ 739 Test that the cylinder model runs, returning the value at [0.1,0.1].726 Test that a sasview model (cylinder) can be run. 740 727 """ 741 728 Cylinder = _make_standard_model('cylinder') … … 746 733 # type: () -> float 747 734 """ 748 Test that 2-D hardsphere model runs and doesn't produce NaN.735 Test that a sasview model (cylinder) can be run. 749 736 """ 750 737 Model = _make_standard_model('hardsphere') … … 757 744 # type: () -> float 758 745 """ 759 Test that the 2-D RPA model runs746 Test that a sasview model (cylinder) can be run. 760 747 """ 761 748 RPA = _make_standard_model('rpa') … … 763 750 return rpa.evalDistribution([0.1, 0.1]) 764 751 765 def test_empty_distribution():766 # type: () -> None767 """768 Make sure that sasmodels returns NaN when there are no polydispersity points769 """770 Cylinder = _make_standard_model('cylinder')771 cylinder = Cylinder()772 cylinder.setParam('radius', -1.0)773 cylinder.setParam('background', 0.)774 Iq = cylinder.evalDistribution(np.asarray([0.1]))775 assert np.isnan(Iq[0]), "empty distribution fails"776 752 777 753 def test_model_list(): 778 754 # type: () -> None 779 755 """ 780 Make sure that all models build as sasview models 756 Make sure that all models build as sasview models. 781 757 """ 782 758 from .exception import annotate_exception … … 805 781 806 782 if __name__ == "__main__": 807 print("cylinder(0.1,0.1)=%g"%test_cylinder()) 808 #test_empty_distribution() 783 print("cylinder(0.1,0.1)=%g"%test_model()) -
sasmodels/sesans.py
r94d13f1 rb397165 14 14 import numpy as np # type: ignore 15 15 from numpy import pi, exp # type: ignore 16 from scipy.special import j0 17 18 class SesansTransform(object): 19 """ 20 Spin-Echo SANS transform calculator. Similar to a resolution function, 21 the SesansTransform object takes I(q) for the set of *q_calc* values and 22 produces a transformed dataset 23 24 *SElength* (A) is the set of spin-echo lengths in the measured data. 25 26 *zaccept* (1/A) is the maximum acceptance of scattering vector in the spin 27 echo encoding dimension (for ToF: Q of min(R) and max(lam)). 28 29 *Rmax* (A) is the maximum size sensitivity; larger radius requires more 30 computation time. 31 """ 32 #: SElength from the data in the original data units; not used by transform 33 #: but the GUI uses it, so make sure that it is present. 34 q = None # type: np.ndarray 35 36 #: q values to calculate when computing transform 37 q_calc = None # type: np.ndarray 38 39 # transform arrays 40 _H = None # type: np.ndarray 41 _H0 = None # type: np.ndarray 42 43 def __init__(self, z, SElength, zaccept, Rmax): 44 # type: (np.ndarray, float, float) -> None 45 #import logging; logging.info("creating SESANS transform") 46 self.q = z 47 self._set_hankel(SElength, zaccept, Rmax) 48 49 def apply(self, Iq): 50 # tye: (np.ndarray) -> np.ndarray 51 G0 = np.dot(self._H0, Iq) 52 G = np.dot(self._H.T, Iq) 53 P = G - G0 54 return P 55 56 def _set_hankel(self, SElength, zaccept, Rmax): 57 # type: (np.ndarray, float, float) -> None 58 # Force float32 arrays, otherwise run into memory problems on some machines 59 SElength = np.asarray(SElength, dtype='float32') 60 61 #Rmax = #value in text box somewhere in FitPage? 62 q_max = 2*pi / (SElength[1] - SElength[0]) 63 q_min = 0.1 * 2*pi / (np.size(SElength) * SElength[-1]) 64 q = np.arange(q_min, q_max, q_min, dtype='float32') 65 dq = q_min 66 67 H0 = np.float32(dq/(2*pi)) * q 68 69 repq = np.tile(q, (SElength.size, 1)).T 70 repSE = np.tile(SElength, (q.size, 1)) 71 H = np.float32(dq/(2*pi)) * j0(repSE*repq) * repq 72 73 self.q_calc = q 74 self._H, self._H0 = H, H0 16 from scipy.special import jv as besselj 17 #import direct_model.DataMixin as model 18 19 def make_q(q_max, Rmax): 20 r""" 21 Return a $q$ vector suitable for SESANS covering from $2\pi/ (10 R_{\max})$ 22 to $q_max$. This is the integration range of the Hankel transform; bigger range and 23 more points makes a better numerical integration. 24 Smaller q_min will increase reliable spin echo length range. 25 Rmax is the "radius" of the largest expected object and can be set elsewhere. 26 q_max is determined by the acceptance angle of the SESANS instrument. 27 """ 28 from sas.sascalc.data_util.nxsunit import Converter 29 30 q_min = dq = 0.1 * 2*pi / Rmax 31 return np.arange(q_min, 32 Converter(q_max[1])(q_max[0], 33 units="1/A"), 34 dq) 35 36 def make_all_q(data): 37 """ 38 Return a $q$ vector suitable for calculating the total scattering cross section for 39 calculating the effect of finite acceptance angles on Time of Flight SESANS instruments. 40 If no acceptance is given, or unwanted (set "unwanted" flag in paramfile), no all_q vector is needed. 41 If the instrument has a rectangular acceptance, 2 all_q vectors are needed. 42 If the instrument has a circular acceptance, 1 all_q vector is needed 43 44 """ 45 if not data.has_no_finite_acceptance: 46 return [] 47 elif data.has_yz_acceptance(data): 48 # compute qx, qy 49 Qx, Qy = np.meshgrid(qx, qy) 50 return [Qx, Qy] 51 else: 52 # else only need q 53 # data.has_z_acceptance 54 return [q] 55 56 def transform(data, q_calc, Iq_calc, qmono, Iq_mono): 57 """ 58 Decides which transform type is to be used, based on the experiment data file contents (header) 59 (2016-03-19: currently controlled from parameters script) 60 nqmono is the number of q vectors to be used for the detector integration 61 """ 62 nqmono = len(qmono) 63 if nqmono == 0: 64 result = call_hankel(data, q_calc, Iq_calc) 65 elif nqmono == 1: 66 q = qmono[0] 67 result = call_HankelAccept(data, q_calc, Iq_calc, q, Iq_mono) 68 else: 69 Qx, Qy = [qmono[0], qmono[1]] 70 Qx = np.reshape(Qx, nqx, nqy) 71 Qy = np.reshape(Qy, nqx, nqy) 72 Iq_mono = np.reshape(Iq_mono, nqx, nqy) 73 qx = Qx[0, :] 74 qy = Qy[:, 0] 75 result = call_Cosine2D(data, q_calc, Iq_calc, qx, qy, Iq_mono) 76 77 return result 78 79 def call_hankel(data, q_calc, Iq_calc): 80 return hankel((data.x, data.x_unit), 81 (data.lam, data.lam_unit), 82 (data.sample.thickness, 83 data.sample.thickness_unit), 84 q_calc, Iq_calc) 85 86 def call_HankelAccept(data, q_calc, Iq_calc, q_mono, Iq_mono): 87 return hankel(data.x, data.lam * 1e-9, 88 data.sample.thickness / 10, 89 q_calc, Iq_calc) 90 91 def call_Cosine2D(data, q_calc, Iq_calc, qx, qy, Iq_mono): 92 return hankel(data.x, data.y, data.lam * 1e-9, 93 data.sample.thickness / 10, 94 q_calc, Iq_calc) 95 96 def TotalScatter(model, parameters): #Work in progress!! 97 # Calls a model with existing model parameters already in place, then integrate the product of q and I(q) from 0 to (4*pi/lambda) 98 allq = np.linspace(0,4*pi/wavelength,1000) 99 allIq = 1 100 integral = allq*allIq 101 102 103 104 def Cosine2D(wavelength, magfield, thickness, qy, qz, Iqy, Iqz, modelname): #Work in progress!! Needs to call model still 105 #============================================================================== 106 # 2D Cosine Transform if "wavelength" is a vector 107 #============================================================================== 108 #allq is the q-space needed to create the total scattering cross-section 109 110 Gprime = np.zeros_like(wavelength, 'd') 111 s = np.zeros_like(wavelength, 'd') 112 sd = np.zeros_like(wavelength, 'd') 113 Gprime = np.zeros_like(wavelength, 'd') 114 f = np.zeros_like(wavelength, 'd') 115 for i, wavelength_i in enumerate(wavelength): 116 z = magfield*wavelength_i 117 allq=np.linspace() #for calculating the Q-range of the scattering power integral 118 allIq=np.linspace() # This is the model applied to the allq q-space. Needs to refference the model somehow 119 alldq = (allq[1]-allq[0])*1e10 120 sigma[i]=wavelength[i]^2*thickness/2/pi*np.sum(allIq*allq*alldq) 121 s[i]=1-exp(-sigma) 122 for j, Iqy_j, qy_j in enumerate(qy): 123 for k, Iqz_k, qz_k in enumerate(qz): 124 Iq = np.sqrt(Iqy_j^2+Iqz_k^2) 125 q = np.sqrt(qy_j^2 + qz_k^2) 126 Gintegral = Iq*cos(z*Qz_k) 127 Gprime[i] += Gintegral 128 # sigma = wavelength^2*thickness/2/pi* allq[i]*allIq[i] 129 # s[i] += 1-exp(Totalscatter(modelname)*thickness) 130 # For now, work with standard 2-phase scatter 131 132 133 sd[i] += Iq 134 f[i] = 1-s[i]+sd[i] 135 P[i] = (1-sd[i]/f[i])+1/f[i]*Gprime[i] 136 137 138 139 140 def HankelAccept(wavelength, magfield, thickness, q, Iq, theta, modelname): 141 #============================================================================== 142 # HankelTransform with fixed circular acceptance angle (circular aperture) for Time of Flight SESANS 143 #============================================================================== 144 #acceptq is the q-space needed to create limited acceptance effect 145 SElength= wavelength*magfield 146 G = np.zeros_like(SElength, 'd') 147 threshold=2*pi*theta/wavelength 148 for i, SElength_i in enumerate(SElength): 149 allq=np.linspace() #for calculating the Q-range of the scattering power integral 150 allIq=np.linspace() # This is the model applied to the allq q-space. Needs to refference the model somehow 151 alldq = (allq[1]-allq[0])*1e10 152 sigma[i]=wavelength[i]^2*thickness/2/pi*np.sum(allIq*allq*alldq) 153 s[i]=1-exp(-sigma) 154 155 dq = (q[1]-q[0])*1e10 156 a = (x<threshold) 157 acceptq = a*q 158 acceptIq = a*Iq 159 160 G[i] = np.sum(besselj(0, acceptq*SElength_i)*acceptIq*acceptq*dq) 161 162 # G[i]=np.sum(integral) 163 164 G *= dq*1e10*2*pi 165 166 P = exp(thickness*wavelength**2/(4*pi**2)*(G-G[0])) 167 168 def hankel(SElength, wavelength, thickness, q, Iq): 169 r""" 170 Compute the expected SESANS polarization for a given SANS pattern. 171 172 Uses the hankel transform followed by the exponential. The values for *zz* 173 (or spin echo length, or delta), wavelength and sample thickness should 174 come from the dataset. $q$ should be chosen such that the oscillations 175 in $I(q)$ are well sampled (e.g., $5 \cdot 2 \pi/d_{\max}$). 176 177 *SElength* [A] is the set of $z$ points at which to compute the 178 Hankel transform 179 180 *wavelength* [m] is the wavelength of each individual point *zz* 181 182 *thickness* [cm] is the sample thickness. 183 184 *q* [A$^{-1}$] is the set of $q$ points at which the model has been 185 computed. These should be equally spaced. 186 187 *I* [cm$^{-1}$] is the value of the SANS model at *q* 188 """ 189 190 from sas.sascalc.data_util.nxsunit import Converter 191 wavelength = Converter(wavelength[1])(wavelength[0],"A") 192 thickness = Converter(thickness[1])(thickness[0],"A") 193 Iq = Converter("1/cm")(Iq,"1/A") # All models default to inverse centimeters 194 SElength = Converter(SElength[1])(SElength[0],"A") 195 196 G = np.zeros_like(SElength, 'd') 197 #============================================================================== 198 # Hankel Transform method if "wavelength" is a scalar; mono-chromatic SESANS 199 #============================================================================== 200 for i, SElength_i in enumerate(SElength): 201 integral = besselj(0, q*SElength_i)*Iq*q 202 G[i] = np.sum(integral) 203 G0 = np.sum(Iq*q) 204 205 # [m^-1] step size in q, needed for integration 206 dq = (q[1]-q[0]) 207 208 # integration step, convert q into [m**-1] and 2 pi circle integration 209 G *= dq*2*pi 210 G0 = np.sum(Iq*q)*dq*2*np.pi 211 212 P = exp(thickness*wavelength**2/(4*pi**2)*(G-G0)) 213 214 return P
Note: See TracChangeset
for help on using the changeset viewer.