Changeset 535fee6 in sasmodels
- Timestamp:
- Apr 12, 2017 4:40:40 AM (8 years ago)
- Branches:
- master, core_shell_microgels, magnetic_model, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
- Children:
- d4c33d6
- Parents:
- a0ebc96 (diff), 1a4d4c0 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - Files:
-
- 11 added
- 8 deleted
- 33 edited
Legend:
- Unmodified
- Added
- Removed
-
example/oriented_usans.py
rea75043 r1cd24b4 19 19 scale=0.08, background=0, 20 20 sld=.291, sld_solvent=7.105, 21 r _polar=1800, r_polar_pd=0.222296, r_polar_pd_n=0,22 r _equatorial=2600, r_equatorial_pd=0.28, r_equatorial_pd_n=0,21 radius_polar=1800, radius_polar_pd=0.222296, radius_polar_pd_n=0, 22 radius_equatorial=2600, radius_equatorial_pd=0.28, radius_equatorial_pd_n=0, 23 23 theta=60, theta_pd=0, theta_pd_n=0, 24 24 phi=60, phi_pd=0, phi_pd_n=0, … … 26 26 27 27 # SET THE FITTING PARAMETERS 28 model.r _polar.range(1000, 10000)29 model.r _equatorial.range(1000, 10000)28 model.radius_polar.range(1000, 10000) 29 model.radius_equatorial.range(1000, 10000) 30 30 model.theta.range(0, 360) 31 31 model.phi.range(0, 360) -
sasmodels/data.py
ra769b54 r09e9e13 450 450 if view is 'log': 451 451 mtheory[mtheory <= 0] = masked 452 plt.plot(data.x, scale*mtheory, '-' , hold=True)452 plt.plot(data.x, scale*mtheory, '-') 453 453 all_positive = all_positive and (mtheory > 0).all() 454 454 some_present = some_present or (mtheory.count() > 0) … … 457 457 plt.ylim(*limits) 458 458 459 plt.xscale('linear' if not some_present or non_positive_x else view) 459 plt.xscale('linear' if not some_present or non_positive_x 460 else view if view is not None 461 else 'log') 460 462 plt.yscale('linear' 461 463 if view == 'q4' or not some_present or not all_positive 462 else view) 464 else view if view is not None 465 else 'log') 463 466 plt.xlabel("$q$/A$^{-1}$") 464 467 plt.ylabel('$I(q)$') 468 title = ("data and model" if use_theory and use_data 469 else "data" if use_data 470 else "model") 471 plt.title(title) 465 472 466 473 if use_calc: … … 482 489 if num_plots > 1: 483 490 plt.subplot(1, num_plots, use_calc + 2) 484 plt.plot(data.x, mresid, ' -')491 plt.plot(data.x, mresid, '.') 485 492 plt.xlabel("$q$/A$^{-1}$") 486 493 plt.ylabel('residuals') 487 plt.xscale('linear' if not some_present or non_positive_x else view) 494 plt.xscale('linear') 495 plt.title('(model - Iq)/dIq') 488 496 489 497 … … 512 520 if theory is not None: 513 521 if is_tof: 514 plt.plot(data.x, np.log(theory)/(data.lam*data.lam), '-' , hold=True)522 plt.plot(data.x, np.log(theory)/(data.lam*data.lam), '-') 515 523 else: 516 plt.plot(data.x, theory, '-' , hold=True)524 plt.plot(data.x, theory, '-') 517 525 if limits is not None: 518 526 plt.ylim(*limits) -
sasmodels/models/onion.py
rc3ccaec rbccb40f 1 1 r""" 2 2 This model provides the form factor, $P(q)$, for a multi-shell sphere where 3 the scattering length density (SLD) of theeach shell is described by an3 the scattering length density (SLD) of each shell is described by an 4 4 exponential, linear, or constant function. The form factor is normalized by 5 5 the volume of the sphere where the SLD is not identical to the SLD of the … … 142 142 143 143 For $A = 0$, the exponential function has no dependence on the radius (so that 144 $\rho_\text{out}$ is ignored this case) and becomes flat. We set the constant144 $\rho_\text{out}$ is ignored in this case) and becomes flat. We set the constant 145 145 to $\rho_\text{in}$ for convenience, and thus the form factor contributed by 146 146 the shells is … … 346 346 # flat shell 347 347 z.append(z_current + thickness[k]) 348 rho.append(sld_ out[k])348 rho.append(sld_in[k]) 349 349 else: 350 350 # exponential shell … … 357 357 z.append(z_current+z_shell) 358 358 rho.append(slope*exp(A[k]*z_shell/thickness[k]) + const) 359 359 360 360 # add in the solvent 361 361 z.append(z[-1]) -
explore/angular_pd.py
r12eb36b r8267e0b 47 47 48 48 def draw_mesh_new(ax, theta, dtheta, phi, dphi, flow, radius=10., dist='gauss'): 49 theta_center = radians( theta)49 theta_center = radians(90-theta) 50 50 phi_center = radians(phi) 51 51 flow_center = radians(flow) … … 137 137 radius=11., dist=dist) 138 138 if not axis.startswith('d'): 139 ax.view_init(elev= theta, azim=phi)139 ax.view_init(elev=90-theta if use_new else theta, azim=phi) 140 140 plt.gcf().canvas.draw() 141 141 -
sasmodels/compare.py
r650c6d2 re6ab0d3 84 84 -edit starts the parameter explorer 85 85 -default/-demo* use demo vs default parameters 86 -h tml shows the model docs instead of running the model86 -help/-html shows the model docs instead of running the model 87 87 -title="note" adds note to the plot title, after the model name 88 88 -data="path" uses q, dq from the data file … … 836 836 'linear', 'log', 'q4', 837 837 'hist', 'nohist', 838 'edit', 'html', 838 'edit', 'html', 'help', 839 839 'demo', 'default', 840 840 ]) … … 1005 1005 elif arg == '-default': opts['use_demo'] = False 1006 1006 elif arg == '-html': opts['html'] = True 1007 elif arg == '-help': opts['html'] = True 1007 1008 # pylint: enable=bad-whitespace 1008 1009 -
sasmodels/kernel_header.c
rdaeef4c rb00a646 148 148 inline double sas_sinx_x(double x) { return x==0 ? 1.0 : sin(x)/x; } 149 149 150 // To rotate from the canonical position to theta, phi, psi, first rotate by 151 // psi about the major axis, oriented along z, which is a rotation in the 152 // detector plane xy. Next rotate by theta about the y axis, aligning the major 153 // axis in the xz plane. Finally, rotate by phi in the detector plane xy. 154 // To compute the scattering, undo these rotations in reverse order: 155 // rotate in xy by -phi, rotate in xz by -theta, rotate in xy by -psi 156 // The returned q is the length of the q vector and (xhat, yhat, zhat) is a unit 157 // vector in the q direction. 158 // To change between counterclockwise and clockwise rotation, change the 159 // sign of phi and psi. 160 150 161 #if 1 151 162 //think cos(theta) should be sin(theta) in new coords, RKH 11Jan2017 … … 166 177 #endif 167 178 179 #if 1 180 #define ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, xhat, yhat, zhat) do { \ 181 q = sqrt(qx*qx + qy*qy); \ 182 const double qxhat = qx/q; \ 183 const double qyhat = qy/q; \ 184 double sin_theta, cos_theta; \ 185 double sin_phi, cos_phi; \ 186 double sin_psi, cos_psi; \ 187 SINCOS(theta*M_PI_180, sin_theta, cos_theta); \ 188 SINCOS(phi*M_PI_180, sin_phi, cos_phi); \ 189 SINCOS(psi*M_PI_180, sin_psi, cos_psi); \ 190 xhat = qxhat*(-sin_phi*sin_psi + cos_theta*cos_phi*cos_psi) \ 191 + qyhat*( cos_phi*sin_psi + cos_theta*sin_phi*cos_psi); \ 192 yhat = qxhat*(-sin_phi*cos_psi - cos_theta*cos_phi*sin_psi) \ 193 + qyhat*( cos_phi*cos_psi - cos_theta*sin_phi*sin_psi); \ 194 zhat = qxhat*(-sin_theta*cos_phi) \ 195 + qyhat*(-sin_theta*sin_phi); \ 196 } while (0) 197 #else 198 // SasView 3.x definition of orientation 168 199 #define ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, cos_alpha, cos_mu, cos_nu) do { \ 169 200 q = sqrt(qx*qx + qy*qy); \ … … 180 211 cos_nu = (-cos_phi*sin_psi*sin_theta + sin_phi*cos_psi)*qxhat + sin_psi*cos_theta*qyhat; \ 181 212 } while (0) 213 #endif -
sasmodels/models/barbell.py
rfcb33e4 r9802ab3 68 68 The 2D scattering intensity is calculated similar to the 2D cylinder model. 69 69 70 .. figure:: img/cylinder_angle_definition. jpg70 .. figure:: img/cylinder_angle_definition.png 71 71 72 72 Definition of the angles for oriented 2D barbells. … … 87 87 * **Last Reviewed by:** Richard Heenan **Date:** January 4, 2017 88 88 """ 89 from numpy import inf 89 from numpy import inf, sin, cos, pi 90 90 91 91 name = "barbell" … … 108 108 ["radius", "Ang", 20, [0, inf], "volume", "Cylindrical bar radius"], 109 109 ["length", "Ang", 400, [0, inf], "volume", "Cylinder bar length"], 110 ["theta", "degrees", 60, [- inf, inf], "orientation", "In planeangle"],111 ["phi", "degrees", 60, [- inf, inf], "orientation", "Out of plane angle"],110 ["theta", "degrees", 60, [-360, 360], "orientation", "Barbell axis to beam angle"], 111 ["phi", "degrees", 60, [-360, 360], "orientation", "Rotation about beam"], 112 112 ] 113 113 # pylint: enable=bad-whitespace, line-too-long … … 125 125 phi_pd=15, phi_pd_n=0, 126 126 ) 127 q = 0.1 128 # april 6 2017, rkh add unit tests, NOT compared with any other calc method, assume correct! 129 qx = q*cos(pi/6.0) 130 qy = q*sin(pi/6.0) 131 tests = [[{}, 0.075, 25.5691260532], 132 [{'theta':80., 'phi':10.}, (qx, qy), 3.04233067789], 133 ] 134 del qx, qy # not necessary to delete, but cleaner -
sasmodels/models/bcc_paracrystal.c
r4962519 r50beefe 90 90 double theta, double phi, double psi) 91 91 { 92 double q, cos_a1, cos_a2, cos_a3;93 ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, cos_a3, cos_a2, cos_a1);92 double q, zhat, yhat, xhat; 93 ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, xhat, yhat, zhat); 94 94 95 const double a1 = + cos_a3 - cos_a1 + cos_a2;96 const double a2 = + cos_a3 + cos_a1 - cos_a2;97 const double a3 = - cos_a3 + cos_a1 + cos_a2;95 const double a1 = +xhat - zhat + yhat; 96 const double a2 = +xhat + zhat - yhat; 97 const double a3 = -xhat + zhat + yhat; 98 98 99 99 const double qd = 0.5*q*dnn; -
sasmodels/models/bcc_paracrystal.py
r925ad6e r69e1afc 79 79 be accurate. 80 80 81 .. figure:: img/ bcc_angle_definition.png81 .. figure:: img/parallelepiped_angle_definition.png 82 82 83 Orientation of the crystal with respect to the scattering plane. 83 Orientation of the crystal with respect to the scattering plane, when 84 $\theta = \phi = 0$ the $c$ axis is along the beam direction (the $z$ axis). 84 85 85 86 References … … 99 100 """ 100 101 101 from numpy import inf 102 from numpy import inf, pi 102 103 103 104 name = "bcc_paracrystal" … … 122 123 ["sld", "1e-6/Ang^2", 4, [-inf, inf], "sld", "Particle scattering length density"], 123 124 ["sld_solvent", "1e-6/Ang^2", 1, [-inf, inf], "sld", "Solvent scattering length density"], 124 ["theta", "degrees", 60, [- inf, inf], "orientation", "In planeangle"],125 ["phi", "degrees", 60, [- inf, inf], "orientation", "Out of plane angle"],126 ["psi", "degrees", 60, [- inf, inf], "orientation", "Out of plane angle"]125 ["theta", "degrees", 60, [-360, 360], "orientation", "c axis to beam angle"], 126 ["phi", "degrees", 60, [-360, 360], "orientation", "rotation about beam"], 127 ["psi", "degrees", 60, [-360, 360], "orientation", "rotation about c axis"] 127 128 ] 128 129 # pylint: enable=bad-whitespace, line-too-long … … 141 142 psi_pd=15, psi_pd_n=0, 142 143 ) 144 # april 6 2017, rkh add unit tests, NOT compared with any other calc method, assume correct! 145 # add 2d test later 146 q =4.*pi/220. 147 tests = [ 148 [{ }, 149 [0.001, q, 0.215268], [1.46601394721, 2.85851284174, 0.00866710287078]], 150 [{'theta':20.0,'phi':30,'psi':40.0},(-0.017,0.035),2082.20264399 ], 151 [{'theta':20.0,'phi':30,'psi':40.0},(-0.081,0.011),0.436323144781 ] 152 ] -
sasmodels/models/capped_cylinder.py
rfcb33e4 r9802ab3 71 71 The 2D scattering intensity is calculated similar to the 2D cylinder model. 72 72 73 .. figure:: img/cylinder_angle_definition. jpg73 .. figure:: img/cylinder_angle_definition.png 74 74 75 75 Definition of the angles for oriented 2D cylinders. … … 91 91 92 92 """ 93 from numpy import inf 93 from numpy import inf, sin, cos, pi 94 94 95 95 name = "capped_cylinder" … … 129 129 ["radius_cap", "Ang", 20, [0, inf], "volume", "Cap radius"], 130 130 ["length", "Ang", 400, [0, inf], "volume", "Cylinder length"], 131 ["theta", "degrees", 60, [- inf, inf], "orientation", "inclinationangle"],132 ["phi", "degrees", 60, [- inf, inf], "orientation", "deflection angle"],131 ["theta", "degrees", 60, [-360, 360], "orientation", "cylinder axis to beam angle"], 132 ["phi", "degrees", 60, [-360, 360], "orientation", "rotation about beam"], 133 133 ] 134 134 # pylint: enable=bad-whitespace, line-too-long … … 145 145 theta_pd=15, theta_pd_n=45, 146 146 phi_pd=15, phi_pd_n=1) 147 q = 0.1 148 # april 6 2017, rkh add unit tests, NOT compared with any other calc method, assume correct! 149 qx = q*cos(pi/6.0) 150 qy = q*sin(pi/6.0) 151 tests = [[{}, 0.075, 26.0698570695], 152 [{'theta':80., 'phi':10.}, (qx, qy), 0.561811990502], 153 ] 154 del qx, qy # not necessary to delete, but cleaner -
sasmodels/models/core_shell_bicelle.c
r592343f rb260926 30 30 31 31 static double 32 bicelle_kernel(double q q,32 bicelle_kernel(double q, 33 33 double rad, 34 34 double radthick, 35 35 double facthick, 36 double length,36 double halflength, 37 37 double rhoc, 38 38 double rhoh, … … 42 42 double cos_alpha) 43 43 { 44 double si1,si2,be1,be2;45 46 44 const double dr1 = rhoc-rhoh; 47 45 const double dr2 = rhor-rhosolv; 48 46 const double dr3 = rhoh-rhor; 49 const double vol1 = M_PI*rad*rad*(2.0*length); 50 const double vol2 = M_PI*(rad+radthick)*(rad+radthick)*2.0*(length+facthick); 51 const double vol3 = M_PI*rad*rad*2.0*(length+facthick); 52 double besarg1 = qq*rad*sin_alpha; 53 double besarg2 = qq*(rad+radthick)*sin_alpha; 54 double sinarg1 = qq*length*cos_alpha; 55 double sinarg2 = qq*(length+facthick)*cos_alpha; 47 const double vol1 = M_PI*square(rad)*2.0*(halflength); 48 const double vol2 = M_PI*square(rad+radthick)*2.0*(halflength+facthick); 49 const double vol3 = M_PI*square(rad)*2.0*(halflength+facthick); 56 50 57 be1 = sas_2J1x_x(besarg1);58 be2 = sas_2J1x_x(besarg2);59 si1 = sas_sinx_x(sinarg1);60 si2 = sas_sinx_x(sinarg2);51 const double be1 = sas_2J1x_x(q*(rad)*sin_alpha); 52 const double be2 = sas_2J1x_x(q*(rad+radthick)*sin_alpha); 53 const double si1 = sas_sinx_x(q*(halflength)*cos_alpha); 54 const double si2 = sas_sinx_x(q*(halflength+facthick)*cos_alpha); 61 55 62 56 const double t = vol1*dr1*si1*be1 + … … 64 58 vol3*dr3*si2*be1; 65 59 66 const double retval = t*t *sin_alpha;60 const double retval = t*t; 67 61 68 62 return retval; … … 71 65 72 66 static double 73 bicelle_integration(double q q,67 bicelle_integration(double q, 74 68 double rad, 75 69 double radthick, … … 83 77 // set up the integration end points 84 78 const double uplim = M_PI_4; 85 const double half height= 0.5*length;79 const double halflength = 0.5*length; 86 80 87 81 double summ = 0.0; … … 90 84 double sin_alpha, cos_alpha; // slots to hold sincos function output 91 85 SINCOS(alpha, sin_alpha, cos_alpha); 92 double yyy = Gauss76Wt[i] * bicelle_kernel(q q, rad, radthick, facthick,93 half height, rhoc, rhoh, rhor, rhosolv,86 double yyy = Gauss76Wt[i] * bicelle_kernel(q, rad, radthick, facthick, 87 halflength, rhoc, rhoh, rhor, rhosolv, 94 88 sin_alpha, cos_alpha); 95 summ += yyy ;89 summ += yyy*sin_alpha; 96 90 } 97 91 … … 119 113 double answer = bicelle_kernel(q, radius, thick_rim, thick_face, 120 114 0.5*length, core_sld, face_sld, rim_sld, 121 solvent_sld, sin_alpha, cos_alpha) / fabs(sin_alpha); 122 123 answer *= 1.0e-4; 124 125 return answer; 115 solvent_sld, sin_alpha, cos_alpha); 116 return 1.0e-4*answer; 126 117 } 127 118 -
sasmodels/models/core_shell_bicelle.py
r3b9a526 r9802ab3 47 47 .. math:: 48 48 49 49 \begin{align} 50 50 F(Q,\alpha) = &\bigg[ 51 51 (\rho_c - \rho_f) V_c \frac{2J_1(QRsin \alpha)}{QRsin\alpha}\frac{sin(QLcos\alpha/2)}{Q(L/2)cos\alpha} \\ … … 63 63 cylinders is then given by integrating over all possible $\theta$ and $\phi$. 64 64 65 The *theta* and *phi* parameters are not used for the 1D output. 65 For oriented bicelles the *theta*, and *phi* orientation parameters will appear when fitting 2D data, 66 see the :ref:`cylinder` model for further information. 66 67 Our implementation of the scattering kernel and the 1D scattering intensity 67 68 use the c-library from NIST. 68 69 69 .. figure:: img/cylinder_angle_definition. jpg70 .. figure:: img/cylinder_angle_definition.png 70 71 71 Definition of the angles for the oriented core shell bicelle tmodel. 72 Definition of the angles for the oriented core shell bicelle model, 73 note that the cylinder axis of the bicelle starts along the beam direction 74 when $\theta = \phi = 0$. 72 75 73 76 … … 88 91 """ 89 92 90 from numpy import inf, sin, cos 93 from numpy import inf, sin, cos, pi 91 94 92 95 name = "core_shell_bicelle" … … 135 138 ["sld_rim", "1e-6/Ang^2", 4, [-inf, inf], "sld", "Cylinder rim scattering length density"], 136 139 ["sld_solvent", "1e-6/Ang^2", 1, [-inf, inf], "sld", "Solvent scattering length density"], 137 ["theta", "degrees", 90, [- inf, inf], "orientation", "In planeangle"],138 ["phi", "degrees", 0, [- inf, inf], "orientation", "Out of plane angle"],140 ["theta", "degrees", 90, [-360, 360], "orientation", "cylinder axis to beam angle"], 141 ["phi", "degrees", 0, [-360, 360], "orientation", "rotation about beam"] 139 142 ] 140 143 … … 155 158 theta=90, 156 159 phi=0) 160 q = 0.1 161 # april 6 2017, rkh add unit tests, NOT compared with any other calc method, assume correct! 162 qx = q*cos(pi/6.0) 163 qy = q*sin(pi/6.0) 164 tests = [[{}, 0.05, 7.4883545957], 165 [{'theta':80., 'phi':10.}, (qx, qy), 2.81048892474 ] 166 ] 167 del qx, qy # not necessary to delete, but cleaner 157 168 158 #qx, qy = 0.4 * cos(pi/2.0), 0.5 * sin(0) -
sasmodels/models/core_shell_bicelle_elliptical.c
r592343f rdedcf34 1 double form_volume(double radius, double x_core, double thick_rim, double thick_face, double length);2 double Iq(double q,3 double radius,4 double x_core,5 double thick_rim,6 double thick_face,7 double length,8 double core_sld,9 double face_sld,10 double rim_sld,11 double solvent_sld);12 13 14 double Iqxy(double qx, double qy,15 double radius,16 double x_core,17 double thick_rim,18 double thick_face,19 double length,20 double core_sld,21 double face_sld,22 double rim_sld,23 double solvent_sld,24 double theta,25 double phi,26 double psi);27 28 1 // NOTE that "length" here is the full height of the core! 29 double form_volume(double radius, double x_core, double thick_rim, double thick_face, double length) 2 static double 3 form_volume(double r_minor, 4 double x_core, 5 double thick_rim, 6 double thick_face, 7 double length) 30 8 { 31 return M_PI*(r adius+thick_rim)*(radius*x_core+thick_rim)*(length+2.0*thick_face);9 return M_PI*(r_minor+thick_rim)*(r_minor*x_core+thick_rim)*(length+2.0*thick_face); 32 10 } 33 11 34 double 35 Iq(double qq,36 double rad,37 38 double radthick,39 double facthick,40 41 42 43 44 12 static double 13 Iq(double q, 14 double r_minor, 15 double x_core, 16 double thick_rim, 17 double thick_face, 18 double length, 19 double rhoc, 20 double rhoh, 21 double rhor, 22 double rhosolv) 45 23 { 46 24 double si1,si2,be1,be2; 47 25 // core_shell_bicelle_elliptical, RKH Dec 2016, based on elliptical_cylinder and core_shell_bicelle 48 // tested against limiting cases of cylinder, elliptical_cylinder and core_shell_bicelle26 // tested against limiting cases of cylinder, elliptical_cylinder, stacked_discs, and core_shell_bicelle 49 27 // const double uplim = M_PI_4; 50 28 const double halfheight = 0.5*length; … … 55 33 //const double vbj=M_PI; 56 34 57 const double r adius_major = rad* x_core;58 const double r A = 0.5*(square(radius_major) + square(rad));59 const double r B = 0.5*(square(radius_major) - square(rad));60 const double dr1 = (rhoc-rhoh) *M_PI*r ad*radius_major*(2.0*halfheight);;61 const double dr2 = (rhor-rhosolv)*M_PI*(r ad+radthick)*(radius_major+radthick)*2.0*(halfheight+facthick);62 const double dr3 = (rhoh-rhor) *M_PI*r ad*radius_major*2.0*(halfheight+facthick);63 //const double vol1 = M_PI*r ad*radius_major*(2.0*halfheight);64 //const double vol2 = M_PI*(r ad+radthick)*(radius_major+radthick)*2.0*(halfheight+facthick);65 //const double vol3 = M_PI*r ad*radius_major*2.0*(halfheight+facthick);35 const double r_major = r_minor * x_core; 36 const double r2A = 0.5*(square(r_major) + square(r_minor)); 37 const double r2B = 0.5*(square(r_major) - square(r_minor)); 38 const double dr1 = (rhoc-rhoh) *M_PI*r_minor*r_major*(2.0*halfheight);; 39 const double dr2 = (rhor-rhosolv)*M_PI*(r_minor+thick_rim)*(r_major+thick_rim)*2.0*(halfheight+thick_face); 40 const double dr3 = (rhoh-rhor) *M_PI*r_minor*r_major*2.0*(halfheight+thick_face); 41 //const double vol1 = M_PI*r_minor*r_major*(2.0*halfheight); 42 //const double vol2 = M_PI*(r_minor+thick_rim)*(r_major+thick_rim)*2.0*(halfheight+thick_face); 43 //const double vol3 = M_PI*r_minor*r_major*2.0*(halfheight+thick_face); 66 44 67 45 //initialize integral … … 74 52 const double sin_alpha = sqrt(1.0 - cos_alpha*cos_alpha); 75 53 double inner_sum=0; 76 double sinarg1 = q q*halfheight*cos_alpha;77 double sinarg2 = q q*(halfheight+facthick)*cos_alpha;54 double sinarg1 = q*halfheight*cos_alpha; 55 double sinarg2 = q*(halfheight+thick_face)*cos_alpha; 78 56 si1 = sas_sinx_x(sinarg1); 79 57 si2 = sas_sinx_x(sinarg2); … … 82 60 //const double beta = ( Gauss76Z[j]*(vbj-vaj) + vaj + vbj )/2.0; 83 61 const double beta = ( Gauss76Z[j] +1.0)*M_PI_2; 84 const double rr = sqrt(r A - rB*cos(beta));85 double besarg1 = q q*rr*sin_alpha;86 double besarg2 = q q*(rr+radthick)*sin_alpha;62 const double rr = sqrt(r2A - r2B*cos(beta)); 63 double besarg1 = q*rr*sin_alpha; 64 double besarg2 = q*(rr+thick_rim)*sin_alpha; 87 65 be1 = sas_2J1x_x(besarg1); 88 66 be2 = sas_2J1x_x(besarg2); … … 98 76 } 99 77 100 double 78 static double 101 79 Iqxy(double qx, double qy, 102 double r ad,80 double r_minor, 103 81 double x_core, 104 double radthick,105 double facthick,82 double thick_rim, 83 double thick_face, 106 84 double length, 107 85 double rhoc, … … 114 92 { 115 93 // THIS NEEDS TESTING 116 double q q, cos_val, cos_mu, cos_nu;117 ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q q, cos_val, cos_mu, cos_nu);94 double q, xhat, yhat, zhat; 95 ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, xhat, yhat, zhat); 118 96 const double dr1 = rhoc-rhoh; 119 97 const double dr2 = rhor-rhosolv; 120 98 const double dr3 = rhoh-rhor; 121 const double r adius_major = rad*x_core;99 const double r_major = r_minor*x_core; 122 100 const double halfheight = 0.5*length; 123 const double vol1 = M_PI*r ad*radius_major*length;124 const double vol2 = M_PI*(r ad+radthick)*(radius_major+radthick)*2.0*(halfheight+facthick);125 const double vol3 = M_PI*r ad*radius_major*2.0*(halfheight+facthick);101 const double vol1 = M_PI*r_minor*r_major*length; 102 const double vol2 = M_PI*(r_minor+thick_rim)*(r_major+thick_rim)*2.0*(halfheight+thick_face); 103 const double vol3 = M_PI*r_minor*r_major*2.0*(halfheight+thick_face); 126 104 127 // Compute : r = sqrt((radius_major*cos_nu)^2 + (radius_minor*cos_mu)^2)128 // Given: radius_major = r_ratio * radius_minor129 // ASSUME the sin_alpha is included in the separate integration over orientation of rod angle130 const double r = rad*sqrt(square(x_core*cos_nu) + cos_mu*cos_mu);131 const double be1 = sas_2J1x_x( q q*r);132 const double be2 = sas_2J1x_x( q q*(r + radthick ));133 const double si1 = sas_sinx_x( q q*halfheight*cos_val);134 const double si2 = sas_sinx_x( q q*(halfheight + facthick)*cos_val);105 // Compute effective radius in rotated coordinates 106 const double r_hat = sqrt(square(r_major*xhat) + square(r_minor*yhat)); 107 const double rshell_hat = sqrt(square((r_major+thick_rim)*xhat) 108 + square((r_minor+thick_rim)*yhat)); 109 const double be1 = sas_2J1x_x( q*r_hat ); 110 const double be2 = sas_2J1x_x( q*rshell_hat ); 111 const double si1 = sas_sinx_x( q*halfheight*zhat ); 112 const double si2 = sas_sinx_x( q*(halfheight + thick_face)*zhat ); 135 113 const double Aq = square( vol1*dr1*si1*be1 + vol2*dr2*si2*be2 + vol3*dr3*si2*be1); 136 //const double vol = form_volume(radius_minor, r_ratio, length);137 114 return 1.0e-4 * Aq; 138 115 } -
sasmodels/models/core_shell_bicelle_elliptical.py
r3b9a526 r9802ab3 76 76 bicelles is then given by integrating over all possible $\alpha$ and $\psi$. 77 77 78 For oriented bicell les the *theta*, *phi* and *psi* orientation parameters onlyappear when fitting 2D data,78 For oriented bicelles the *theta*, *phi* and *psi* orientation parameters will appear when fitting 2D data, 79 79 see the :ref:`elliptical-cylinder` model for further information. 80 80 81 81 82 .. figure:: img/elliptical_cylinder_angle_definition. jpg82 .. figure:: img/elliptical_cylinder_angle_definition.png 83 83 84 Definition of the angles for the oriented core_shell_bicelle_elliptical model.85 Note that *theta* and *phi* are currently defined differently to those for the core_shell_bicelle model. 84 Definition of the angles for the oriented core_shell_bicelle_elliptical particles. 85 86 86 87 87 … … 99 99 """ 100 100 101 from numpy import inf, sin, cos 101 from numpy import inf, sin, cos, pi 102 102 103 103 name = "core_shell_bicelle_elliptical" … … 119 119 ["radius", "Ang", 30, [0, inf], "volume", "Cylinder core radius"], 120 120 ["x_core", "None", 3, [0, inf], "volume", "axial ratio of core, X = r_polar/r_equatorial"], 121 ["thick_rim", "Ang", 8, [0, inf], "volume", "Rim shell thickness"],122 ["thick_face", "Ang", 14, [0, inf], "volume", "Cylinder face thickness"],123 ["length", "Ang", 50, [0, inf], "volume", "Cylinder length"],121 ["thick_rim", "Ang", 8, [0, inf], "volume", "Rim shell thickness"], 122 ["thick_face", "Ang", 14, [0, inf], "volume", "Cylinder face thickness"], 123 ["length", "Ang", 50, [0, inf], "volume", "Cylinder length"], 124 124 ["sld_core", "1e-6/Ang^2", 4, [-inf, inf], "sld", "Cylinder core scattering length density"], 125 125 ["sld_face", "1e-6/Ang^2", 7, [-inf, inf], "sld", "Cylinder face scattering length density"], 126 126 ["sld_rim", "1e-6/Ang^2", 1, [-inf, inf], "sld", "Cylinder rim scattering length density"], 127 127 ["sld_solvent", "1e-6/Ang^2", 6, [-inf, inf], "sld", "Solvent scattering length density"], 128 ["theta", "degrees", 90, [-360, 360], "orientation", "In planeangle"],129 ["phi", "degrees", 0, [-360, 360], "orientation", "Out of plane angle"],130 ["psi", "degrees", 0, [-360, 360], "orientation", "Major axis angle relative to Q"],128 ["theta", "degrees", 90.0, [-360, 360], "orientation", "cylinder axis to beam angle"], 129 ["phi", "degrees", 0, [-360, 360], "orientation", "rotation about beam"], 130 ["psi", "degrees", 0, [-360, 360], "orientation", "rotation about cylinder axis"] 131 131 ] 132 132 … … 150 150 psi=0) 151 151 152 #qx, qy = 0.4 * cos(pi/2.0), 0.5 * sin(0) 152 q = 0.1 153 # april 6 2017, rkh added a 2d unit test, NOT READY YET pull #890 branch assume correct! 154 qx = q*cos(pi/6.0) 155 qy = q*sin(pi/6.0) 153 156 154 157 tests = [ … … 159 162 'sld_core':4.0, 'sld_face':7.0, 'sld_rim':1.0, 'sld_solvent':6.0, 'background':0.0}, 160 163 0.015, 286.540286], 161 ] 164 # [{'theta':80., 'phi':10.}, (qx, qy), 7.88866563001 ], 165 ] 166 167 del qx, qy # not necessary to delete, but cleaner -
sasmodels/models/core_shell_cylinder.py
rfcb33e4 r9b79f29 73 73 """ 74 74 75 from numpy import pi, inf 75 from numpy import pi, inf, sin, cos 76 76 77 77 name = "core_shell_cylinder" … … 117 117 ["length", "Ang", 400, [0, inf], "volume", 118 118 "Cylinder length"], 119 ["theta", "degrees", 60, [- inf, inf], "orientation",120 " In planeangle"],121 ["phi", "degrees", 60, [-inf, inf], "orientation",122 " Out of plane angle"],119 ["theta", "degrees", 60, [-360, 360], "orientation", 120 "cylinder axis to beam angle"], 121 ["phi", "degrees", 60, [-360, 360], "orientation", 122 "rotation about beam"], 123 123 ] 124 124 … … 151 151 theta_pd=15, theta_pd_n=45, 152 152 phi_pd=15, phi_pd_n=1) 153 153 q = 0.1 154 # april 6 2017, rkh add unit tests, NOT compared with any other calc method, assume correct! 155 qx = q*cos(pi/6.0) 156 qy = q*sin(pi/6.0) 157 tests = [[{}, 0.075, 10.8552692237], 158 [{}, (qx, qy), 0.444618752741 ], 159 ] 160 del qx, qy # not necessary to delete, but cleaner -
sasmodels/models/core_shell_ellipsoid.py
rdaeef4c r9802ab3 77 77 F^2(q)=\int_{0}^{\pi/2}{F^2(q,\alpha)\sin(\alpha)d\alpha} 78 78 79 For oriented ellipsoids the *theta*, *phi* and *psi* orientation parameters will appear when fitting 2D data, 80 see the :ref:`elliptical-cylinder` model for further information. 79 81 80 82 References … … 132 134 ["sld_shell", "1e-6/Ang^2", 1, [-inf, inf], "sld", "Shell scattering length density"], 133 135 ["sld_solvent", "1e-6/Ang^2", 6.3, [-inf, inf], "sld", "Solvent scattering length density"], 134 ["theta", "degrees", 0, [- inf, inf], "orientation", "Oblate orientation wrt incoming beam"],135 ["phi", "degrees", 0, [- inf, inf], "orientation", "Oblate orientation in the plane of the detector"],136 ["theta", "degrees", 0, [-360, 360], "orientation", "elipsoid axis to beam angle"], 137 ["phi", "degrees", 0, [-360, 360], "orientation", "rotation about beam"], 136 138 ] 137 139 # pylint: enable=bad-whitespace, line-too-long -
sasmodels/models/core_shell_parallelepiped.c
r1e7b0db0 r92dfe0c 134 134 double psi) 135 135 { 136 double q, cos_val_a, cos_val_b, cos_val_c;137 ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, cos_val_c, cos_val_b, cos_val_a);136 double q, zhat, yhat, xhat; 137 ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, xhat, yhat, zhat); 138 138 139 139 // cspkernel in csparallelepiped recoded here … … 160 160 double tc = length_a + 2.0*thick_rim_c; 161 161 //handle arg=0 separately, as sin(t)/t -> 1 as t->0 162 double siA = sas_sinx_x(0.5*q*length_a* cos_val_a);163 double siB = sas_sinx_x(0.5*q*length_b* cos_val_b);164 double siC = sas_sinx_x(0.5*q*length_c* cos_val_c);165 double siAt = sas_sinx_x(0.5*q*ta* cos_val_a);166 double siBt = sas_sinx_x(0.5*q*tb* cos_val_b);167 double siCt = sas_sinx_x(0.5*q*tc* cos_val_c);162 double siA = sas_sinx_x(0.5*q*length_a*xhat); 163 double siB = sas_sinx_x(0.5*q*length_b*yhat); 164 double siC = sas_sinx_x(0.5*q*length_c*zhat); 165 double siAt = sas_sinx_x(0.5*q*ta*xhat); 166 double siBt = sas_sinx_x(0.5*q*tb*yhat); 167 double siCt = sas_sinx_x(0.5*q*tc*zhat); 168 168 169 169 -
sasmodels/models/core_shell_parallelepiped.py
rcb0dc22 r9b79f29 6 6 The thickness and the scattering length density of the shell or 7 7 "rim" can be different on each (pair) of faces. However at this time 8 the modeldoes **NOT** actually calculate a c face rim despite the presence of9 the parameter. 8 the 1D calculation does **NOT** actually calculate a c face rim despite the presence of 9 the parameter. Some other aspects of the 1D calculation may be wrong. 10 10 11 11 .. note:: 12 This model was originally ported from NIST IGOR macros. However, t is not13 yet fully understood by the SasView developers and is currently review.12 This model was originally ported from NIST IGOR macros. However, it is not 13 yet fully understood by the SasView developers and is currently under review. 14 14 15 15 The form factor is normalized by the particle volume $V$ such that … … 48 48 amplitudes of the core and shell, in the same manner as a core-shell model. 49 49 50 .. math:: 51 52 F_{a}(Q,\alpha,\beta)= 53 \left[\frac{\sin(\tfrac{1}{2}Q(L_A+2t_A)\sin\alpha \sin\beta)}{\tfrac{1}{2}Q(L_A+2t_A)\sin\alpha\sin\beta} 54 - \frac{\sin(\tfrac{1}{2}QL_A\sin\alpha \sin\beta)}{\tfrac{1}{2}QL_A\sin\alpha \sin\beta} \right] 55 \left[\frac{\sin(\tfrac{1}{2}QL_B\sin\alpha \sin\beta)}{\tfrac{1}{2}QL_B\sin\alpha \sin\beta} \right] 56 \left[\frac{\sin(\tfrac{1}{2}QL_C\sin\alpha \sin\beta)}{\tfrac{1}{2}QL_C\sin\alpha \sin\beta} \right] 50 57 51 58 .. note:: 52 59 60 Why does t_B not appear in the above equation? 53 61 For the calculation of the form factor to be valid, the sides of the solid 54 MUST be chosen such that** $A < B < C$.62 MUST (perhaps not any more?) be chosen such that** $A < B < C$. 55 63 If this inequality is not satisfied, the model will not report an error, 56 64 but the calculation will not be correct and thus the result wrong. 57 65 58 66 FITTING NOTES 59 If the scale is set equal to the particle volume fraction, |phi|, the returned67 If the scale is set equal to the particle volume fraction, $\phi$, the returned 60 68 value is the scattered intensity per unit volume, $I(q) = \phi P(q)$. 61 69 However, **no interparticle interference effects are included in this … … 73 81 NB: The 2nd virial coefficient of the core_shell_parallelepiped is calculated 74 82 based on the the averaged effective radius $(=\sqrt{(A+2t_A)(B+2t_B)/\pi})$ 75 and length $(C+2t_C)$ values, and used as the effective radius 76 for $S(Q)$ when $P(Q) * S(Q)$ is applied. 83 and length $(C+2t_C)$ values, after appropriately 84 sorting the three dimensions to give an oblate or prolate particle, to give an 85 effective radius, for $S(Q)$ when $P(Q) * S(Q)$ is applied. 77 86 78 87 To provide easy access to the orientation of the parallelepiped, we define the … … 83 92 *x*-axis of the detector. 84 93 85 .. figure:: img/parallelepiped_angle_definition. jpg94 .. figure:: img/parallelepiped_angle_definition.png 86 95 87 96 Definition of the angles for oriented core-shell parallelepipeds. 88 97 89 .. figure:: img/parallelepiped_angle_projection. jpg98 .. figure:: img/parallelepiped_angle_projection.png 90 99 91 100 Examples of the angles for oriented core-shell parallelepipeds against the … … 112 121 113 122 import numpy as np 114 from numpy import pi, inf, sqrt 123 from numpy import pi, inf, sqrt, cos, sin 115 124 116 125 name = "core_shell_parallelepiped" … … 144 153 ["thick_rim_c", "Ang", 10, [0, inf], "volume", 145 154 "Thickness of C rim"], 146 ["theta", "degrees", 0, [- inf, inf], "orientation",147 " In planeangle"],148 ["phi", "degrees", 0, [- inf, inf], "orientation",149 " Out of plane angle"],150 ["psi", "degrees", 0, [- inf, inf], "orientation",151 " Rotation angle around its own c axis against q plane"],155 ["theta", "degrees", 0, [-360, 360], "orientation", 156 "c axis to beam angle"], 157 ["phi", "degrees", 0, [-360, 360], "orientation", 158 "rotation about beam"], 159 ["psi", "degrees", 0, [-360, 360], "orientation", 160 "rotation about c axis"], 152 161 ] 153 162 … … 186 195 psi_pd=10, psi_pd_n=1) 187 196 188 qx, qy = 0.2 * np.cos(2.5), 0.2 * np.sin(2.5) 197 # rkh 7/4/17 add random unit test for 2d, note make all params different, 2d values not tested against other codes or models 198 qx, qy = 0.2 * cos(pi/6.), 0.2 * sin(pi/6.) 189 199 tests = [[{}, 0.2, 0.533149288477], 190 200 [{}, [0.2], [0.533149288477]], 191 [{'theta':10.0, 'phi': 10.0}, (qx, qy), 0.032102135569],192 [{'theta':10.0, 'phi': 10.0}, [(qx, qy)], [0.032102135569]],201 [{'theta':10.0, 'phi':20.0}, (qx, qy), 0.0853299803222], 202 [{'theta':10.0, 'phi':20.0}, [(qx, qy)], [0.0853299803222]], 193 203 ] 194 204 del qx, qy # not necessary to delete, but cleaner -
sasmodels/models/cylinder.py
r3330bb4 r9802ab3 38 38 39 39 40 Numerical integration is simplified by a change of variable to $u = cos(\alpha)$ with 41 $sin(\alpha)=\sqrt{1-u^2}$. 40 Numerical integration is simplified by a change of variable to $u = cos(\alpha)$ with 41 $sin(\alpha)=\sqrt{1-u^2}$. 42 42 43 43 The output of the 1D scattering intensity function for randomly oriented … … 61 61 .. _cylinder-angle-definition: 62 62 63 .. figure:: img/cylinder_angle_definition. jpg63 .. figure:: img/cylinder_angle_definition.png 64 64 65 Definition of the angles for oriented cylinders. 65 Definition of the $\theta$ and $\phi$ orientation angles for a cylinder relative 66 to the beam line coordinates, plus an indication of their orientation distributions 67 which are described as rotations about each of the perpendicular axes $\delta_1$ and $\delta_2$ 68 in the frame of the cylinder itself, which when $\theta = \phi = 0$ are parallel to the $Y$ and $X$ axes. 66 69 67 The $\theta$ and $\phi$ parameters only appear in the model when fitting 2d data. 70 .. figure:: img/cylinder_angle_projection.png 71 72 Examples for oriented cylinders. 73 74 The $\theta$ and $\phi$ parameters to orient the cylinder only appear in the model when fitting 2d data. 75 On introducing "Orientational Distribution" in the angles, "distribution of theta" and "distribution of phi" parameters will 76 appear. These are actually rotations about the axes $\delta_1$ and $\delta_2$ of the cylinder, which when $\theta = \phi = 0$ are parallel 77 to the $Y$ and $X$ axes of the instrument respectively. Some experimentation may be required to understand the 2d patterns fully. 78 (Earlier implementations had numerical integration issues in some circumstances when orientation distributions passed through 90 degrees, such 79 situations, with very broad distributions, should still be approached with care.) 68 80 69 81 Validation … … 123 135 ["length", "Ang", 400, [0, inf], "volume", 124 136 "Cylinder length"], 125 ["theta", "degrees", 60, [- inf, inf], "orientation",126 " latitude"],127 ["phi", "degrees", 60, [-inf, inf], "orientation",128 " longitude"],137 ["theta", "degrees", 60, [-360, 360], "orientation", 138 "cylinder axis to beam angle"], 139 ["phi", "degrees", 60, [-360, 360], "orientation", 140 "rotation about beam"], 129 141 ] 130 142 … … 152 164 tests = [[{}, 0.2, 0.042761386790780453], 153 165 [{}, [0.2], [0.042761386790780453]], 154 # new coords 166 # new coords 155 167 [{'theta':80.1534480601659, 'phi':10.1510817110481}, (qx, qy), 0.03514647218513852], 156 168 [{'theta':80.1534480601659, 'phi':10.1510817110481}, [(qx, qy)], [0.03514647218513852]], -
sasmodels/models/ellipsoid.c
r130d4c7 r3b571ae 3 3 double Iqxy(double qx, double qy, double sld, double sld_solvent, 4 4 double radius_polar, double radius_equatorial, double theta, double phi); 5 6 static double7 _ellipsoid_kernel(double q, double radius_polar, double radius_equatorial, double cos_alpha)8 {9 double ratio = radius_polar/radius_equatorial;10 // Using ratio v = Rp/Re, we can expand the following to match the11 // 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 //17 // Instead of using pythagoras we could pass in sin and cos; this may be18 // slightly better for 2D which has already computed it, but it introduces19 // an extra sqrt and square for 1-D not required by the current form, so20 // leave it as is.21 const double r = radius_equatorial22 * sqrt(1.0 + cos_alpha*cos_alpha*(ratio*ratio - 1.0));23 const double f = sas_3j1x_x(q*r);24 25 return f*f;26 }27 5 28 6 double form_volume(double radius_polar, double radius_equatorial) … … 37 15 double radius_equatorial) 38 16 { 17 // Using ratio v = Rp/Re, we can implement the form given in Guinier (1955) 18 // i(h) = int_0^pi/2 Phi^2(h a sqrt(cos^2 + v^2 sin^2) cos dT 19 // = int_0^pi/2 Phi^2(h a sqrt((1-sin^2) + v^2 sin^2) cos dT 20 // = int_0^pi/2 Phi^2(h a sqrt(1 + sin^2(v^2-1)) cos dT 21 // u-substitution of 22 // u = sin, du = cos dT 23 // i(h) = int_0^1 Phi^2(h a sqrt(1 + u^2(v^2-1)) du 24 const double v_square_minus_one = square(radius_polar/radius_equatorial) - 1.0; 25 39 26 // translate a point in [-1,1] to a point in [0, 1] 27 // const double u = Gauss76Z[i]*(upper-lower)/2 + (upper+lower)/2; 40 28 const double zm = 0.5; 41 29 const double zb = 0.5; 42 30 double total = 0.0; 43 31 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); 32 const double u = Gauss76Z[i]*zm + zb; 33 const double r = radius_equatorial*sqrt(1.0 + u*u*v_square_minus_one); 34 const double f = sas_3j1x_x(q*r); 35 total += Gauss76Wt[i] * f * f; 47 36 } 48 37 // translate dx in [-1,1] to dx in [lower,upper] … … 62 51 double q, sin_alpha, cos_alpha; 63 52 ORIENT_SYMMETRIC(qx, qy, theta, phi, q, sin_alpha, cos_alpha); 64 const double form = _ellipsoid_kernel(q, radius_polar, radius_equatorial, cos_alpha); 53 const double r = sqrt(square(radius_equatorial*sin_alpha) 54 + square(radius_polar*cos_alpha)); 55 const double f = sas_3j1x_x(q*r); 65 56 const double s = (sld - sld_solvent) * form_volume(radius_polar, radius_equatorial); 66 57 67 return 1.0e-4 * form * s * s;58 return 1.0e-4 * square(f * s); 68 59 } 69 60 -
sasmodels/models/ellipsoid.py
r925ad6e r9b79f29 18 18 .. math:: 19 19 20 F(q,\alpha) = \frac{3 \Delta \rho V (\sin[qr(R_p,R_e,\alpha)] 21 - \cos[qr(R_p,R_e,\alpha)])} 22 {[qr(R_p,R_e,\alpha)]^3} 20 F(q,\alpha) = \Delta \rho V \frac{3(\sin qr - qr \cos qr)}{(qr)^3} 23 21 24 and 22 for 25 23 26 24 .. math:: 27 25 28 r(R_p,R_e,\alpha) = \left[ R_e^2 \sin^2 \alpha 29 + R_p^2 \cos^2 \alpha \right]^{1/2} 26 r = \left[ R_e^2 \sin^2 \alpha + R_p^2 \cos^2 \alpha \right]^{1/2} 30 27 31 28 32 29 $\alpha$ is the angle between the axis of the ellipsoid and $\vec q$, 33 $V = (4/3)\pi R_pR_e^2$ is the volume of the ellipsoid , $R_p$ is the polar radius along the 34 rotational axis of the ellipsoid, $R_e$ is the equatorial radius perpendicular 35 to the rotational axis of the ellipsoid and $\Delta \rho$ (contrast) is the 36 scattering length density difference between the scatterer and the solvent. 30 $V = (4/3)\pi R_pR_e^2$ is the volume of the ellipsoid, $R_p$ is the polar 31 radius along the rotational axis of the ellipsoid, $R_e$ is the equatorial 32 radius perpendicular to the rotational axis of the ellipsoid and 33 $\Delta \rho$ (contrast) is the scattering length density difference between 34 the scatterer and the solvent. 37 35 38 For randomly oriented particles :36 For randomly oriented particles use the orientational average, 39 37 40 38 .. math:: 41 39 42 F^2(q)=\int_{0}^{\pi/2}{F^2(q,\alpha)\sin(\alpha)d\alpha}40 \langle F^2(q) \rangle = \int_{0}^{\pi/2}{F^2(q,\alpha)\sin(\alpha)\,d\alpha} 43 41 42 43 computed via substitution of $u=\sin(\alpha)$, $du=\cos(\alpha)\,d\alpha$ as 44 45 .. math:: 46 47 \langle F^2(q) \rangle = \int_0^1{F^2(q, u)\,du} 48 49 with 50 51 .. math:: 52 53 r = R_e \left[ 1 + u^2\left(R_p^2/R_e^2 - 1\right)\right]^{1/2} 44 54 45 55 To provide easy access to the orientation of the ellipsoid, we define … … 48 58 :ref:`cylinder orientation figure <cylinder-angle-definition>`. 49 59 For the ellipsoid, $\theta$ is the angle between the rotational axis 50 and the $z$ -axis. 60 and the $z$ -axis in the $xz$ plane followed by a rotation by $\phi$ 61 in the $xy$ plane. 51 62 52 63 NB: The 2nd virial coefficient of the solid ellipsoid is calculated based … … 90 101 than 500. 91 102 103 Model was also tested against the triaxial ellipsoid model with equal major 104 and minor equatorial radii. It is also consistent with the cyclinder model 105 with polar radius equal to length and equatorial radius equal to radius. 106 92 107 References 93 108 ---------- … … 96 111 *Structure Analysis by Small-Angle X-Ray and Neutron Scattering*, 97 112 Plenum Press, New York, 1987. 113 114 Authorship and Verification 115 ---------------------------- 116 117 * **Author:** NIST IGOR/DANSE **Date:** pre 2010 118 * **Converted to sasmodels by:** Helen Park **Date:** July 9, 2014 119 * **Last Modified by:** Paul Kienzle **Date:** March 22, 2017 98 120 """ 99 121 100 from numpy import inf 122 from numpy import inf, sin, cos, pi 101 123 102 124 name = "ellipsoid" … … 129 151 ["radius_equatorial", "Ang", 400, [0, inf], "volume", 130 152 "Equatorial radius"], 131 ["theta", "degrees", 60, [- inf, inf], "orientation",132 " In planeangle"],133 ["phi", "degrees", 60, [- inf, inf], "orientation",134 " Out of plane angle"],153 ["theta", "degrees", 60, [-360, 360], "orientation", 154 "ellipsoid axis to beam angle"], 155 ["phi", "degrees", 60, [-360, 360], "orientation", 156 "rotation about beam"], 135 157 ] 136 158 … … 139 161 def ER(radius_polar, radius_equatorial): 140 162 import numpy as np 141 163 # see equation (26) in A.Isihara, J.Chem.Phys. 18(1950)1446-1449 142 164 ee = np.empty_like(radius_polar) 143 165 idx = radius_polar > radius_equatorial … … 168 190 theta_pd=15, theta_pd_n=45, 169 191 phi_pd=15, phi_pd_n=1) 192 q = 0.1 193 # april 6 2017, rkh add unit tests, NOT compared with any other calc method, assume correct! 194 qx = q*cos(pi/6.0) 195 qy = q*sin(pi/6.0) 196 tests = [[{}, 0.05, 54.8525847025], 197 [{'theta':80., 'phi':10.}, (qx, qy), 1.74134670026 ], 198 ] 199 del qx, qy # not necessary to delete, but cleaner -
sasmodels/models/elliptical_cylinder.c
r592343f r61104c8 67 67 double theta, double phi, double psi) 68 68 { 69 double q, cos_val, cos_mu, cos_nu;70 ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, cos_val, cos_mu, cos_nu);69 double q, xhat, yhat, zhat; 70 ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, xhat, yhat, zhat); 71 71 72 72 // Compute: r = sqrt((radius_major*cos_nu)^2 + (radius_minor*cos_mu)^2) 73 73 // Given: radius_major = r_ratio * radius_minor 74 const double r = radius_minor*sqrt(square(r_ratio* cos_nu) + cos_mu*cos_mu);74 const double r = radius_minor*sqrt(square(r_ratio*xhat) + square(yhat)); 75 75 const double be = sas_2J1x_x(q*r); 76 const double si = sas_sinx_x(q* 0.5*length*cos_val);76 const double si = sas_sinx_x(q*zhat*0.5*length); 77 77 const double Aq = be * si; 78 78 const double delrho = sld - solvent_sld; -
sasmodels/models/elliptical_cylinder.py
rfcb33e4 r9802ab3 57 57 define the axis of the cylinder using two angles $\theta$, $\phi$ and $\Psi$ 58 58 (see :ref:`cylinder orientation <cylinder-angle-definition>`). The angle 59 $\Psi$ is the rotational angle around its own long_c axis against the $q$ plane. 60 For example, $\Psi = 0$ when the $r_\text{minor}$ axis is parallel to the 61 $x$ axis of the detector. 59 $\Psi$ is the rotational angle around its own long_c axis. 62 60 63 61 All angle parameters are valid and given only for 2D calculation; ie, an 64 62 oriented system. 65 63 66 .. figure:: img/elliptical_cylinder_angle_definition. jpg64 .. figure:: img/elliptical_cylinder_angle_definition.png 67 65 68 Definition of angles for 2D 66 Definition of angles for oriented elliptical cylinder, where axis_ratio is drawn >1, 67 and angle $\Psi$ is now a rotation around the axis of the cylinder. 69 68 70 .. figure:: img/ cylinder_angle_projection.jpg69 .. figure:: img/elliptical_cylinder_angle_projection.png 71 70 72 71 Examples of the angles for oriented elliptical cylinders against the 73 detector plane. 72 detector plane, with $\Psi$ = 0. 73 74 The $\theta$ and $\phi$ parameters to orient the cylinder only appear in the model when fitting 2d data. 75 On introducing "Orientational Distribution" in the angles, "distribution of theta" and "distribution of phi" parameters will 76 appear. These are actually rotations about the axes $\delta_1$ and $\delta_2$ of the cylinder, the $b$ and $a$ axes of the 77 cylinder cross section. (When $\theta = \phi = 0$ these are parallel to the $Y$ and $X$ axes of the instrument.) 78 The third orientation distribution, in $\psi$, is about the $c$ axis of the particle. Some experimentation may be required to 79 understand the 2d patterns fully. (Earlier implementations had numerical integration issues in some circumstances when orientation 80 distributions passed through 90 degrees, such situations, with very broad distributions, should still be approached with care.) 74 81 75 82 NB: The 2nd virial coefficient of the cylinder is calculated based on the … … 108 115 """ 109 116 110 from numpy import pi, inf, sqrt 117 from numpy import pi, inf, sqrt, sin, cos 111 118 112 119 name = "elliptical_cylinder" … … 125 132 ["sld", "1e-6/Ang^2", 4.0, [-inf, inf], "sld", "Cylinder scattering length density"], 126 133 ["sld_solvent", "1e-6/Ang^2", 1.0, [-inf, inf], "sld", "Solvent scattering length density"], 127 ["theta", "degrees", 90.0, [-360, 360], "orientation", " In planeangle"],128 ["phi", "degrees", 0, [-360, 360], "orientation", " Out of plane angle"],129 ["psi", "degrees", 0, [-360, 360], "orientation", " Major axis angle relative to Q"]]134 ["theta", "degrees", 90.0, [-360, 360], "orientation", "cylinder axis to beam angle"], 135 ["phi", "degrees", 0, [-360, 360], "orientation", "rotation about beam"], 136 ["psi", "degrees", 0, [-360, 360], "orientation", "rotation about cylinder axis"]] 130 137 131 138 # pylint: enable=bad-whitespace, line-too-long … … 149 156 + (length + radius) * (length + pi * radius)) 150 157 return 0.5 * (ddd) ** (1. / 3.) 158 q = 0.1 159 # april 6 2017, rkh added a 2d unit test, NOT READY YET pull #890 branch assume correct! 160 qx = q*cos(pi/6.0) 161 qy = q*sin(pi/6.0) 151 162 152 163 tests = [ … … 158 169 'sld_solvent':1.0, 'background':0.0}, 159 170 0.001, 675.504402], 171 # [{'theta':80., 'phi':10.}, (qx, qy), 7.88866563001 ], 160 172 ] -
sasmodels/models/fcc_paracrystal.c
r4962519 r50beefe 90 90 double theta, double phi, double psi) 91 91 { 92 double q, cos_a1, cos_a2, cos_a3;93 ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, cos_a3, cos_a2, cos_a1);92 double q, zhat, yhat, xhat; 93 ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, xhat, yhat, zhat); 94 94 95 const double a1 = cos_a2 + cos_a3;96 const double a2 = cos_a3 + cos_a1;97 const double a3 = cos_a2 + cos_a1;95 const double a1 = yhat + xhat; 96 const double a2 = xhat + zhat; 97 const double a3 = yhat + zhat; 98 98 const double qd = 0.5*q*dnn; 99 99 const double arg = 0.5*square(qd*d_factor)*(a1*a1 + a2*a2 + a3*a3); -
sasmodels/models/fcc_paracrystal.py
r925ad6e r69e1afc 76 76 2D model computation. 77 77 78 .. figure:: img/ bcc_angle_definition.png78 .. figure:: img/parallelepiped_angle_definition.png 79 79 80 Orientation of the crystal with respect to the scattering plane. 80 Orientation of the crystal with respect to the scattering plane, when 81 $\theta = \phi = 0$ the $c$ axis is along the beam direction (the $z$ axis). 81 82 82 83 References … … 90 91 """ 91 92 92 from numpy import inf 93 from numpy import inf, pi 93 94 94 95 name = "fcc_paracrystal" … … 110 111 ["sld", "1e-6/Ang^2", 4, [-inf, inf], "sld", "Particle scattering length density"], 111 112 ["sld_solvent", "1e-6/Ang^2", 1, [-inf, inf], "sld", "Solvent scattering length density"], 112 ["theta", "degrees", 60, [-inf, inf], "orientation", "In planeangle"],113 ["phi", "degrees", 60, [-inf, inf], "orientation", "Out of plane angle"],114 ["psi", "degrees", 60, [-inf, inf], "orientation", "Out of plane angle"]113 ["theta", "degrees", 60, [-360, 360], "orientation", "c axis to beam angle"], 114 ["phi", "degrees", 60, [-360, 360], "orientation", "rotation about beam"], 115 ["psi", "degrees", 60, [-360, 360], "orientation", "rotation about c axis"] 115 116 ] 116 117 # pylint: enable=bad-whitespace, line-too-long … … 128 129 psi_pd=15, psi_pd_n=0, 129 130 ) 131 # april 10 2017, rkh add unit tests, NOT compared with any other calc method, assume correct! 132 q =4.*pi/220. 133 tests = [ 134 [{ }, 135 [0.001, q, 0.215268], [0.275164706668, 5.7776842567, 0.00958167119232]], 136 [{}, (-0.047,-0.007), 238.103096286], 137 [{}, (0.053,0.063), 0.863609587796 ], 138 ] -
sasmodels/models/hollow_cylinder.py
raea2e2a r9b79f29 60 60 """ 61 61 62 from numpy import pi, inf 62 from numpy import pi, inf, sin, cos 63 63 64 64 name = "hollow_cylinder" … … 82 82 ["sld", "1/Ang^2", 6.3, [-inf, inf], "sld", "Cylinder sld"], 83 83 ["sld_solvent", "1/Ang^2", 1, [-inf, inf], "sld", "Solvent sld"], 84 ["theta", "degrees", 90, [-360, 360], "orientation", " Thetaangle"],85 ["phi", "degrees", 0, [-360, 360], "orientation", " Phi angle"],84 ["theta", "degrees", 90, [-360, 360], "orientation", "Cylinder axis to beam angle"], 85 ["phi", "degrees", 0, [-360, 360], "orientation", "Rotation about beam"], 86 86 ] 87 87 # pylint: enable=bad-whitespace, line-too-long … … 129 129 theta_pd=10, theta_pd_n=5, 130 130 ) 131 131 q = 0.1 132 # april 6 2017, rkh added a 2d unit test, assume correct! 133 qx = q*cos(pi/6.0) 134 qy = q*sin(pi/6.0) 132 135 # Parameters for unit tests 133 136 tests = [ 134 137 [{}, 0.00005, 1764.926], 135 138 [{}, 'VR', 1.8], 136 [{}, 0.001, 1756.76] 137 ] 139 [{}, 0.001, 1756.76], 140 [{}, (qx, qy), 2.36885476192 ], 141 ] 142 del qx, qy # not necessary to delete, but cleaner -
sasmodels/models/parallelepiped.c
r1e7b0db0 rd605080 67 67 double psi) 68 68 { 69 double q, cos_val_a, cos_val_b, cos_val_c;70 ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, cos_val_c, cos_val_b, cos_val_a);69 double q, xhat, yhat, zhat; 70 ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, xhat, yhat, zhat); 71 71 72 const double siA = sas_sinx_x(0.5* q*length_a*cos_val_a);73 const double siB = sas_sinx_x(0.5* q*length_b*cos_val_b);74 const double siC = sas_sinx_x(0.5* q*length_c*cos_val_c);72 const double siA = sas_sinx_x(0.5*length_a*q*xhat); 73 const double siB = sas_sinx_x(0.5*length_b*q*yhat); 74 const double siC = sas_sinx_x(0.5*length_c*q*zhat); 75 75 const double V = form_volume(length_a, length_b, length_c); 76 76 const double drho = (sld - solvent_sld); -
sasmodels/models/parallelepiped.py
r3330bb4 r9802ab3 9 9 ---------- 10 10 11 |This model calculates the scattering from a rectangular parallelepiped12 |(\:numref:`parallelepiped-image`\).13 |If you need to apply polydispersity, see also :ref:`rectangular-prism`.11 This model calculates the scattering from a rectangular parallelepiped 12 (\:numref:`parallelepiped-image`\). 13 If you need to apply polydispersity, see also :ref:`rectangular-prism`. 14 14 15 15 .. _parallelepiped-image: 16 16 17 17 18 .. figure:: img/parallelepiped_geometry.jpg 18 19 … … 21 22 .. note:: 22 23 23 The edge of the solid mustsatisfy the condition that $A < B < C$.24 This requirement is not enforced in the model, so it is up to the25 user to check this during the analysis.24 The edge of the solid used to have to satisfy the condition that $A < B < C$. 25 After some improvements to the effective radius calculation, used with 26 an S(Q), it is beleived that this is no longer the case. 26 27 27 28 The 1D scattering intensity $I(q)$ is calculated as: … … 67 68 \mu &= qB 68 69 69 70 70 The scattering intensity per unit volume is returned in units of |cm^-1|. 71 71 72 72 NB: The 2nd virial coefficient of the parallelepiped is calculated based on 73 the averaged effective radius $(=\sqrt{A B / \pi})$ and 73 the averaged effective radius, after appropriately sorting the three 74 dimensions, to give an oblate or prolate particle, $(=\sqrt{AB/\pi})$ and 74 75 length $(= C)$ values, and used as the effective radius for 75 76 $S(q)$ when $P(q) \cdot S(q)$ is applied. … … 102 103 .. _parallelepiped-orientation: 103 104 104 .. figure:: img/parallelepiped_angle_definition. jpg105 106 Definition of the angles for oriented parallelepiped s.107 108 .. figure:: img/parallelepiped_angle_projection. jpg109 110 Examples of the angles for oriented parallelepipedsagainst the105 .. figure:: img/parallelepiped_angle_definition.png 106 107 Definition of the angles for oriented parallelepiped, shown with $A<B<C$. 108 109 .. figure:: img/parallelepiped_angle_projection.png 110 111 Examples of the angles for an oriented parallelepiped against the 111 112 detector plane. 112 113 114 On introducing "Orientational Distribution" in the angles, "distribution of theta" and "distribution of phi" parameters will 115 appear. These are actually rotations about axes $\delta_1$ and $\delta_2$ of the parallelepiped, perpendicular to the $a$ x $c$ and $b$ x $c$ faces. 116 (When $\theta = \phi = 0$ these are parallel to the $Y$ and $X$ axes of the instrument.) The third orientation distribution, in $\psi$, is 117 about the $c$ axis of the particle, perpendicular to the $a$ x $b$ face. Some experimentation may be required to 118 understand the 2d patterns fully. (Earlier implementations had numerical integration issues in some circumstances when orientation 119 distributions passed through 90 degrees, such situations, with very broad distributions, should still be approached with care.) 120 121 113 122 For a given orientation of the parallelepiped, the 2D form factor is 114 123 calculated as … … 116 125 .. math:: 117 126 118 P(q_x, q_y) = \left[\frac{\sin( qA\cos\alpha/2)}{(qA\cos\alpha/2)}\right]^2119 \left[\frac{\sin( qB\cos\beta/2)}{(qB\cos\beta/2)}\right]^2120 \left[\frac{\sin( qC\cos\gamma/2)}{(qC\cos\gamma/2)}\right]^2127 P(q_x, q_y) = \left[\frac{\sin(\tfrac{1}{2}qA\cos\alpha)}{(\tfrac{1}{2}qA\cos\alpha)}\right]^2 128 \left[\frac{\sin(\tfrac{1}{2}qB\cos\beta)}{(\tfrac{1}{2}qB\cos\beta)}\right]^2 129 \left[\frac{\sin(\tfrac{1}{2}qC\cos\gamma)}{(\tfrac{1}{2}qC\cos\gamma)}\right]^2 121 130 122 131 with … … 154 163 angles. 155 164 156 This model is based on form factor calculations implemented in a c-library157 provided by the NIST Center for Neutron Research (Kline, 2006).158 165 159 166 References … … 163 170 164 171 R Nayuk and K Huber, *Z. Phys. Chem.*, 226 (2012) 837-854 172 173 Authorship and Verification 174 ---------------------------- 175 176 * **Author:** This model is based on form factor calculations implemented 177 in a c-library provided by the NIST Center for Neutron Research (Kline, 2006). 178 * **Last Modified by:** Paul Kienzle **Date:** April 05, 2017 179 * **Last Reviewed by:** Richard Heenan **Date:** April 06, 2017 180 165 181 """ 166 182 167 183 import numpy as np 168 from numpy import pi, inf, sqrt 184 from numpy import pi, inf, sqrt, sin, cos 169 185 170 186 name = "parallelepiped" … … 180 196 mu = q*B 181 197 V: Volume of the rectangular parallelepiped 182 alpha: angle between the long axis of the 198 alpha: angle between the long axis of the 183 199 parallelepiped and the q-vector for 1D 184 200 """ … … 196 212 ["length_c", "Ang", 400, [0, inf], "volume", 197 213 "Larger side of the parallelepiped"], 198 ["theta", "degrees", 60, [- inf, inf], "orientation",199 " In planeangle"],200 ["phi", "degrees", 60, [- inf, inf], "orientation",201 " Out of plane angle"],202 ["psi", "degrees", 60, [- inf, inf], "orientation",203 " Rotation angle around its own c axis against q plane"],214 ["theta", "degrees", 60, [-360, 360], "orientation", 215 "c axis to beam angle"], 216 ["phi", "degrees", 60, [-360, 360], "orientation", 217 "rotation about beam"], 218 ["psi", "degrees", 60, [-360, 360], "orientation", 219 "rotation about c axis"], 204 220 ] 205 221 … … 208 224 def ER(length_a, length_b, length_c): 209 225 """ 210 226 Return effective radius (ER) for P(q)*S(q) 211 227 """ 212 228 # now that axes can be in any size order, need to sort a,b,c where a~b and c is either much smaller 229 # or much larger 230 abc = np.vstack((length_a, length_b, length_c)) 231 abc = np.sort(abc, axis=0) 232 selector = (abc[1] - abc[0]) > (abc[2] - abc[1]) 233 length = np.where(selector, abc[0], abc[2]) 213 234 # surface average radius (rough approximation) 214 surf_rad = sqrt(length_a * length_b/ pi)215 216 ddd = 0.75 * surf_rad * (2 * surf_rad * length_c + (length_c + surf_rad) * (length_c + pi * surf_rad))235 radius = np.sqrt(np.where(~selector, abc[0]*abc[1], abc[1]*abc[2]) / pi) 236 237 ddd = 0.75 * radius * (2*radius*length + (length + radius)*(length + pi*radius)) 217 238 return 0.5 * (ddd) ** (1. / 3.) 218 239 … … 230 251 phi_pd=10, phi_pd_n=1, 231 252 psi_pd=10, psi_pd_n=10) 232 233 qx, qy = 0.2 * np.cos(2.5), 0.2 * np.sin(2.5)253 # rkh 7/4/17 add random unit test for 2d, note make all params different, 2d values not tested against other codes or models 254 qx, qy = 0.2 * cos(pi/6.), 0.2 * sin(pi/6.) 234 255 tests = [[{}, 0.2, 0.17758004974], 235 256 [{}, [0.2], [0.17758004974]], 236 [{'theta':10.0, 'phi': 10.0}, (qx, qy), 0.00560296014],237 [{'theta':10.0, 'phi': 10.0}, [(qx, qy)], [0.00560296014]],257 [{'theta':10.0, 'phi':20.0}, (qx, qy), 0.0089517140475], 258 [{'theta':10.0, 'phi':20.0}, [(qx, qy)], [0.0089517140475]], 238 259 ] 239 260 del qx, qy # not necessary to delete, but cleaner -
sasmodels/models/sc_paracrystal.c
r4962519 r50beefe 111 111 double psi) 112 112 { 113 double q, cos_a1, cos_a2, cos_a3;114 ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, cos_a3, cos_a2, cos_a1);113 double q, zhat, yhat, xhat; 114 ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, xhat, yhat, zhat); 115 115 116 116 const double qd = q*dnn; … … 118 118 const double tanh_qd = tanh(arg); 119 119 const double cosh_qd = cosh(arg); 120 const double Zq = tanh_qd/(1. - cos(qd* cos_a1)/cosh_qd)121 * tanh_qd/(1. - cos(qd* cos_a2)/cosh_qd)122 * tanh_qd/(1. - cos(qd* cos_a3)/cosh_qd);120 const double Zq = tanh_qd/(1. - cos(qd*zhat)/cosh_qd) 121 * tanh_qd/(1. - cos(qd*yhat)/cosh_qd) 122 * tanh_qd/(1. - cos(qd*xhat)/cosh_qd); 123 123 124 124 const double Fq = sphere_form(q, radius, sphere_sld, solvent_sld)*Zq; -
sasmodels/models/sc_paracrystal.py
r3330bb4 r69e1afc 83 83 model computation. 84 84 85 .. figure:: img/sc_crystal_angle_definition.jpg 85 .. figure:: img/parallelepiped_angle_definition.png 86 87 Orientation of the crystal with respect to the scattering plane, when 88 $\theta = \phi = 0$ the $c$ axis is along the beam direction (the $z$ axis). 86 89 87 90 Reference … … 127 130 ["sld", "1e-6/Ang^2", 3.0, [0.0, inf], "sld", "Sphere scattering length density"], 128 131 ["sld_solvent", "1e-6/Ang^2", 6.3, [0.0, inf], "sld", "Solvent scattering length density"], 129 ["theta", "degrees", 0.0, [-inf, inf], "orientation", "Orientation of the a1 axis w/respect incoming beam"],130 ["phi", "degrees", 0.0, [-inf, inf], "orientation", "Orientation of the a2 in the plane of the detector"],131 ["psi", "degrees", 0.0, [-inf, inf], "orientation", "Orientation of the a3 in the plane of the detector"],132 ["theta", "degrees", 0, [-360, 360], "orientation", "c axis to beam angle"], 133 ["phi", "degrees", 0, [-360, 360], "orientation", "rotation about beam"], 134 ["psi", "degrees", 0, [-360, 360], "orientation", "rotation about c axis"] 132 135 ] 133 136 # pylint: enable=bad-whitespace, line-too-long … … 146 149 147 150 tests = [ 148 # Accuracy tests based on content in test/utest_extra_models.py 151 # Accuracy tests based on content in test/utest_extra_models.py, 2d tests added April 10, 2017 149 152 [{}, 0.001, 10.3048], 150 153 [{}, 0.215268, 0.00814889], 151 [{}, (0.414467), 0.001313289] 154 [{}, (0.414467), 0.001313289], 155 [{'theta':10.0,'phi':20,'psi':30.0},(0.045,-0.035),18.0397138402 ], 156 [{'theta':10.0,'phi':20,'psi':30.0},(0.023,0.045),0.0177333171285 ] 152 157 ] 153 158 -
sasmodels/models/stacked_disks.py
rc3ccaec r9802ab3 58 58 and $\sigma_d$ = the Gaussian standard deviation of the d-spacing (*sigma_d*). 59 59 Note that $D\cos(\alpha)$ is the component of $D$ parallel to $q$ and the last 60 term in the equation above is effectively a Debye-Waller factor term. 60 term in the equation above is effectively a Debye-Waller factor term. 61 61 62 62 .. note:: … … 77 77 the axis of the cylinder using two angles $\theta$ and $\varphi$. 78 78 79 .. figure:: img/cylinder_angle_definition. jpg79 .. figure:: img/cylinder_angle_definition.png 80 80 81 81 Examples of the angles against the detector plane. … … 103 103 """ 104 104 105 from numpy import inf 105 from numpy import inf, sin, cos, pi 106 106 107 107 name = "stacked_disks" … … 131 131 ["sld_layer", "1e-6/Ang^2", 0.0, [-inf, inf], "sld", "Layer scattering length density"], 132 132 ["sld_solvent", "1e-6/Ang^2", 5.0, [-inf, inf], "sld", "Solvent scattering length density"], 133 ["theta", "degrees", 0, [- inf, inf], "orientation", "Orientation of the stacked disk axis w/respect incoming beam"],134 ["phi", "degrees", 0, [- inf, inf], "orientation", "Orientation of the stacked disk in the plane of the detector"],133 ["theta", "degrees", 0, [-360, 360], "orientation", "Orientation of the stacked disk axis w/respect incoming beam"], 134 ["phi", "degrees", 0, [-360, 360], "orientation", "Rotation about beam"], 135 135 ] 136 136 # pylint: enable=bad-whitespace, line-too-long … … 152 152 # After redefinition of spherical coordinates - 153 153 # tests had in old coords theta=0, phi=0; new coords theta=90, phi=0 154 # but should not matter here as so far all the tests are 1D not 2D 154 q = 0.1 155 # april 6 2017, rkh added a 2d unit test, assume correct! 156 qx = q*cos(pi/6.0) 157 qy = q*sin(pi/6.0) 155 158 tests = [ 156 159 # Accuracy tests based on content in test/utest_extra_models.py. 157 # Added 2 tests with n_stacked = 5 using SasView 3.1.2 - PDB; for which alas q=0.001 values seem closer to n_stacked=1 not 5, changed assuming my 4.1 code OK, RKH 160 # Added 2 tests with n_stacked = 5 using SasView 3.1.2 - PDB; 161 # for which alas q=0.001 values seem closer to n_stacked=1 not 5, 162 # changed assuming my 4.1 code OK, RKH 158 163 [{'thick_core': 10.0, 159 164 'thick_layer': 15.0, … … 186 191 [{'thick_core': 10.0, 187 192 'thick_layer': 15.0, 193 'radius': 100.0, 194 'n_stacking': 5, 195 'sigma_d': 0.0, 196 'sld_core': 4.0, 197 'sld_layer': -0.4, 198 'solvent_sd': 5.0, 199 'theta': 90.0, 200 'phi': 20.0, 201 'scale': 0.01, 202 'background': 0.001}, 203 (qx, qy), 0.0491167089952 ], 204 [{'thick_core': 10.0, 205 'thick_layer': 15.0, 188 206 'radius': 3000.0, 189 207 'n_stacking': 5, … … 228 246 'background': 0.001, 229 247 }, ([0.4, 0.5]), [0.00105074, 0.00121761]], 248 [{'thick_core': 10.0, 249 'thick_layer': 15.0, 250 'radius': 3000.0, 251 'n_stacking': 1.0, 252 'sigma_d': 0.0, 253 'sld_core': 4.0, 254 'sld_layer': -0.4, 255 'solvent_sd': 5.0, 256 'theta': 90.0, 257 'phi': 20.0, 258 'scale': 0.01, 259 'background': 0.001, 260 }, (qx, qy), 0.0341738733124 ], 230 261 231 262 [{'thick_core': 10.0, -
sasmodels/models/triaxial_ellipsoid.c
r925ad6e r68dd6a9 20 20 double radius_polar) 21 21 { 22 double sn, cn; 23 // translate a point in [-1,1] to a point in [0, 1] 24 const double zm = 0.5; 25 const double zb = 0.5; 22 const double pa = square(radius_equat_minor/radius_equat_major) - 1.0; 23 const double pc = square(radius_polar/radius_equat_major) - 1.0; 24 // translate a point in [-1,1] to a point in [0, pi/2] 25 const double zm = M_PI_4; 26 const double zb = M_PI_4; 26 27 double outer = 0.0; 27 28 for (int i=0;i<76;i++) { 28 //const double cos_alpha = (Gauss76Z[i]*(upper-lower) + upper + lower)/2; 29 const double x = 0.5*(Gauss76Z[i] + 1.0); 30 SINCOS(M_PI_2*x, sn, cn); 31 const double acosx2 = radius_equat_minor*radius_equat_minor*cn*cn; 32 const double bsinx2 = radius_equat_major*radius_equat_major*sn*sn; 33 const double c2 = radius_polar*radius_polar; 29 //const double u = Gauss76Z[i]*(upper-lower)/2 + (upper + lower)/2; 30 const double phi = Gauss76Z[i]*zm + zb; 31 const double pa_sinsq_phi = pa*square(sin(phi)); 34 32 35 33 double inner = 0.0; 34 const double um = 0.5; 35 const double ub = 0.5; 36 36 for (int j=0;j<76;j++) { 37 const double ysq = square(Gauss76Z[j]*zm + zb); 38 const double t = q*sqrt(acosx2 + bsinx2*(1.0-ysq) + c2*ysq); 39 const double fq = sas_3j1x_x(t); 40 inner += Gauss76Wt[j] * fq * fq ; 37 // translate a point in [-1,1] to a point in [0, 1] 38 const double usq = square(Gauss76Z[j]*um + ub); 39 const double r = radius_equat_major*sqrt(pa_sinsq_phi*(1.0-usq) + 1.0 + pc*usq); 40 const double fq = sas_3j1x_x(q*r); 41 inner += Gauss76Wt[j] * fq * fq; 41 42 } 42 outer += Gauss76Wt[i] * 0.5 * inner;43 outer += Gauss76Wt[i] * inner; // correcting for dx later 43 44 } 44 // translate dx in [-1,1] to dx in [lower,upper]45 const double fqsq = outer *zm;45 // translate integration ranges from [-1,1] to [lower,upper] and normalize by 4 pi 46 const double fqsq = outer/4.0; // = outer*um*zm*8.0/(4.0*M_PI); 46 47 const double s = (sld - sld_solvent) * form_volume(radius_equat_minor, radius_equat_major, radius_polar); 47 48 return 1.0e-4 * s * s * fqsq; … … 58 59 double psi) 59 60 { 60 double q, calpha, cmu, cnu;61 ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, calpha, cmu, cnu);61 double q, xhat, yhat, zhat; 62 ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, xhat, yhat, zhat); 62 63 63 const double t = q*sqrt(radius_equat_minor*radius_equat_minor*cnu*cnu64 + radius_equat_major*radius_equat_major*cmu*cmu65 + radius_polar*radius_polar*calpha*calpha);66 const double fq = sas_3j1x_x( t);64 const double r = sqrt(square(radius_equat_minor*xhat) 65 + square(radius_equat_major*yhat) 66 + square(radius_polar*zhat)); 67 const double fq = sas_3j1x_x(q*r); 67 68 const double s = (sld - sld_solvent) * form_volume(radius_equat_minor, radius_equat_major, radius_polar); 68 69 -
sasmodels/models/triaxial_ellipsoid.py
r3330bb4 re645373 2 2 # Note: model title and parameter table are inserted automatically 3 3 r""" 4 All three axes are of different lengths with $R_a \leq R_b \leq R_c$ 5 **Users should maintain this inequality for all calculations**. 4 Definition 5 ---------- 6 7 .. figure:: img/triaxial_ellipsoid_geometry.jpg 8 9 Ellipsoid with $R_a$ as *radius_equat_minor*, $R_b$ as *radius_equat_major* 10 and $R_c$ as *radius_polar*. 11 12 Given an ellipsoid 6 13 7 14 .. math:: 8 15 9 P(q) = \text{scale} V \left< F^2(q) \right> + \text{background}16 \frac{X^2}{R_a^2} + \frac{Y^2}{R_b^2} + \frac{Z^2}{R_c^2} = 1 10 17 11 where the volume $V = 4/3 \pi R_a R_b R_c$, and the averaging 12 $\left<\ldots\right>$ is applied over all orientations for 1D. 13 14 .. figure:: img/triaxial_ellipsoid_geometry.jpg 15 16 Ellipsoid schematic. 17 18 Definition 19 ---------- 20 21 The form factor calculated is 18 the scattering for randomly oriented particles is defined by the average over 19 all orientations $\Omega$ of: 22 20 23 21 .. math:: 24 22 25 P(q) = \frac{\text{scale}}{V}\int_0^1\int_0^1 26 \Phi^2(qR_a^2\cos^2( \pi x/2) + qR_b^2\sin^2(\pi y/2)(1-y^2) + R_c^2y^2) 27 dx dy 23 P(q) = \text{scale}(\Delta\rho)^2\frac{V}{4 \pi}\int_\Omega\Phi^2(qr)\,d\Omega 24 + \text{background} 28 25 29 26 where … … 31 28 .. math:: 32 29 33 \Phi(u) = 3 u^{-3} (\sin u - u \cos u) 30 \Phi(qr) &= 3 j_1(qr)/qr = 3 (\sin qr - qr \cos qr)/(qr)^3 \\ 31 r^2 &= R_a^2e^2 + R_b^2f^2 + R_c^2g^2 \\ 32 V &= \tfrac{4}{3} \pi R_a R_b R_c 33 34 The $e$, $f$ and $g$ terms are the projections of the orientation vector on $X$, 35 $Y$ and $Z$ respectively. Keeping the orientation fixed at the canonical 36 axes, we can integrate over the incident direction using polar angle 37 $-\pi/2 \le \gamma \le \pi/2$ and equatorial angle $0 \le \phi \le 2\pi$ 38 (as defined in ref [1]), 39 40 .. math:: 41 42 \langle\Phi^2\rangle = \int_0^{2\pi} \int_{-\pi/2}^{\pi/2} \Phi^2(qr) 43 \cos \gamma\,d\gamma d\phi 44 45 with $e = \cos\gamma \sin\phi$, $f = \cos\gamma \cos\phi$ and $g = \sin\gamma$. 46 A little algebra yields 47 48 .. math:: 49 50 r^2 = b^2(p_a \sin^2 \phi \cos^2 \gamma + 1 + p_c \sin^2 \gamma) 51 52 for 53 54 .. math:: 55 56 p_a = \frac{a^2}{b^2} - 1 \text{ and } p_c = \frac{c^2}{b^2} - 1 57 58 Due to symmetry, the ranges can be restricted to a single quadrant 59 $0 \le \gamma \le \pi/2$ and $0 \le \phi \le \pi/2$, scaling the resulting 60 integral by 8. The computation is done using the substitution $u = \sin\gamma$, 61 $du = \cos\gamma\,d\gamma$, giving 62 63 .. math:: 64 65 \langle\Phi^2\rangle &= 8 \int_0^{\pi/2} \int_0^1 \Phi^2(qr) du d\phi \\ 66 r^2 &= b^2(p_a \sin^2(\phi)(1 - u^2) + 1 + p_c u^2) 34 67 35 68 To provide easy access to the orientation of the triaxial ellipsoid, 36 69 we define the axis of the cylinder using the angles $\theta$, $\phi$ 37 and $\psi$. These angles are defined on 38 :numref:`triaxial-ellipsoid-angles` . 39 The angle $\psi$ is the rotational angle around its own $c$ axis 40 against the $q$ plane. For example, $\psi = 0$ when the 41 $a$ axis is parallel to the $x$ axis of the detector. 70 and $\psi$. These angles are defined analogously to the elliptical_cylinder below 71 72 .. figure:: img/elliptical_cylinder_angle_definition.png 73 74 Definition of angles for oriented triaxial ellipsoid, where radii shown 75 here are $a < b << c$ and angle $\Psi$ is a rotation around the axis 76 of the particle. 77 78 For oriented ellipsoids the *theta*, *phi* and *psi* orientation parameters will appear when fitting 2D data, 79 see the :ref:`elliptical-cylinder` model for further information. 42 80 43 81 .. _triaxial-ellipsoid-angles: 44 82 45 .. figure:: img/triaxial_ellipsoid_angle_projection. jpg83 .. figure:: img/triaxial_ellipsoid_angle_projection.png 46 84 47 The angles for oriented ellipsoid.85 Some example angles for oriented ellipsoid. 48 86 49 87 The radius-of-gyration for this system is $R_g^2 = (R_a R_b R_c)^2/5$. 50 88 51 The contrast is defined as SLD(ellipsoid) - SLD(solvent). In the89 The contrast $\Delta\rho$ is defined as SLD(ellipsoid) - SLD(solvent). In the 52 90 parameters, $R_a$ is the minor equatorial radius, $R_b$ is the major 53 91 equatorial radius, and $R_c$ is the polar radius of the ellipsoid. … … 69 107 ---------- 70 108 71 L A Feigin and D I Svergun, *Structure Analysis by Small-Angle X-Ray 72 and Neutron Scattering*, Plenum, New York, 1987. 109 [1] Finnigan, J.A., Jacobs, D.J., 1971. 110 *Light scattering by ellipsoidal particles in solution*, 111 J. Phys. D: Appl. Phys. 4, 72-77. doi:10.1088/0022-3727/4/1/310 112 113 Authorship and Verification 114 ---------------------------- 115 116 * **Author:** NIST IGOR/DANSE **Date:** pre 2010 117 * **Last Modified by:** Paul Kienzle (improved calculation) **Date:** April 4, 2017 118 * **Last Reviewed by:** Paul Kienzle & Richard Heenan **Date:** April 4, 2017 73 119 """ 74 120 75 from numpy import inf 121 from numpy import inf, sin, cos, pi 76 122 77 123 name = "triaxial_ellipsoid" 78 124 title = "Ellipsoid of uniform scattering length density with three independent axes." 79 125 80 description = """\ 81 Note: During fitting ensure that the inequality ra<rb<rc is not 82 violated. Otherwise the calculation will 83 not be correct. 126 description = """ 127 Note - fitting ensure that the inequality ra<rb<rc is not 128 violated. Otherwise the calculation may not be correct. 84 129 """ 85 130 category = "shape:ellipsoid" … … 91 136 "Solvent scattering length density"], 92 137 ["radius_equat_minor", "Ang", 20, [0, inf], "volume", 93 "Minor equatorial radius "],138 "Minor equatorial radius, Ra"], 94 139 ["radius_equat_major", "Ang", 400, [0, inf], "volume", 95 "Major equatorial radius "],140 "Major equatorial radius, Rb"], 96 141 ["radius_polar", "Ang", 10, [0, inf], "volume", 97 "Polar radius "],98 ["theta", "degrees", 60, [- inf, inf], "orientation",99 " In planeangle"],100 ["phi", "degrees", 60, [- inf, inf], "orientation",101 " Out of plane angle"],102 ["psi", "degrees", 60, [- inf, inf], "orientation",103 " Out of plane angle"],142 "Polar radius, Rc"], 143 ["theta", "degrees", 60, [-360, 360], "orientation", 144 "polar axis to beam angle"], 145 ["phi", "degrees", 60, [-360, 360], "orientation", 146 "rotation about beam"], 147 ["psi", "degrees", 60, [-360, 360], "orientation", 148 "rotation about polar axis"], 104 149 ] 105 150 … … 108 153 def ER(radius_equat_minor, radius_equat_major, radius_polar): 109 154 """ 110 155 Returns the effective radius used in the S*P calculation 111 156 """ 112 157 import numpy as np 113 158 from .ellipsoid import ER as ellipsoid_ER 114 return ellipsoid_ER(radius_polar, np.sqrt(radius_equat_minor * radius_equat_major)) 159 160 # now that radii can be in any size order, radii need sorting a,b,c 161 # where a~b and c is either much smaller or much larger 162 radii = np.vstack((radius_equat_major, radius_equat_minor, radius_polar)) 163 radii = np.sort(radii, axis=0) 164 selector = (radii[1] - radii[0]) > (radii[2] - radii[1]) 165 polar = np.where(selector, radii[0], radii[2]) 166 equatorial = np.sqrt(np.where(~selector, radii[0]*radii[1], radii[1]*radii[2])) 167 return ellipsoid_ER(polar, equatorial) 115 168 116 169 demo = dict(scale=1, background=0, … … 124 177 phi_pd=15, phi_pd_n=1, 125 178 psi_pd=15, psi_pd_n=1) 179 180 q = 0.1 181 # april 6 2017, rkh add unit tests 182 # NOT compared with any other calc method, assume correct! 183 # check 2d test after pull #890 184 qx = q*cos(pi/6.0) 185 qy = q*sin(pi/6.0) 186 tests = [[{}, 0.05, 24.8839548033], 187 [{'theta':80., 'phi':10.}, (qx, qy), 166.712060266 ], 188 ] 189 del qx, qy # not necessary to delete, but cleaner
Note: See TracChangeset
for help on using the changeset viewer.