Changes in / [352494a:956960a] in sasmodels
- Files:
-
- 14 added
- 15 deleted
- 50 edited
Legend:
- Unmodified
- Added
- Removed
-
.travis.yml
rbec0e75 r24cd982 1 # Test Travis CL 1 language: python 2 2 3 language: python 4 python: 5 - "2.7" 3 sudo: false 4 5 matrix: 6 include: 7 - os: linux 8 env: 9 - PY=2.7 10 - NUMPYSPEC=numpy 11 - os: linux 12 env: 13 - PY=3 14 - NUMPYSPEC=numpy 15 - os: osx 16 language: generic 17 env: 18 - PY=2.7 19 - NUMPYSPEC=numpy 20 - os: osx 21 language: generic 22 env: 23 - PY=3 24 - NUMPYSPEC=numpy 25 6 26 # whitelist 7 27 branches: 8 28 only: 9 29 - master 10 # command to install dependencies 11 virtualenv: 12 system_site_packages: true 30 31 addons: 32 apt: 33 packages: 34 opencl-headers 35 13 36 before_install: 14 - sudo apt-get update; 15 - sudo apt-get install python-numpy python-scipy 16 # - sudo apt-get install opencl-headers 37 - echo $TRAVIS_OS_NAME 38 39 - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then 40 wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; 41 fi; 42 - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then 43 wget https://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh -O miniconda.sh; 44 fi; 45 46 - bash miniconda.sh -b -p $HOME/miniconda 47 - export PATH="$HOME/miniconda/bin:$PATH" 48 - hash -r 49 - conda update --yes conda 50 51 # Useful for debugging any issues with conda 52 - conda info -a 53 54 - conda install --yes python=$PY $NUMPYSPEC scipy cython mako cffi 55 56 - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then 57 pip install pyopencl; 58 fi; 17 59 18 60 install: 19 # - pip install pyopencl20 61 - pip install bumps 21 62 - pip install unittest-xml-reporting 63 22 64 script: 23 - export WORKSPACE=/home/travis/build/SasView/sasmodels/ 24 - python -m sasmodels.model_test dll all 65 - export WORKSPACE=/home/travis/build/SasView/sasmodels/ 66 - python -m sasmodels.model_test dll all 67 68 notifications: 69 slack: 70 secure: xNAUeSu1/it/x9Q2CSg79aw1LLc7d6mLpcqSCTeKROp71RhkFf8VjJnJm/lEbKHNC8yj5H9UHrz5DmzwJzI+6oMt4NdEeS6WvGhwGY/wCt2IcJKxw0vj1DAU04qFMS041Khwclo6jIqm76DloinXvmvsS+K/nSyQkF7q4egSlwA= -
LICENSE.txt
rc8de1bd rf68e2a5 1 This program is in the public domain. 1 Copyright (c) 2009-2017, SasView Developers 2 All rights reserved. 2 3 3 Individual files may be copyright different authors, with licences that 4 allow modification and redistribution in source or binary form with or 5 without modification, and a disclaimer of warranty. 4 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 6 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 8 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 10 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 12 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -
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) -
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
rf72d70a r630156b 30 30 31 31 import sys 32 import os 32 33 import math 33 34 import datetime … … 40 41 from . import kerneldll 41 42 from . import exception 42 from .data import plot_theory, empty_data1D, empty_data2D 43 from .data import plot_theory, empty_data1D, empty_data2D, load_data 43 44 from .direct_model import DirectModel 44 45 from .convert import revert_name, revert_pars, constrain_new_to_old … … 72 73 -1d*/-2d computes 1d or 2d data 73 74 -preset*/-random[=seed] preset or random parameters 74 -mono /-poly* force monodisperse/polydisperse75 -mono*/-poly force monodisperse or allow polydisperse demo parameters 75 76 -magnetic/-nonmagnetic* suppress magnetism 76 77 -cutoff=1e-5* cutoff value for including a point in polydispersity … … 83 84 -edit starts the parameter explorer 84 85 -default/-demo* use demo vs default parameters 85 -h tml shows the model docs instead of running the model86 -help/-html shows the model docs instead of running the model 86 87 -title="note" adds note to the plot title, after the model name 88 -data="path" uses q, dq from the data file 87 89 88 90 Any two calculation engines can be selected for comparison: … … 544 546 'f32': '32', 545 547 'f64': '64', 548 'float16': '16', 549 'float32': '32', 550 'float64': '64', 551 'float128': '128', 546 552 'longdouble': '128', 547 553 } … … 747 753 comp = opts['engines'][1] if have_comp else None 748 754 data = opts['data'] 755 use_data = (opts['datafile'] is not None) and (have_base ^ have_comp) 749 756 750 757 # Plot if requested 751 758 view = opts['view'] 752 759 import matplotlib.pyplot as plt 753 if limits is None :760 if limits is None and not use_data: 754 761 vmin, vmax = np.Inf, -np.Inf 755 762 if have_base: … … 763 770 if have_base: 764 771 if have_comp: plt.subplot(131) 765 plot_theory(data, base_value, view=view, use_data= False, limits=limits)772 plot_theory(data, base_value, view=view, use_data=use_data, limits=limits) 766 773 plt.title("%s t=%.2f ms"%(base.engine, base_time)) 767 774 #cbar_title = "log I" … … 769 776 if have_base: plt.subplot(132) 770 777 if not opts['is2d'] and have_base: 771 plot_theory(data, base_value, view=view, use_data= False, limits=limits)772 plot_theory(data, comp_value, view=view, use_data= False, limits=limits)778 plot_theory(data, base_value, view=view, use_data=use_data, limits=limits) 779 plot_theory(data, comp_value, view=view, use_data=use_data, limits=limits) 773 780 plt.title("%s t=%.2f ms"%(comp.engine, comp_time)) 774 781 #cbar_title = "log I" … … 784 791 err[err>cutoff] = cutoff 785 792 #err,errstr = base/comp,"ratio" 786 plot_theory(data, None, resid=err, view=errview, use_data= False)793 plot_theory(data, None, resid=err, view=errview, use_data=use_data) 787 794 if view == 'linear': 788 795 plt.xscale('linear') … … 829 836 'linear', 'log', 'q4', 830 837 'hist', 'nohist', 831 'edit', 'html', 838 'edit', 'html', 'help', 832 839 'demo', 'default', 833 840 ]) 834 841 VALUE_OPTIONS = [ 835 842 # Note: random is both a name option and a value option 836 'cutoff', 'random', 'nq', 'res', 'accuracy', 'title', 843 'cutoff', 'random', 'nq', 'res', 'accuracy', 'title', 'data', 837 844 ] 838 845 … … 940 947 'cutoff' : 0.0, 941 948 'seed' : -1, # default to preset 942 'mono' : False,949 'mono' : True, 943 950 # Default to magnetic a magnetic moment is set on the command line 944 951 'magnetic' : False, … … 951 958 'html' : False, 952 959 'title' : None, 960 'datafile' : None, 953 961 } 954 962 engines = [] … … 971 979 elif arg.startswith('-cutoff='): opts['cutoff'] = float(arg[8:]) 972 980 elif arg.startswith('-random='): opts['seed'] = int(arg[8:]) 973 elif arg.startswith('-title'): opts['title'] = arg[7:] 981 elif arg.startswith('-title='): opts['title'] = arg[7:] 982 elif arg.startswith('-data='): opts['datafile'] = arg[6:] 974 983 elif arg == '-random': opts['seed'] = np.random.randint(1000000) 975 984 elif arg == '-preset': opts['seed'] = -1 … … 996 1005 elif arg == '-default': opts['use_demo'] = False 997 1006 elif arg == '-html': opts['html'] = True 1007 elif arg == '-help': opts['html'] = True 998 1008 # pylint: enable=bad-whitespace 999 1009 … … 1112 1122 1113 1123 # Create the computational engines 1114 data, _ = make_data(opts) 1124 if opts['datafile'] is not None: 1125 data = load_data(os.path.expanduser(opts['datafile'])) 1126 else: 1127 data, _ = make_data(opts) 1115 1128 if n1: 1116 1129 base = make_engine(model_info, data, engines[0], opts['cutoff']) … … 1142 1155 show html docs for the model 1143 1156 """ 1144 import wx # type: ignore 1145 from .generate import view_html_from_info 1146 app = wx.App() if wx.GetApp() is None else None 1147 view_html_from_info(opts['def'][0]) 1148 if app: app.MainLoop() 1149 1157 import os 1158 from .generate import make_html 1159 from . import rst2html 1160 1161 info = opts['def'][0] 1162 html = make_html(info) 1163 path = os.path.dirname(info.filename) 1164 url = "file://"+path.replace("\\","/")[2:]+"/" 1165 rst2html.view_html_qtapp(html, url) 1150 1166 1151 1167 def explore(opts): -
sasmodels/core.py
r5124c969 r650c6d2 250 250 dtype = "longdouble" 251 251 elif dtype == "half": 252 dtype = "f 16"252 dtype = "float16" 253 253 254 254 # Convert dtype string to numpy dtype. -
sasmodels/data.py
r40a87fa r630156b 51 51 from sas.sascalc.dataloader.loader import Loader # type: ignore 52 52 loader = Loader() 53 data = loader.load(filename) 54 if data is None: 53 # Allow for one part in multipart file 54 if '[' in filename: 55 filename, indexstr = filename[:-1].split('[') 56 index = int(indexstr) 57 else: 58 index = None 59 datasets = loader.load(filename) 60 if datasets is None: 55 61 raise IOError("Data %r could not be loaded" % filename) 62 if not isinstance(datasets, list): 63 datasets = [datasets] 64 if index is None and len(datasets) > 1: 65 raise ValueError("Need to specify filename[index] for multipart data") 66 data = datasets[index if index is not None else 0] 67 if hasattr(data, 'x'): 68 data.qmin, data.qmax = data.x.min(), data.x.max() 69 data.mask = (np.isnan(data.y) if data.y is not None 70 else np.zeros_like(data.x, dtype='bool')) 71 elif hasattr(data, 'qx_data'): 72 data.mask = ~data.mask 56 73 return data 57 74 … … 348 365 # data, but they already handle the masking and graph markup already, so 349 366 # do not repeat. 350 if hasattr(data, ' lam'):367 if hasattr(data, 'isSesans') and data.isSesans: 351 368 _plot_result_sesans(data, None, None, use_data=True, limits=limits) 352 369 elif hasattr(data, 'qx_data'): … … 376 393 *Iq_calc* is the raw theory values without resolution smearing 377 394 """ 378 if hasattr(data, ' lam'):395 if hasattr(data, 'isSesans') and data.isSesans: 379 396 _plot_result_sesans(data, theory, resid, use_data=True, limits=limits) 380 397 elif hasattr(data, 'qx_data'): … … 446 463 if view is 'log': 447 464 mtheory[mtheory <= 0] = masked 448 plt.plot(data.x, scale*mtheory, '-' , hold=True)465 plt.plot(data.x, scale*mtheory, '-') 449 466 all_positive = all_positive and (mtheory > 0).all() 450 467 some_present = some_present or (mtheory.count() > 0) … … 453 470 plt.ylim(*limits) 454 471 455 plt.xscale('linear' if not some_present or non_positive_x else view) 472 plt.xscale('linear' if not some_present or non_positive_x 473 else view if view is not None 474 else 'log') 456 475 plt.yscale('linear' 457 476 if view == 'q4' or not some_present or not all_positive 458 else view) 477 else view if view is not None 478 else 'log') 459 479 plt.xlabel("$q$/A$^{-1}$") 460 480 plt.ylabel('$I(q)$') 481 title = ("data and model" if use_theory and use_data 482 else "data" if use_data 483 else "model") 484 plt.title(title) 461 485 462 486 if use_calc: … … 478 502 if num_plots > 1: 479 503 plt.subplot(1, num_plots, use_calc + 2) 480 plt.plot(data.x, mresid, ' -')504 plt.plot(data.x, mresid, '.') 481 505 plt.xlabel("$q$/A$^{-1}$") 482 506 plt.ylabel('residuals') 483 plt.xscale('linear' if not some_present or non_positive_x else view) 507 plt.xscale('linear') 508 plt.title('(model - Iq)/dIq') 484 509 485 510 … … 508 533 if theory is not None: 509 534 if is_tof: 510 plt.plot(data.x, np.log(theory)/(data.lam*data.lam), '-' , hold=True)535 plt.plot(data.x, np.log(theory)/(data.lam*data.lam), '-') 511 536 else: 512 plt.plot(data.x, theory, '-' , hold=True)537 plt.plot(data.x, theory, '-') 513 538 if limits is not None: 514 539 plt.ylim(*limits) -
sasmodels/direct_model.py
rb397165 ra769b54 192 192 193 193 # interpret data 194 if hasattr(data, ' lam'):194 if hasattr(data, 'isSesans') and data.isSesans: 195 195 self.data_type = 'sesans' 196 196 elif hasattr(data, 'qx_data'): -
sasmodels/generate.py
r1e7b0db0 rbb4b509 492 492 493 493 def test_tag_float(): 494 495 cases=""" 494 """check that floating point constants are properly identified and tagged with 'f'""" 495 496 cases = """ 496 497 ZP : 0. 497 498 ZPF : 0.0,0.01,0.1 … … 519 520 """ 520 521 521 output ="""522 output = """ 522 523 ZP : 0.f 523 524 ZPF : 0.0f,0.01f,0.1f … … 611 612 # type: (str, List[Parameter]) -> List[str] 612 613 """ 613 Return a list of *prefix.parameter* from parameter items. 614 Return a list of *prefix+parameter* from parameter items. 615 616 *prefix* should be "v." if v is a struct. 614 617 """ 615 618 return [p.as_call_reference(prefix) for p in pars] … … 733 736 call_iqxy = "#define CALL_IQ(_q,_i,_v) Iq(%s)" % (",".join(pars_sqrt)) 734 737 735 magpars = [k-2 for k, p in enumerate(partable.call_parameters)738 magpars = [k-2 for k, p in enumerate(partable.call_parameters) 736 739 if p.type == 'sld'] 737 740 … … 742 745 source.append("#define NUM_MAGNETIC %d" % partable.nmagnetic) 743 746 source.append("#define MAGNETIC_PARS %s"%",".join(str(k) for k in magpars)) 744 for k, v in enumerate(magpars[:3]):747 for k, v in enumerate(magpars[:3]): 745 748 source.append("#define MAGNETIC_PAR%d %d"%(k+1, v)) 746 749 … … 779 782 "#undef CALL_IQ", 780 783 "#undef KERNEL_NAME", 781 784 ] 782 785 783 786 imagnetic = [ … … 872 875 873 876 # TODO: need a single source for rst_prolog; it is also in doc/rst_prolog 874 RST_PROLOG = """\877 RST_PROLOG = r"""\ 875 878 .. |Ang| unicode:: U+212B 876 879 .. |Ang^-1| replace:: |Ang|\ :sup:`-1` … … 928 931 from . import rst2html 929 932 url = "file://"+dirname(info.filename)+"/" 930 rst2html. wxview(make_html(info), url=url)933 rst2html.view_html(make_html(info), url=url) 931 934 932 935 def demo_time(): -
sasmodels/kernel_header.c
r1e7b0db0 rbb4b509 14 14 # define SINCOS(angle,svar,cvar) do {const double _t_=angle; svar=sin(_t_);cvar=cos(_t_);} while (0) 15 15 # endif 16 // Intel CPU on Mac gives strange values for erf(); also on the tested16 // Intel CPU on Mac gives strange values for erf(); on the verified 17 17 // platforms (intel, nvidia, amd), the cephes erf() is significantly 18 18 // faster than that available in the native OpenCL. … … 57 57 typedef int int32_t; 58 58 #include <math.h> 59 // TODO: test isnan59 // TODO: check isnan is correct 60 60 inline double _isnan(double x) { return x != x; } // hope this doesn't optimize away! 61 61 #undef isnan … … 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/kerneldll.py
r886fa25 rb2f1d2f 97 97 98 98 if "SAS_COMPILER" in os.environ: 99 compiler= os.environ["SAS_COMPILER"]99 COMPILER = os.environ["SAS_COMPILER"] 100 100 elif os.name == 'nt': 101 # If vcvarsall.bat has been called, then VCINSTALLDIR is in the environment102 # and we can use the MSVC compiler. Otherwise, if tinycc is available103 # the use it. Otherwise, hope that mingw is available.104 if "VCINSTALLDIR" in os.environ:105 compiler = "msvc"106 elif tinycc:107 compiler = "tinycc"101 if tinycc is not None: 102 COMPILER = "tinycc" 103 elif "VCINSTALLDIR" in os.environ: 104 # If vcvarsall.bat has been called, then VCINSTALLDIR is in the environment 105 # and we can use the MSVC compiler. Otherwise, if tinycc is available 106 # the use it. Otherwise, hope that mingw is available. 107 COMPILER = "msvc" 108 108 else: 109 compiler= "mingw"109 COMPILER = "mingw" 110 110 else: 111 compiler= "unix"111 COMPILER = "unix" 112 112 113 113 ARCH = "" if ct.sizeof(ct.c_void_p) > 4 else "x86" # 4 byte pointers on x86 114 if compiler== "unix":114 if COMPILER == "unix": 115 115 # Generic unix compile 116 116 # On mac users will need the X code command line tools installed … … 123 123 """unix compiler command""" 124 124 return CC + [source, "-o", output, "-lm"] 125 elif compiler== "msvc":125 elif COMPILER == "msvc": 126 126 # Call vcvarsall.bat before compiling to set path, headers, libs, etc. 127 127 # MSVC compiler is available, so use it. OpenMP requires a copy of … … 139 139 """MSVC compiler command""" 140 140 return CC + ["/Tp%s"%source] + LN + ["/OUT:%s"%output] 141 elif compiler== "tinycc":141 elif COMPILER == "tinycc": 142 142 # TinyCC compiler. 143 143 CC = [tinycc.TCC] + "-shared -rdynamic -Wall".split() … … 145 145 """tinycc compiler command""" 146 146 return CC + [source, "-o", output] 147 elif compiler== "mingw":147 elif COMPILER == "mingw": 148 148 # MinGW compiler. 149 149 CC = "gcc -shared -std=c99 -O2 -Wall".split() -
sasmodels/kernelpy.py
rb397165 rdbfd471 235 235 # exclude all q for that NaN. Even better would be to have an 236 236 # INVALID expression like the C models, but that is too expensive. 237 Iq = form()237 Iq = np.asarray(form(), 'd') 238 238 if np.isnan(Iq).any(): continue 239 239 -
sasmodels/model_test.py
r598857b rbb4b509 85 85 skip = [] 86 86 for model_name in models: 87 if model_name in skip: continue 87 if model_name in skip: 88 continue 88 89 model_info = load_model_info(model_name) 89 90 … … 239 240 multiple = [test for test in self.info.tests 240 241 if isinstance(test[2], list) 241 242 and not all(result is None for result in test[2])] 242 243 tests_has_1D_multiple = any(isinstance(test[1][0], float) 243 244 for test in multiple) … … 262 263 user_pars, x, y = test 263 264 pars = expand_pars(self.info.parameters, user_pars) 265 invalid = invalid_pars(self.info.parameters, pars) 266 if invalid: 267 raise ValueError("Unknown parameters in test: " + ", ".join(invalid)) 264 268 265 269 if not isinstance(y, list): … … 305 309 306 310 return ModelTestCase 311 312 def invalid_pars(partable, pars): 313 # type: (ParameterTable, Dict[str, float]) 314 """ 315 Return a list of parameter names that are not part of the model. 316 """ 317 names = set(p.id for p in partable.call_parameters) 318 invalid = [] 319 for par in sorted(pars.keys()): 320 parts = par.split('_pd') 321 if len(parts) > 1 and parts[1] not in ("", "_n", "nsigma", "type"): 322 invalid.append(par) 323 continue 324 if parts[0] not in names: 325 invalid.append(par) 326 return invalid 327 307 328 308 329 def is_near(target, actual, digits=5): -
sasmodels/modelinfo.py
rf88e248 rbb4b509 101 101 limits = (float(low), float(high)) 102 102 except Exception: 103 raise ValueError("invalid limits for %s: %r"%(name, user_limits))103 raise ValueError("invalid limits for %s: %r"%(name, user_limits)) 104 104 if low >= high: 105 105 raise ValueError("require lower limit < upper limit") … … 342 342 def as_call_reference(self, prefix=""): 343 343 # type: (str) -> str 344 """ 345 Return *prefix* + parameter name. For struct references, use "v." 346 as the prefix. 347 """ 344 348 # Note: if the parameter is a struct type, then we will need to use 345 349 # &prefix+id. For scalars and vectors we can just use prefix+id. … … 420 424 self.npars = sum(p.length for p in self.kernel_parameters) 421 425 self.nmagnetic = sum(p.length for p in self.kernel_parameters 422 if p.type =='sld')426 if p.type == 'sld') 423 427 self.nvalues = 2 + self.npars 424 428 if self.nmagnetic: … … 457 461 self.has_2d = any(p.type in ('orientation', 'magnetic') 458 462 for p in self.kernel_parameters) 459 self.magnetism_index = [k for k, p in enumerate(self.call_parameters)463 self.magnetism_index = [k for k, p in enumerate(self.call_parameters) 460 464 if p.id.startswith('M0:')] 461 465 … … 544 548 'magnetic', 'magnetic amplitude for '+p.description), 545 549 Parameter('mtheta:'+p.id, 'degrees', 0., [-90., 90.], 546 550 'magnetic', 'magnetic latitude for '+p.description), 547 551 Parameter('mphi:'+p.id, 'degrees', 0., [-180., 180.], 548 552 'magnetic', 'magnetic longitude for '+p.description), 549 553 ]) 550 554 #print("call parameters", full_list) … … 683 687 684 688 if (model_info.Iq is None 685 and model_info.Iqxy is None686 and model_info.Imagnetic is None687 and model_info.form_volume is None):689 and model_info.Iqxy is None 690 and model_info.Imagnetic is None 691 and model_info.form_volume is None): 688 692 return 689 693 … … 843 847 #: it to False because they require double precision calculations. 844 848 single = None # type: bool 849 #: True if the model can be run as an opencl model. If for some reason 850 #: the model cannot be run in opencl (e.g., because the model passes 851 #: functions by reference), then set this to false. 852 opencl = None # type: bool 845 853 #: True if the model is a structure factor used to model the interaction 846 854 #: between form factor models. This will default to False if it is not -
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
r8afefae 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
r8afefae 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
r8e68ea0 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
r8e68ea0 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
rb7e8b94 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/hayter_msa.py
ra807206 r5702f52 74 74 ["radius_effective", "Ang", 20.75, [0, inf], "volume", "effective radius of charged sphere"], 75 75 ["volfraction", "None", 0.0192, [0, 0.74], "", "volume fraction of spheres"], 76 ["charge", "e", 19.0, [0, inf], "", "charge on sphere (in electrons)"],77 ["temperature", "K", 318.16, [0, inf], "", "temperature, in Kelvin, for Debye length calculation"],78 ["concentration_salt", "M", 0.0, [ -inf, inf], "", "conc of salt, moles/litre, 1:1 electolyte, for Debye length"],76 ["charge", "e", 19.0, [0, 200], "", "charge on sphere (in electrons)"], 77 ["temperature", "K", 318.16, [0, 450], "", "temperature, in Kelvin, for Debye length calculation"], 78 ["concentration_salt", "M", 0.0, [0, inf], "", "conc of salt, moles/litre, 1:1 electolyte, for Debye length"], 79 79 ["dielectconst", "None", 71.08, [-inf, inf], "", "dielectric constant (relative permittivity) of solvent, default water, for Debye length"] 80 80 ] -
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/lib/sas_3j1x_x.c
r473a9f1 reb2946f 46 46 double sas_3j1x_x(double q) 47 47 { 48 if (q < SPH_J1C_CUTOFF) { 48 // 2017-05-18 PAK - support negative q 49 if (fabs(q) < SPH_J1C_CUTOFF) { 49 50 const double q2 = q*q; 50 51 return (1.0 + q2*(-3./30. + q2*(3./840. + q2*(-3./45360.))));// + q2*(3./3991680.))))); -
sasmodels/models/lib/sas_J0.c
rc8902ac reb2946f 236 236 xx = x; 237 237 238 if( x <= 2.0 ) { 238 // 2017-05-18 PAK - support negative x 239 if( xx <= 2.0 ) { 239 240 z = xx * xx; 240 if( x < 1.0e-3 )241 if( xx < 1.0e-3 ) 241 242 return( 1.0 - 0.25*z ); 242 243 … … 245 246 } 246 247 247 q = 1.0/x ;248 q = 1.0/xx; 248 249 w = sqrt(q); 249 250 -
sasmodels/models/lib/sas_J1.c
r473a9f1 reb2946f 109 109 { 110 110 111 double w, z, p, q, xn ;111 double w, z, p, q, xn, abs_x, sign_x; 112 112 113 113 const double Z1 = 1.46819706421238932572E1; … … 116 116 const double SQ2OPI = 0.79788456080286535588; 117 117 118 w = x; 119 if( x < 0 ) 120 w = -x; 121 122 if( w <= 5.0 ) { 123 z = x * x; 118 // 2017-05-18 PAK - mathematica and mpmath use J1(-x) = -J1(x) 119 if (x < 0) { 120 abs_x = -x; 121 sign_x = -1.0; 122 } else { 123 abs_x = x; 124 sign_x = 1.0; 125 } 126 127 if( abs_x <= 5.0 ) { 128 z = abs_x * abs_x; 124 129 w = polevl( z, RPJ1, 3 ) / p1evl( z, RQJ1, 8 ); 125 w = w * x * (z - Z1) * (z - Z2);126 return( w );130 w = w * abs_x * (z - Z1) * (z - Z2); 131 return( sign_x * w ); 127 132 } 128 133 129 w = 5.0/ x;134 w = 5.0/abs_x; 130 135 z = w * w; 131 132 136 p = polevl( z, PPJ1, 6)/polevl( z, PQJ1, 6 ); 133 137 q = polevl( z, QPJ1, 7)/p1evl( z, QQJ1, 7 ); 134 135 xn = x - THPIO4; 138 xn = abs_x - THPIO4; 136 139 137 140 double sn, cn; … … 139 142 p = p * cn - w * q * sn; 140 143 141 return( p * SQ2OPI / sqrt(x) );144 return( sign_x * p * SQ2OPI / sqrt(abs_x) ); 142 145 } 143 146 … … 179 182 }; 180 183 181 float cephes_j1f(float x )184 float cephes_j1f(float xx) 182 185 { 183 186 184 float x x, w, z, p, q, xn;187 float x, w, z, p, q, xn; 185 188 186 189 const float Z1 = 1.46819706421238932572E1; … … 188 191 189 192 190 xx = x; 191 if( xx < 0 ) 192 xx = -x; 193 194 if( xx <= 2.0 ) { 195 z = xx * xx; 196 p = (z-Z1) * xx * polevl( z, JPJ1, 4 ); 197 return( p ); 193 // 2017-05-18 PAK - mathematica and mpmath use J1(-x) = -J1(x) 194 x = xx; 195 if( x < 0 ) 196 x = -xx; 197 198 if( x <= 2.0 ) { 199 z = x * x; 200 p = (z-Z1) * x * polevl( z, JPJ1, 4 ); 201 return( xx < 0. ? -p : p ); 198 202 } 199 203 … … 204 208 w = q*q; 205 209 xn = q * polevl( w, PH1J1, 7) - THPIO4F; 206 p = p * cos(xn + x x);207 208 return( p);210 p = p * cos(xn + x); 211 212 return( xx < 0. ? -p : p ); 209 213 } 210 214 #endif -
sasmodels/models/lib/sas_erf.c
rb3796fa reb2946f 165 165 // the erf function instead and z < 1.0. 166 166 //return (1.0 - cephes_erf(a)); 167 z = x * x; 168 y = x * polevl(z, TD, 4) / p1evl(z, UD, 5); 169 170 return y; 167 // 2017-05-18 PAK - use erf(a) rather than erf(|a|) 168 z = a * a; 169 y = a * polevl(z, TD, 4) / p1evl(z, UD, 5); 170 171 return 1.0 - y; 171 172 } 172 173 … … 279 280 //is explicit here for the case < 1.0 280 281 //return (1.0 - sas_erf(a)); 281 z = x * x; 282 y = x * polevl( z, TF, 6 ); 283 284 return y; 282 // 2017-05-18 PAK - use erf(a) rather than erf(|a|) 283 z = a * a; 284 y = a * polevl( z, TF, 6 ); 285 286 return 1.0 - y; 285 287 } 286 288 -
sasmodels/models/onion.py
r925ad6e 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]) -
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
r8e68ea0 r34a9e4e 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 must satisfy the condition that $A < B < C$. 24 This requirement is not enforced in the model, so it is up to the 25 user to check this during the analysis. 24 The three dimensions of the parallelepiped (strictly here a cuboid) may be given in 25 $any$ size order. To avoid multiple fit solutions, especially 26 with Monte-Carlo fit methods, it may be advisable to restrict their ranges. There may 27 be a number of closely similar "best fits", so some trial and error, or fixing of some 28 dimensions at expected values, may help. 26 29 27 30 The 1D scattering intensity $I(q)$ is calculated as: … … 67 70 \mu &= qB 68 71 69 70 72 The scattering intensity per unit volume is returned in units of |cm^-1|. 71 73 72 74 NB: The 2nd virial coefficient of the parallelepiped is calculated based on 73 the averaged effective radius $(=\sqrt{A B / \pi})$ and 75 the averaged effective radius, after appropriately sorting the three 76 dimensions, to give an oblate or prolate particle, $(=\sqrt{AB/\pi})$ and 74 77 length $(= C)$ values, and used as the effective radius for 75 78 $S(q)$ when $P(q) \cdot S(q)$ is applied. … … 102 105 .. _parallelepiped-orientation: 103 106 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 the107 .. figure:: img/parallelepiped_angle_definition.png 108 109 Definition of the angles for oriented parallelepiped, shown with $A<B<C$. 110 111 .. figure:: img/parallelepiped_angle_projection.png 112 113 Examples of the angles for an oriented parallelepiped against the 111 114 detector plane. 112 115 116 On introducing "Orientational Distribution" in the angles, "distribution of theta" and "distribution of phi" parameters will 117 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. 118 (When $\theta = \phi = 0$ these are parallel to the $Y$ and $X$ axes of the instrument.) The third orientation distribution, in $\psi$, is 119 about the $c$ axis of the particle, perpendicular to the $a$ x $b$ face. Some experimentation may be required to 120 understand the 2d patterns fully. (Earlier implementations had numerical integration issues in some circumstances when orientation 121 distributions passed through 90 degrees, such situations, with very broad distributions, should still be approached with care.) 122 123 113 124 For a given orientation of the parallelepiped, the 2D form factor is 114 125 calculated as … … 116 127 .. math:: 117 128 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]^2129 P(q_x, q_y) = \left[\frac{\sin(\tfrac{1}{2}qA\cos\alpha)}{(\tfrac{1}{2}qA\cos\alpha)}\right]^2 130 \left[\frac{\sin(\tfrac{1}{2}qB\cos\beta)}{(\tfrac{1}{2}qB\cos\beta)}\right]^2 131 \left[\frac{\sin(\tfrac{1}{2}qC\cos\gamma)}{(\tfrac{1}{2}qC\cos\gamma)}\right]^2 121 132 122 133 with … … 154 165 angles. 155 166 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 167 159 168 References … … 163 172 164 173 R Nayuk and K Huber, *Z. Phys. Chem.*, 226 (2012) 837-854 174 175 Authorship and Verification 176 ---------------------------- 177 178 * **Author:** This model is based on form factor calculations implemented 179 in a c-library provided by the NIST Center for Neutron Research (Kline, 2006). 180 * **Last Modified by:** Paul Kienzle **Date:** April 05, 2017 181 * **Last Reviewed by:** Richard Heenan **Date:** April 06, 2017 182 165 183 """ 166 184 167 185 import numpy as np 168 from numpy import pi, inf, sqrt 186 from numpy import pi, inf, sqrt, sin, cos 169 187 170 188 name = "parallelepiped" … … 180 198 mu = q*B 181 199 V: Volume of the rectangular parallelepiped 182 alpha: angle between the long axis of the 200 alpha: angle between the long axis of the 183 201 parallelepiped and the q-vector for 1D 184 202 """ … … 196 214 ["length_c", "Ang", 400, [0, inf], "volume", 197 215 "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"],216 ["theta", "degrees", 60, [-360, 360], "orientation", 217 "c axis to beam angle"], 218 ["phi", "degrees", 60, [-360, 360], "orientation", 219 "rotation about beam"], 220 ["psi", "degrees", 60, [-360, 360], "orientation", 221 "rotation about c axis"], 204 222 ] 205 223 … … 208 226 def ER(length_a, length_b, length_c): 209 227 """ 210 228 Return effective radius (ER) for P(q)*S(q) 211 229 """ 212 230 # now that axes can be in any size order, need to sort a,b,c where a~b and c is either much smaller 231 # or much larger 232 abc = np.vstack((length_a, length_b, length_c)) 233 abc = np.sort(abc, axis=0) 234 selector = (abc[1] - abc[0]) > (abc[2] - abc[1]) 235 length = np.where(selector, abc[0], abc[2]) 213 236 # 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))237 radius = np.sqrt(np.where(~selector, abc[0]*abc[1], abc[1]*abc[2]) / pi) 238 239 ddd = 0.75 * radius * (2*radius*length + (length + radius)*(length + pi*radius)) 217 240 return 0.5 * (ddd) ** (1. / 3.) 218 241 … … 230 253 phi_pd=10, phi_pd_n=1, 231 254 psi_pd=10, psi_pd_n=10) 232 233 qx, qy = 0.2 * np.cos(2.5), 0.2 * np.sin(2.5)255 # rkh 7/4/17 add random unit test for 2d, note make all params different, 2d values not tested against other codes or models 256 qx, qy = 0.2 * cos(pi/6.), 0.2 * sin(pi/6.) 234 257 tests = [[{}, 0.2, 0.17758004974], 235 258 [{}, [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]],259 [{'theta':10.0, 'phi':20.0}, (qx, qy), 0.0089517140475], 260 [{'theta':10.0, 'phi':20.0}, [(qx, qy)], [0.0089517140475]], 238 261 ] 239 262 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
r925ad6e 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/spherical_sld.py
r925ad6e r63a7fe8 199 199 category = "shape:sphere" 200 200 201 SHAPES = [ ["erf(|nu|*z)", "Rpow(z^|nu|)", "Lpow(z^|nu|)",202 "Rexp(-|nu|z)", "Lexp(-|nu|z)"]]201 SHAPES = ["erf(|nu|*z)", "Rpow(z^|nu|)", "Lpow(z^|nu|)", 202 "Rexp(-|nu|z)", "Lexp(-|nu|z)"] 203 203 204 204 # pylint: disable=bad-whitespace, line-too-long … … 209 209 ["thickness[n_shells]", "Ang", 100.0, [0, inf], "volume", "thickness shell"], 210 210 ["interface[n_shells]", "Ang", 50.0, [0, inf], "volume", "thickness of the interface"], 211 ["shape[n_shells]", "", 0, SHAPES,"", "interface shape"],211 ["shape[n_shells]", "", 0, [SHAPES], "", "interface shape"], 212 212 ["nu[n_shells]", "", 2.5, [0, inf], "", "interface shape exponent"], 213 213 ["n_steps", "", 35, [0, inf], "", "number of steps in each interface (must be an odd integer)"], -
sasmodels/models/stacked_disks.py
rb7e8b94 r1b85b55 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) 158 # Accuracy tests based on content in test/utest_extra_models.py. 159 # Added 2 tests with n_stacked = 5 using SasView 3.1.2 - PDB; 160 # for which alas q=0.001 values seem closer to n_stacked=1 not 5, 161 # changed assuming my 4.1 code OK, RKH 155 162 tests = [ 156 # 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 158 [{'thick_core': 10.0, 159 'thick_layer': 15.0, 160 'radius': 3000.0, 161 'n_stacking': 1.0, 162 'sigma_d': 0.0, 163 'sld_core': 4.0, 164 'sld_layer': -0.4, 165 'solvent_sd': 5.0, 163 [{'thick_core': 10.0, 164 'thick_layer': 15.0, 165 'radius': 3000.0, 166 'n_stacking': 1.0, 167 'sigma_d': 0.0, 168 'sld_core': 4.0, 169 'sld_layer': -0.4, 170 'sld_solvent': 5.0, 166 171 'theta': 90.0, 167 172 'phi': 0.0, … … 176 181 'sld_core': 4.0, 177 182 'sld_layer': -0.4, 178 's olvent_sd': 5.0,183 'sld_solvent': 5.0, 179 184 'theta': 90.0, 180 185 'phi': 0.0, … … 186 191 [{'thick_core': 10.0, 187 192 'thick_layer': 15.0, 188 'radius': 3000.0,193 'radius': 100.0, 189 194 'n_stacking': 5, 190 195 'sigma_d': 0.0, 191 196 'sld_core': 4.0, 192 197 'sld_layer': -0.4, 193 'solvent_sd': 5.0, 198 'sld_solvent': 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, 206 'radius': 3000.0, 207 'n_stacking': 5, 208 'sigma_d': 0.0, 209 'sld_core': 4.0, 210 'sld_layer': -0.4, 211 'sld_solvent': 5.0, 194 212 'theta': 90.0, 195 213 'phi': 0.0, … … 207 225 'sld_core': 4.0, 208 226 'sld_layer': -0.4, 209 's olvent_sd': 5.0,227 'sld_solvent': 5.0, 210 228 'theta': 90.0, 211 229 'phi': 0.0, … … 222 240 'sld_core': 4.0, 223 241 'sld_layer': -0.4, 224 's olvent_sd': 5.0,242 'sld_solvent': 5.0, 225 243 'theta': 90.0, 226 244 'phi': 0.0, … … 228 246 'background': 0.001, 229 247 }, ([0.4, 0.5]), [0.00105074, 0.00121761]], 230 231 [{'thick_core': 10.0, 232 'thick_layer': 15.0, 233 'radius': 3000.0, 234 'n_stacking': 1.0, 235 'sigma_d': 0.0, 236 'sld_core': 4.0, 237 'sld_layer': -0.4, 238 'solvent_sd': 5.0, 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 'sld_solvent': 5.0, 256 'theta': 90.0, 257 'phi': 20.0, 258 'scale': 0.01, 259 'background': 0.001, 260 # 2017-05-18 PAK temporarily suppress output of qx,qy test; j1 is not accurate for large qr 261 # }, (qx, qy), 0.0341738733124], 262 }, (qx, qy), None], 263 264 [{'thick_core': 10.0, 265 'thick_layer': 15.0, 266 'radius': 3000.0, 267 'n_stacking': 1.0, 268 'sigma_d': 0.0, 269 'sld_core': 4.0, 270 'sld_layer': -0.4, 271 'sld_solvent': 5.0, 239 272 'theta': 90.0, 240 273 'phi': 0.0, … … 243 276 }, ([1.3, 1.57]), [0.0010039, 0.0010038]], 244 277 ] 245 # 11Jan2017 RKH checking unit test agai, note they are all 1D, no 2D 246 278 # 11Jan2017 RKH checking unit test again, note they are all 1D, no 2D -
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
r925ad6e r34a9e4e 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 34 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) 67 68 Though for convenience we describe the three radii of the ellipsoid as equatorial 69 and polar, they may be given in $any$ size order. To avoid multiple solutions, especially 70 with Monte-Carlo fit methods, it may be advisable to restrict their ranges. For typical 71 small angle diffraction situations there may be a number of closely similar "best fits", 72 so some trial and error, or fixing of some radii at expected values, may help. 73 35 74 To provide easy access to the orientation of the triaxial ellipsoid, 36 75 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. 76 and $\psi$. These angles are defined analogously to the elliptical_cylinder below, note that 77 angle $\phi$ is now NOT the same as in the equations above. 78 79 .. figure:: img/elliptical_cylinder_angle_definition.png 80 81 Definition of angles for oriented triaxial ellipsoid, where radii are for illustration here 82 $a < b << c$ and angle $\Psi$ is a rotation around the axis of the particle. 83 84 For oriented ellipsoids the *theta*, *phi* and *psi* orientation parameters will appear when fitting 2D data, 85 see the :ref:`elliptical-cylinder` model for further information. 42 86 43 87 .. _triaxial-ellipsoid-angles: 44 88 45 .. figure:: img/triaxial_ellipsoid_angle_projection. jpg89 .. figure:: img/triaxial_ellipsoid_angle_projection.png 46 90 47 The angles for orientedellipsoid.91 Some examples for an oriented triaxial ellipsoid. 48 92 49 93 The radius-of-gyration for this system is $R_g^2 = (R_a R_b R_c)^2/5$. 50 94 51 The contrast is defined as SLD(ellipsoid) - SLD(solvent). In the95 The contrast $\Delta\rho$ is defined as SLD(ellipsoid) - SLD(solvent). In the 52 96 parameters, $R_a$ is the minor equatorial radius, $R_b$ is the major 53 97 equatorial radius, and $R_c$ is the polar radius of the ellipsoid. 54 98 55 99 NB: The 2nd virial coefficient of the triaxial solid ellipsoid is 56 calculated based on the polar radius $R_p = R_c$ and equatorial 57 radius $R_e = \sqrt{R_a R_b}$, and used as the effective radius for 100 calculated after sorting the three radii to give the most appropriate 101 prolate or oblate form, from the new polar radius $R_p = R_c$ and effective equatorial 102 radius, $R_e = \sqrt{R_a R_b}$, to then be used as the effective radius for 58 103 $S(q)$ when $P(q) \cdot S(q)$ is applied. 59 104 … … 69 114 ---------- 70 115 71 L A Feigin and D I Svergun, *Structure Analysis by Small-Angle X-Ray 72 and Neutron Scattering*, Plenum, New York, 1987. 116 [1] Finnigan, J.A., Jacobs, D.J., 1971. 117 *Light scattering by ellipsoidal particles in solution*, 118 J. Phys. D: Appl. Phys. 4, 72-77. doi:10.1088/0022-3727/4/1/310 119 120 Authorship and Verification 121 ---------------------------- 122 123 * **Author:** NIST IGOR/DANSE **Date:** pre 2010 124 * **Last Modified by:** Paul Kienzle (improved calculation) **Date:** April 4, 2017 125 * **Last Reviewed by:** Paul Kienzle & Richard Heenan **Date:** April 4, 2017 73 126 """ 74 127 75 from numpy import inf 128 from numpy import inf, sin, cos, pi 76 129 77 130 name = "triaxial_ellipsoid" 78 131 title = "Ellipsoid of uniform scattering length density with three independent axes." 79 132 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. 133 description = """ 134 Triaxial ellipsoid - see main documentation. 84 135 """ 85 136 category = "shape:ellipsoid" … … 91 142 "Solvent scattering length density"], 92 143 ["radius_equat_minor", "Ang", 20, [0, inf], "volume", 93 "Minor equatorial radius "],144 "Minor equatorial radius, Ra"], 94 145 ["radius_equat_major", "Ang", 400, [0, inf], "volume", 95 "Major equatorial radius "],146 "Major equatorial radius, Rb"], 96 147 ["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"],148 "Polar radius, Rc"], 149 ["theta", "degrees", 60, [-360, 360], "orientation", 150 "polar axis to beam angle"], 151 ["phi", "degrees", 60, [-360, 360], "orientation", 152 "rotation about beam"], 153 ["psi", "degrees", 60, [-360, 360], "orientation", 154 "rotation about polar axis"], 104 155 ] 105 156 … … 108 159 def ER(radius_equat_minor, radius_equat_major, radius_polar): 109 160 """ 110 161 Returns the effective radius used in the S*P calculation 111 162 """ 112 163 import numpy as np 113 164 from .ellipsoid import ER as ellipsoid_ER 114 return ellipsoid_ER(radius_polar, np.sqrt(radius_equat_minor * radius_equat_major)) 165 166 # now that radii can be in any size order, radii need sorting a,b,c 167 # where a~b and c is either much smaller or much larger 168 radii = np.vstack((radius_equat_major, radius_equat_minor, radius_polar)) 169 radii = np.sort(radii, axis=0) 170 selector = (radii[1] - radii[0]) > (radii[2] - radii[1]) 171 polar = np.where(selector, radii[0], radii[2]) 172 equatorial = np.sqrt(np.where(~selector, radii[0]*radii[1], radii[1]*radii[2])) 173 return ellipsoid_ER(polar, equatorial) 115 174 116 175 demo = dict(scale=1, background=0, … … 124 183 phi_pd=15, phi_pd_n=1, 125 184 psi_pd=15, psi_pd_n=1) 185 186 q = 0.1 187 # april 6 2017, rkh add unit tests 188 # NOT compared with any other calc method, assume correct! 189 # check 2d test after pull #890 190 qx = q*cos(pi/6.0) 191 qy = q*sin(pi/6.0) 192 tests = [[{}, 0.05, 24.8839548033], 193 [{'theta':80., 'phi':10.}, (qx, qy), 166.712060266 ], 194 ] 195 del qx, qy # not necessary to delete, but cleaner -
sasmodels/models/two_power_law.py
r40a87fa rbb4b509 120 120 }, 0.150141, 0.125945], 121 121 122 [{'coeff cent_1': 1.0,122 [{'coefficent_1': 1.0, 123 123 'crossover': 0.04, 124 124 'power_1': 1.0, … … 127 127 }, 0.442528, 0.00166884], 128 128 129 [{'coeff cent_1': 1.0,129 [{'coefficent_1': 1.0, 130 130 'crossover': 0.04, 131 131 'power_1': 1.0, -
sasmodels/rst2html.py
r0890871 rf2f5413 29 29 from docutils.writers.html4css1 import HTMLTranslator 30 30 from docutils.nodes import SkipNode 31 32 def wxview(html, url="", size=(850, 540)):33 import wx34 from wx.html2 import WebView35 frame = wx.Frame(None, -1, size=size)36 view = WebView.New(frame)37 view.SetPage(html, url)38 frame.Show()39 return frame40 41 def view_rst(filename):42 from os.path import expanduser43 with open(expanduser(filename)) as fid:44 rst = fid.read()45 html = rst2html(rst)46 wxview(html)47 31 48 32 def rst2html(rst, part="whole", math_output="mathjax"): … … 155 139 assert replace_dollar(u"a (again $in parens$) a") == u"a (again :math:`in parens`) a" 156 140 157 def view_rst_app(filename): 141 def load_rst_as_html(filename): 142 from os.path import expanduser 143 with open(expanduser(filename)) as fid: 144 rst = fid.read() 145 html = rst2html(rst) 146 return html 147 148 def wxview(html, url="", size=(850, 540)): 149 import wx 150 from wx.html2 import WebView 151 frame = wx.Frame(None, -1, size=size) 152 view = WebView.New(frame) 153 view.SetPage(html, url) 154 frame.Show() 155 return frame 156 157 def view_html_wxapp(html, url=""): 158 158 import wx # type: ignore 159 159 app = wx.App() 160 view_rst(filename)160 frame = wxview(html, url) 161 161 app.MainLoop() 162 162 163 def view_url_wxapp(url): 164 import wx # type: ignore 165 from wx.html2 import WebView 166 app = wx.App() 167 frame = wx.Frame(None, -1, size=(850, 540)) 168 view = WebView.New(frame) 169 view.LoadURL(url) 170 frame.Show() 171 app.MainLoop() 172 173 def qtview(html, url=""): 174 try: 175 from PyQt5.QtWebKitWidgets import QWebView 176 from PyQt5.QtCore import QUrl 177 except ImportError: 178 from PyQt4.QtWebkit import QWebView 179 from PyQt4.QtCore import QUrl 180 helpView = QWebView() 181 helpView.setHtml(html, QUrl(url)) 182 helpView.show() 183 return helpView 184 185 def view_html_qtapp(html, url=""): 186 import sys 187 try: 188 from PyQt5.QtWidgets import QApplication 189 except ImportError: 190 from PyQt4.QtGui import QApplication 191 app = QApplication([]) 192 frame = qtview(html, url) 193 sys.exit(app.exec_()) 194 195 def view_url_qtapp(url): 196 import sys 197 try: 198 from PyQt5.QtWidgets import QApplication 199 except ImportError: 200 from PyQt4.QtGui import QApplication 201 app = QApplication([]) 202 try: 203 from PyQt5.QtWebKitWidgets import QWebView 204 from PyQt5.QtCore import QUrl 205 except ImportError: 206 from PyQt4.QtWebkit import QWebView 207 from PyQt4.QtCore import QUrl 208 frame = QWebView() 209 frame.load(QUrl(url)) 210 frame.show() 211 sys.exit(app.exec_()) 212 213 def view_help(filename, qt=False): 214 import os 215 url="file:///"+os.path.abspath(filename).replace("\\","/") 216 if filename.endswith('.rst'): 217 html = load_rst_as_html(filename) 218 if qt: 219 view_html_qtapp(html, url) 220 else: 221 view_html_wxapp(html, url) 222 else: 223 if qt: 224 view_url_qtapp(url) 225 else: 226 view_url_wxapp(url) 163 227 164 228 if __name__ == "__main__": 165 229 import sys 166 view_ rst_app(sys.argv[1])167 230 view_help(sys.argv[1], qt=True) 231
Note: See TracChangeset
for help on using the changeset viewer.