Changes in / [5da1ac8:bef029d] in sasmodels
- Files:
-
- 3 added
- 3 deleted
- 28 edited
Legend:
- Unmodified
- Added
- Removed
-
.travis.yml
r947a61e rce8c388 24 24 packages: opencl-headers 25 25 before_install: 26 - openssl aes-256-cbc -K $encrypted_fe6026add10a_key -iv $encrypted_fe6026add10a_iv27 -in .travis/travis_rsa.enc -out .travis/travis_rsa -d 26 - if [[ $encrypted_cb04388797b6_iv ]]; then openssl aes-256-cbc -K $encrypted_cb04388797b6_key -iv $encrypted_cb04388797b6_iv 27 -in .travis/travis_rsa.enc -out .travis/travis_rsa -d; fi; 28 28 - echo $TRAVIS_OS_NAME 29 29 - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh … … 46 46 - echo -e "Host danse.chem.utk.edu\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config 47 47 deploy: 48 49 50 script: /bin/sh -ex ./deploy.sh51 52 48 skip_cleanup: true 49 provider: script 50 script: "/bin/sh -ex ./deploy.sh" 51 on: 52 branch: master 53 53 notifications: 54 54 slack: -
deploy.sh
rd9d77b0 r9d1e3e4 1 eval "$(ssh-agent -s)" 2 chmod 600 .travis/travis_rsa 3 ssh-add .travis/travis_rsa 4 git remote add deploy git@danse.chem.utk.edu:/home/git/sasmodels 5 git push deploy master 1 if [[ $encrypted_cb04388797b6_iv ]] 2 then 3 eval "$(ssh-agent -s)" 4 chmod 600 .travis/travis_rsa 5 ssh-add .travis/travis_rsa 6 git remote add deploy git@danse.chem.utk.edu:/home/git/sasmodels 7 git push deploy master 8 fi -
doc/conf.py
r8ae8532 r30b60d2 211 211 #latex_preamble = '' 212 212 LATEX_PREAMBLE=r""" 213 \newcommand{\lt}{<} 214 \newcommand{\gt}{>} 213 215 \renewcommand{\AA}{\text{\r{A}}} % Allow \AA in math mode 214 216 \usepackage[utf8]{inputenc} % Allow unicode symbols in text -
doc/guide/magnetism/magnetism.rst
r990d8df r990d8df 16 16 17 17 .. figure:: 18 mag_img/mag_vector. bmp18 mag_img/mag_vector.png 19 19 20 20 The magnetic scattering length density is then … … 36 36 37 37 .. figure:: 38 mag_img/M_angles_pic. bmp38 mag_img/M_angles_pic.png 39 39 40 40 If the angles of the $Q$ vector and the spin-axis $x'$ to the $x$ - axis are -
doc/guide/plugin.rst
r870a2f4 r30b60d2 117 117 Models that do not conform to these requirements will *never* be incorporated 118 118 into the built-in library. 119 120 More complete documentation for the sasmodels package can be found at121 `<http://www.sasview.org/sasmodels>`_. In particular,122 `<http://www.sasview.org/sasmodels/api/generate.html#module-sasmodels.generate>`_123 describes the structure of a model.124 119 125 120 … … 613 608 614 609 sas_gamma(x): 615 Gamma function $\text{sas_gamma}(x) = \Gamma(x)$.610 Gamma function sas_gamma\ $(x) = \Gamma(x)$. 616 611 617 612 The standard math function, tgamma(x) is unstable for $x < 1$ … … 623 618 sas_erf(x), sas_erfc(x): 624 619 Error function 625 $\text{sas_erf}(x) = \frac{2}{\sqrt\pi}\int_0^x e^{-t^2}\,dt$620 sas_erf\ $(x) = \frac{2}{\sqrt\pi}\int_0^x e^{-t^2}\,dt$ 626 621 and complementary error function 627 $\text{sas_erfc}(x) = \frac{2}{\sqrt\pi}\int_x^{\infty} e^{-t^2}\,dt$.622 sas_erfc\ $(x) = \frac{2}{\sqrt\pi}\int_x^{\infty} e^{-t^2}\,dt$. 628 623 629 624 The standard math functions erf(x) and erfc(x) are slower and broken … … 634 629 635 630 sas_J0(x): 636 Bessel function of the first kind $\text{sas_J0}(x)=J_0(x)$ where631 Bessel function of the first kind sas_J0\ $(x)=J_0(x)$ where 637 632 $J_0(x) = \frac{1}{\pi}\int_0^\pi \cos(x\sin(\tau))\,d\tau$. 638 633 … … 643 638 644 639 sas_J1(x): 645 Bessel function of the first kind $\text{sas_J1}(x)=J_1(x)$ where640 Bessel function of the first kind sas_J1\ $(x)=J_1(x)$ where 646 641 $J_1(x) = \frac{1}{\pi}\int_0^\pi \cos(\tau - x\sin(\tau))\,d\tau$. 647 642 … … 652 647 653 648 sas_JN(n, x): 654 Bessel function of the first kind and integer order $n$ :655 $\text{sas_JN}(n, x)=J_n(x)$ where649 Bessel function of the first kind and integer order $n$, 650 sas_JN\ $(n, x) =J_n(x)$ where 656 651 $J_n(x) = \frac{1}{\pi}\int_0^\pi \cos(n\tau - x\sin(\tau))\,d\tau$. 657 If $n$ = 0 or 1, it uses sas_J0( x) or sas_J1(x), respectively.652 If $n$ = 0 or 1, it uses sas_J0($x$) or sas_J1($x$), respectively. 658 653 659 654 The standard math function jn(n, x) is not available on all platforms. … … 663 658 664 659 sas_Si(x): 665 Sine integral $\text{Si}(x) = \int_0^x \tfrac{\sin t}{t}\,dt$.660 Sine integral Si\ $(x) = \int_0^x \tfrac{\sin t}{t}\,dt$. 666 661 667 662 This function uses Taylor series for small and large arguments: … … 688 683 sas_3j1x_x(x): 689 684 Spherical Bessel form 690 $\text{sph_j1c}(x) = 3 j_1(x)/x = 3 (\sin(x) - x \cos(x))/x^3$,685 sph_j1c\ $(x) = 3 j_1(x)/x = 3 (\sin(x) - x \cos(x))/x^3$, 691 686 with a limiting value of 1 at $x=0$, where $j_1(x)$ is the spherical 692 687 Bessel function of the first kind and first order. … … 699 694 700 695 sas_2J1x_x(x): 701 Bessel form $\text{sas_J1c}(x) = 2 J_1(x)/x$, with a limiting value696 Bessel form sas_J1c\ $(x) = 2 J_1(x)/x$, with a limiting value 702 697 of 1 at $x=0$, where $J_1(x)$ is the Bessel function of first kind 703 698 and first order. -
doc/guide/resolution.rst
rf8a2baa r30b60d2 212 212 elliptical Gaussian distribution. The $A$ is a normalization factor. 213 213 214 .. figure:: resolution_2d_rotation. gif214 .. figure:: resolution_2d_rotation.png 215 215 216 216 Coordinate axis rotation for 2D resolution calculation. -
doc/rst_prolog
ra0fb06a r30b60d2 1 1 .. Set up some substitutions to make life easier... 2 .. Remove |biggamma|, etc. when they are no longer needed.3 2 4 5 .. |alpha| unicode:: U+03B16 .. |beta| unicode:: U+03B27 .. |gamma| unicode:: U+03B38 .. |delta| unicode:: U+03B49 .. |epsilon| unicode:: U+03B510 .. |zeta| unicode:: U+03B611 .. |eta| unicode:: U+03B712 .. |theta| unicode:: U+03B813 .. |iota| unicode:: U+03B914 .. |kappa| unicode:: U+03BA15 .. |lambda| unicode:: U+03BB16 .. |mu| unicode:: U+03BC17 .. |nu| unicode:: U+03BD18 .. |xi| unicode:: U+03BE19 .. |omicron| unicode:: U+03BF20 .. |pi| unicode:: U+03C021 .. |rho| unicode:: U+03C122 .. |sigma| unicode:: U+03C323 .. |tau| unicode:: U+03C424 .. |upsilon| unicode:: U+03C525 .. |phi| unicode:: U+03C626 .. |chi| unicode:: U+03C727 .. |psi| unicode:: U+03C828 .. |omega| unicode:: U+03C929 30 31 .. |biggamma| unicode:: U+039332 .. |bigdelta| unicode:: U+039433 .. |bigzeta| unicode:: U+039E34 .. |bigpsi| unicode:: U+03A835 .. |bigphi| unicode:: U+03A636 .. |bigsigma| unicode:: U+03A337 .. |Gamma| unicode:: U+039338 .. |Delta| unicode:: U+039439 .. |Zeta| unicode:: U+039E40 .. |Psi| unicode:: U+03A841 42 43 .. |drho| replace:: |Delta|\ |rho|44 3 .. |Ang| unicode:: U+212B 45 4 .. |Ang^-1| replace:: |Ang|\ :sup:`-1` … … 57 16 .. |cm^-3| replace:: cm\ :sup:`-3` 58 17 .. |sr^-1| replace:: sr\ :sup:`-1` 59 .. |P0| replace:: P\ :sub:`0`\60 .. |A2| replace:: A\ :sub:`2`\61 62 63 .. |equiv| unicode:: U+226164 .. |noteql| unicode:: U+226065 .. |TM| unicode:: U+212266 67 18 68 19 .. |cdot| unicode:: U+00B7 -
sasmodels/compare.py
rd9ec8f9 r765eb0e 88 88 -magnetic/-nonmagnetic* suppress magnetism 89 89 -accuracy=Low accuracy of the resolution calculation Low, Mid, High, Xhigh 90 -neval=1 sets the number of evals for more accurate timing 90 91 91 92 === precision options === … … 1013 1014 'magnetic', 'nonmagnetic', 1014 1015 'accuracy=', 1016 'neval=', # for timing... 1015 1017 1016 1018 # Precision options … … 1018 1020 'half', 'fast', 'single', 'double', 'single!', 'double!', 'quad!', 1019 1021 'sasview', # TODO: remove sasview 3.x support 1020 'timing=',1021 1022 1022 1023 # Output options … … 1068 1069 1069 1070 # Plug in values given in demo 1070 if use_demo :1071 if use_demo and model_info.demo: 1071 1072 pars.update(model_info.demo) 1072 1073 return pars -
sasmodels/core.py
rbb39b4a r60335cc 10 10 11 11 import os 12 import re 12 13 from os.path import basename, dirname, join as joinpath 13 14 from glob import glob … … 21 22 from . import kernelpy 22 23 from . import kerneldll 24 from . import custom 23 25 24 26 if os.environ.get("SAS_OPENCL", "").lower() == "none": … … 30 32 except Exception: 31 33 HAVE_OPENCL = False 34 35 CUSTOM_MODEL_PATH = os.environ.get('SAS_MODELPATH', "") 36 if CUSTOM_MODEL_PATH == "": 37 path = joinpath(os.path.expanduser("~"), ".sasmodels", "custom_models") 38 if not os.path.isdir(path): 39 os.makedirs(path) 40 CUSTOM_MODEL_PATH = path 32 41 33 42 try: … … 125 134 dtype=dtype, platform=platform) 126 135 127 128 def load_model_info(model_name): 136 def load_model_info(model_string): 129 137 # type: (str) -> modelinfo.ModelInfo 130 138 """ 131 139 Load a model definition given the model name. 132 140 133 *model_name* is the name of the model, or perhaps a model expression 134 such as sphere*hardsphere or sphere+cylinder. 141 *model_string* is the name of the model, or perhaps a model expression 142 such as sphere*cylinder or sphere+cylinder. Use '@' for a structure 143 factor product, e.g. sphere@hardsphere. Custom models can be specified by 144 prefixing the model name with 'custom.', e.g. 'custom.MyModel+sphere'. 135 145 136 146 This returns a handle to the module defining the model. This can be 137 147 used with functions in generate to build the docs or extract model info. 138 148 """ 139 parts = model_name.split('+') 140 if len(parts) > 1: 141 model_info_list = [load_model_info(p) for p in parts] 142 return mixture.make_mixture_info(model_info_list) 143 144 parts = model_name.split('*') 145 if len(parts) > 1: 146 if len(parts) > 2: 147 raise ValueError("use P*S to apply structure factor S to model P") 148 P_info, Q_info = [load_model_info(p) for p in parts] 149 if '@' in model_string: 150 parts = model_string.split('@') 151 if len(parts) != 2: 152 raise ValueError("Use P@S to apply a structure factor S to model P") 153 P_info, Q_info = [load_model_info(part) for part in parts] 149 154 return product.make_product_info(P_info, Q_info) 150 155 151 kernel_module = generate.load_kernel_module(model_name) 152 return modelinfo.make_model_info(kernel_module) 156 product_parts = [] 157 addition_parts = [] 158 159 addition_parts_names = model_string.split('+') 160 if len(addition_parts_names) >= 2: 161 addition_parts = [load_model_info(part) for part in addition_parts_names] 162 elif len(addition_parts_names) == 1: 163 product_parts_names = model_string.split('*') 164 if len(product_parts_names) >= 2: 165 product_parts = [load_model_info(part) for part in product_parts_names] 166 elif len(product_parts_names) == 1: 167 if "custom." in product_parts_names[0]: 168 # Extract ModelName from "custom.ModelName" 169 pattern = "custom.([A-Za-z0-9_-]+)" 170 result = re.match(pattern, product_parts_names[0]) 171 if result is None: 172 raise ValueError("Model name in invalid format: " + product_parts_names[0]) 173 model_name = result.group(1) 174 # Use ModelName to find the path to the custom model file 175 model_path = joinpath(CUSTOM_MODEL_PATH, model_name + ".py") 176 if not os.path.isfile(model_path): 177 raise ValueError("The model file {} doesn't exist".format(model_path)) 178 kernel_module = custom.load_custom_kernel_module(model_path) 179 return modelinfo.make_model_info(kernel_module) 180 # Model is a core model 181 kernel_module = generate.load_kernel_module(product_parts_names[0]) 182 return modelinfo.make_model_info(kernel_module) 183 184 model = None 185 if len(product_parts) > 1: 186 model = mixture.make_mixture_info(product_parts, operation='*') 187 if len(addition_parts) > 1: 188 if model is not None: 189 addition_parts.append(model) 190 model = mixture.make_mixture_info(addition_parts, operation='+') 191 return model 153 192 154 193 -
sasmodels/generate.py
r573ffab r30b60d2 210 210 211 211 # Conversion from units defined in the parameter table for each model 212 # to units displayed in the sphinx documentation. 212 # to units displayed in the sphinx documentation. 213 213 # This section associates the unit with the macro to use to produce the LaTex 214 214 # code. The macro itself needs to be defined in sasmodels/doc/rst_prolog. … … 216 216 # NOTE: there is an RST_PROLOG at the end of this file which is NOT 217 217 # used for the bundled documentation. Still as long as we are defining the macros 218 # in two places any new addition should define the macro in both places. 218 # in two places any new addition should define the macro in both places. 219 219 RST_UNITS = { 220 220 "Ang": "|Ang|", … … 898 898 .. |cm^-3| replace:: cm\ :sup:`-3` 899 899 .. |sr^-1| replace:: sr\ :sup:`-1` 900 .. |P0| replace:: P\ :sub:`0`\901 902 .. |equiv| unicode:: U+2261903 .. |noteql| unicode:: U+2260904 .. |TM| unicode:: U+2122905 900 906 901 .. |cdot| unicode:: U+00B7 -
sasmodels/mixture.py
r6dc78e4 r765eb0e 25 25 pass 26 26 27 def make_mixture_info(parts ):27 def make_mixture_info(parts, operation='+'): 28 28 # type: (List[ModelInfo]) -> ModelInfo 29 29 """ 30 30 Create info block for mixture model. 31 31 """ 32 flatten = []33 for part in parts:34 if part.composition and part.composition[0] == 'mixture':35 flatten.extend(part.composition[1])36 else:37 flatten.append(part)38 parts = flatten39 40 32 # Build new parameter list 41 33 combined_pars = [] 42 demo = {} 43 for k, part in enumerate(parts): 34 35 model_num = 0 36 all_parts = copy(parts) 37 is_flat = False 38 while not is_flat: 39 is_flat = True 40 for part in all_parts: 41 if part.composition and part.composition[0] == 'mixture' and \ 42 len(part.composition[1]) > 1: 43 all_parts += part.composition[1] 44 all_parts.remove(part) 45 is_flat = False 46 47 # When creating a mixture model that is a sum of product models (ie (1*2)+(3*4)) 48 # the parameters for models 1 & 2 will be prefixed with A & B respectively, 49 # but so will the parameters for models 3 & 4. We need to rename models 3 & 4 50 # so that they are prefixed with C & D to avoid overlap of parameter names. 51 used_prefixes = [] 52 for part in parts: 53 i = 0 54 if part.composition and part.composition[0] == 'mixture': 55 npars_list = [info.parameters.npars for info in part.composition[1]] 56 for npars in npars_list: 57 # List of params of one of the constituent models of part 58 submodel_pars = part.parameters.kernel_parameters[i:i+npars] 59 # Prefix of the constituent model 60 prefix = submodel_pars[0].name[0] 61 if prefix not in used_prefixes: # Haven't seen this prefix so far 62 used_prefixes.append(prefix) 63 i += npars 64 continue 65 while prefix in used_prefixes: 66 # This prefix has been already used, so change it to the 67 # next letter that hasn't been used 68 prefix = chr(ord(prefix) + 1) 69 used_prefixes.append(prefix) 70 prefix += "_" 71 # Update the parameters of this constituent model to use the 72 # new prefix 73 for par in submodel_pars: 74 par.id = prefix + par.id[2:] 75 par.name = prefix + par.name[2:] 76 if par.length_control is not None: 77 par.length_control = prefix + par.length_control[2:] 78 i += npars 79 80 for part in parts: 44 81 # Parameter prefix per model, A_, B_, ... 45 82 # Note that prefix must also be applied to id and length_control 46 83 # to support vector parameters 47 prefix = chr(ord('A')+k) + '_' 48 scale = Parameter(prefix+'scale', default=1.0, 49 description="model intensity for " + part.name) 50 combined_pars.append(scale) 84 prefix = '' 85 if not part.composition: 86 # Model isn't a composition model, so it's parameters don't have a 87 # a prefix. Add the next available prefix 88 prefix = chr(ord('A')+len(used_prefixes)) 89 used_prefixes.append(prefix) 90 prefix += '_' 91 92 if operation == '+': 93 # If model is a sum model, each constituent model gets its own scale parameter 94 scale_prefix = prefix 95 if prefix == '' and part.operation == '*': 96 # `part` is a composition product model. Find the prefixes of 97 # it's parameters to form a new prefix for the scale, eg: 98 # a model with A*B*C will have ABC_scale 99 sub_prefixes = [] 100 for param in part.parameters.kernel_parameters: 101 # Prefix of constituent model 102 sub_prefix = param.id.split('_')[0] 103 if sub_prefix not in sub_prefixes: 104 sub_prefixes.append(sub_prefix) 105 # Concatenate sub_prefixes to form prefix for the scale 106 scale_prefix = ''.join(sub_prefixes) + '_' 107 scale = Parameter(scale_prefix + 'scale', default=1.0, 108 description="model intensity for " + part.name) 109 combined_pars.append(scale) 51 110 for p in part.parameters.kernel_parameters: 52 111 p = copy(p) … … 56 115 p.length_control = prefix + p.length_control 57 116 combined_pars.append(p) 58 demo.update((prefix+k, v) for k, v in part.demo.items()59 if k != "background")60 #print("pars",combined_pars)61 117 parameters = ParameterTable(combined_pars) 62 118 parameters.max_pd = sum(part.parameters.max_pd for part in parts) 63 119 120 def random(): 121 combined_pars = {} 122 for k, part in enumerate(parts): 123 prefix = chr(ord('A')+k) + '_' 124 pars = part.random() 125 combined_pars.update((prefix+k, v) for k, v in pars.items()) 126 return combined_pars 127 64 128 model_info = ModelInfo() 65 model_info.id = '+'.join(part.id for part in parts) 66 model_info.name = ' + '.join(part.name for part in parts) 129 model_info.id = operation.join(part.id for part in parts) 130 model_info.operation = operation 131 model_info.name = '(' + operation.join(part.name for part in parts) + ')' 67 132 model_info.filename = None 68 133 model_info.title = 'Mixture model with ' + model_info.name … … 71 136 model_info.category = "custom" 72 137 model_info.parameters = parameters 138 model_info.random = random 73 139 #model_info.single = any(part['single'] for part in parts) 74 140 model_info.structure_factor = False … … 79 145 # Remember the component info blocks so we can build the model 80 146 model_info.composition = ('mixture', parts) 81 model_info.demo = demo82 147 return model_info 83 148 … … 88 153 self.info = model_info 89 154 self.parts = parts 155 self.dtype = parts[0].dtype 90 156 91 157 def make_kernel(self, q_vectors): … … 116 182 self.kernels = kernels 117 183 self.dtype = self.kernels[0].dtype 184 self.operation = model_info.operation 118 185 self.results = [] # type: List[np.ndarray] 119 186 … … 124 191 # remember the parts for plotting later 125 192 self.results = [] # type: List[np.ndarray] 126 offset = 2 # skip scale & background127 193 parts = MixtureParts(self.info, self.kernels, call_details, values) 128 194 for kernel, kernel_details, kernel_values in parts: 129 195 #print("calling kernel", kernel.info.name) 130 196 result = kernel(kernel_details, kernel_values, cutoff, magnetic) 131 #print(kernel.info.name, result) 132 total += result 197 result = np.array(result).astype(kernel.dtype) 198 # print(kernel.info.name, result) 199 if self.operation == '+': 200 total += result 201 elif self.operation == '*': 202 if np.all(total) == 0.0: 203 total = result 204 else: 205 total *= result 133 206 self.results.append(result) 134 207 … … 171 244 172 245 self.part_num += 1 173 self.par_index += info.parameters.npars + 1 246 self.par_index += info.parameters.npars 247 if self.model_info.operation == '+': 248 self.par_index += 1 # Account for each constituent model's scale param 174 249 self.mag_index += 3 * len(info.parameters.magnetism_index) 175 250 … … 182 257 # which includes the initial scale and background parameters. 183 258 # We want the index into the weight length/offset for each parameter. 184 # Exclude the initial scale and background, so subtract two, but each 185 # component has its own scale factor which we need to skip when 186 # constructing the details for the kernel, so add one, giving a 187 # net subtract one. 188 index = slice(par_index - 1, par_index - 1 + info.parameters.npars) 259 # Exclude the initial scale and background, so subtract two. If we're 260 # building an addition model, each component has its own scale factor 261 # which we need to skip when constructing the details for the kernel, so 262 # add one, giving a net subtract one. 263 diff = 1 if self.model_info.operation == '+' else 2 264 index = slice(par_index - diff, par_index - diff + info.parameters.npars) 189 265 length = full.length[index] 190 266 offset = full.offset[index] … … 196 272 def _part_values(self, info, par_index, mag_index): 197 273 # type: (ModelInfo, int, int) -> np.ndarray 198 #print(info.name, par_index, self.values[par_index:par_index + info.parameters.npars + 1]) 199 scale = self.values[par_index] 200 pars = self.values[par_index + 1:par_index + info.parameters.npars + 1] 274 # Set each constituent model's scale to 1 if this is a multiplication model 275 scale = self.values[par_index] if self.model_info.operation == '+' else 1.0 276 diff = 1 if self.model_info.operation == '+' else 0 # Skip scale if addition model 277 pars = self.values[par_index + diff:par_index + info.parameters.npars + diff] 201 278 nmagnetic = len(info.parameters.magnetism_index) 202 279 if nmagnetic: -
sasmodels/model_test.py
rbedb9b0 r65314f7 201 201 ({}, 'VR', None), 202 202 ] 203 204 tests = smoke_tests + self.info.tests 203 tests = smoke_tests 204 if self.info.tests is not None: 205 tests += self.info.tests 205 206 try: 206 207 model = build_model(self.info, dtype=self.dtype, … … 371 372 stream.writeln(traceback.format_exc()) 372 373 return 373 374 374 # Run the test suite 375 375 suite.run(result) -
sasmodels/modelinfo.py
r0bdddc2 r65314f7 727 727 models when the model is first called, not when the model is loaded. 728 728 """ 729 if hasattr(kernel_module, "model_info"): 730 # Custom sum/multi models 731 return kernel_module.model_info 729 732 info = ModelInfo() 730 733 #print("make parameter table", kernel_module.parameters) -
sasmodels/models/binary_hard_sphere.py
r8f04da4 r30b60d2 23 23 :nowrap: 24 24 25 \begin{align }25 \begin{align*} 26 26 x &= \frac{(\phi_2 / \phi)\alpha^3}{(1-(\phi_2/\phi) + (\phi_2/\phi) 27 27 \alpha^3)} \\ 28 28 \phi &= \phi_1 + \phi_2 = \text{total volume fraction} \\ 29 29 \alpha &= R_1/R_2 = \text{size ratio} 30 \end{align }30 \end{align*} 31 31 32 32 The 2D scattering intensity is the same as 1D, regardless of the orientation of -
sasmodels/models/core_shell_bicelle.py
ra151caa r30b60d2 41 41 42 42 I(Q,\alpha) = \frac{\text{scale}}{V_t} \cdot 43 F(Q,\alpha)^2 .sin(\alpha) + \text{background}43 F(Q,\alpha)^2 \cdot sin(\alpha) + \text{background} 44 44 45 45 where 46 46 47 47 .. math:: 48 :nowrap: 48 49 49 \begin{align }50 \begin{align*} 50 51 F(Q,\alpha) = &\bigg[ 51 52 (\rho_c - \rho_f) V_c \frac{2J_1(QRsin \alpha)}{QRsin\alpha}\frac{sin(QLcos\alpha/2)}{Q(L/2)cos\alpha} \\ … … 53 54 &+(\rho_r - \rho_s) V_t \frac{2J_1(Q(R+t_r)sin\alpha)}{Q(R+t_r)sin\alpha}\frac{sin(Q(L/2+t_f)cos\alpha)}{Q(L/2+t_f)cos\alpha} 54 55 \bigg] 55 \end{align }56 \end{align*} 56 57 57 58 where $V_t$ is the total volume of the bicelle, $V_c$ the volume of the core, -
sasmodels/models/core_shell_bicelle_elliptical.py
r8f04da4 r30b60d2 42 42 43 43 I(Q,\alpha,\psi) = \frac{\text{scale}}{V_t} \cdot 44 F(Q,\alpha, \psi)^2 .sin(\alpha) + \text{background}44 F(Q,\alpha, \psi)^2 \cdot sin(\alpha) + \text{background} 45 45 46 where a numerical integration of $F(Q,\alpha, \psi)^2 .sin(\alpha)$ is carried out over \alpha and \psi for:46 where a numerical integration of $F(Q,\alpha, \psi)^2 \cdot sin(\alpha)$ is carried out over \alpha and \psi for: 47 47 48 48 .. math:: 49 :nowrap: 49 50 50 \begin{align}51 \begin{align*} 51 52 F(Q,\alpha,\psi) = &\bigg[ 52 53 (\rho_c - \rho_f) V_c \frac{2J_1(QR'sin \alpha)}{QR'sin\alpha}\frac{sin(QLcos\alpha/2)}{Q(L/2)cos\alpha} \\ … … 54 55 &+(\rho_r - \rho_s) V_t \frac{2J_1(Q(R'+t_r)sin\alpha)}{Q(R'+t_r)sin\alpha}\frac{sin(Q(L/2+t_f)cos\alpha)}{Q(L/2+t_f)cos\alpha} 55 56 \bigg] 56 \end{align }57 \end{align*} 57 58 58 59 where -
sasmodels/models/core_shell_ellipsoid.py
r9f6823b r30b60d2 44 44 45 45 .. math:: 46 \begin{align} 46 :nowrap: 47 48 \begin{align*} 47 49 F(q,\alpha) = &f(q,radius\_equat\_core,radius\_equat\_core.x\_core,\alpha) \\ 48 50 &+ f(q,radius\_equat\_core + thick\_shell,radius\_equat\_core.x\_core + thick\_shell.x\_polar\_shell,\alpha) 49 \end{align }51 \end{align*} 50 52 51 53 where -
sasmodels/models/fractal_core_shell.py
r8f04da4 r8f04da4 31 31 $\rho_{solv}$ are the scattering length densities of the core, shell, and 32 32 solvent respectively, $r_c$ and $r_s$ are the radius of the core and the radius 33 of the whole particle respectively, $D_f$ is the fractal dimension, and |xi|the33 of the whole particle respectively, $D_f$ is the fractal dimension, and $\xi$ the 34 34 correlation length. 35 35 -
sasmodels/models/hollow_rectangular_prism.py
r8f04da4 r30b60d2 31 31 :nowrap: 32 32 33 \begin{align }33 \begin{align*} 34 34 A_{P\Delta}(q) & = A B C 35 35 \left[\frac{\sin \bigl( q \frac{C}{2} \cos\theta \bigr)} … … 47 47 \left[ \frac{\sin \bigl[ q \bigl(\frac{B}{2}-\Delta\bigr) \sin\theta \cos\phi \bigr]} 48 48 {q \bigl(\frac{B}{2}-\Delta\bigr) \sin\theta \cos\phi} \right] 49 \end{align }49 \end{align*} 50 50 51 51 where $A$, $B$ and $C$ are the external sides of the parallelepiped fulfilling -
sasmodels/models/multilayer_vesicle.py
r870a2f4 r870a2f4 33 33 .. math:: 34 34 35 r_i &= r_c + (i-1)(t_s + t_w) &&\text{ solvent radius before shell } i \\36 R_i &= r_i + t_s &&\text{ shell radius for shell } i35 r_i &= r_c + (i-1)(t_s + t_w) \text{ solvent radius before shell } i \\ 36 R_i &= r_i + t_s \text{ shell radius for shell } i 37 37 38 38 $\phi$ is the volume fraction of particles, $V(r)$ is the volume of a sphere -
sasmodels/models/parallelepiped.py
r8f04da4 r30b60d2 20 20 Parallelepiped with the corresponding definition of sides. 21 21 22 .. note:: 23 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. 22 The three dimensions of the parallelepiped (strictly here a cuboid) may be 23 given in *any* size order. To avoid multiple fit solutions, especially 24 with Monte-Carlo fit methods, it may be advisable to restrict their ranges. 25 There may be a number of closely similar "best fits", so some trial and 26 error, or fixing of some dimensions at expected values, may help. 29 27 30 28 The 1D scattering intensity $I(q)$ is calculated as: -
sasmodels/models/rpa.py
r4f9e288 r30b60d2 30 30 These case numbers are different from those in the NIST SANS package! 31 31 32 The models are based on the papers by Akcasu et al. [#Akcasu]_and by33 Hammouda [#Hammouda]_assuming the polymer follows Gaussian statistics such32 The models are based on the papers by Akcasu *et al.* and by 33 Hammouda assuming the polymer follows Gaussian statistics such 34 34 that $R_g^2 = n b^2/6$ where $b$ is the statistical segment length and $n$ is 35 35 the number of statistical segment lengths. A nice tutorial on how these are 36 36 constructed and implemented can be found in chapters 28 and 39 of Boualem 37 Hammouda's 'SANS Toolbox' [#toolbox]_.37 Hammouda's 'SANS Toolbox'. 38 38 39 39 In brief the macroscopic cross sections are derived from the general forms … … 49 49 are calculated with respect to component D).** So the scattering contrast 50 50 for a C/D blend = [SLD(component C) - SLD(component D)]\ :sup:`2`. 51 * Depending on which case is being used, the number of fitting parameters can 51 * Depending on which case is being used, the number of fitting parameters can 52 52 vary. 53 53 … … 57 57 component are obtained from other methods and held fixed while The *scale* 58 58 parameter should be held equal to unity. 59 * The variables are normally the segment lengths (b\ :sub:`a`, b\ :sub:`b`, 60 etc) and $\chi$ parameters (K\ :sub:`ab`, K\ :sub:`ac`, etc). 61 59 * The variables are normally the segment lengths ($b_a$, $b_b$, 60 etc.) and $\chi$ parameters ($K_{ab}$, $K_{ac}$, etc). 62 61 63 62 References 64 63 ---------- 65 64 66 .. [#Akcasu] A Z Akcasu, R Klein and B Hammouda, *Macromolecules*, 26 (1993) 67 4136. 68 .. [#Hammouda] B. Hammouda, *Advances in Polymer Science* 106 (1993) 87. 69 .. [#toolbox] https://www.ncnr.nist.gov/staff/hammouda/the_sans_toolbox.pdf 65 A Z Akcasu, R Klein and B Hammouda, *Macromolecules*, 26 (1993) 4136. 66 67 B. Hammouda, *Advances in Polymer Science* 106 (1993) 87. 68 69 B. Hammouda, *SANS Toolbox* 70 https://www.ncnr.nist.gov/staff/hammouda/the_sans_toolbox.pdf. 70 71 71 72 Authorship and Verification -
sasmodels/models/spherical_sld.py
r63a7fe8 r2ad5d30 18 18 Interface shapes are as follows:: 19 19 20 0: erf( |nu|*z)21 1: Rpow( z^|nu|)22 2: Lpow( z^|nu|)23 3: Rexp( -|nu|z)24 4: Lexp( -|nu|z)20 0: erf($\nu z$) 21 1: Rpow($z^\nu$) 22 2: Lpow($z^\nu$) 23 3: Rexp($-\nu z$) 24 4: Lexp($-\nu z$) 25 25 26 26 Definition -
sasmodels/models/star_polymer.py
r5da1ac8 r5da1ac8 7 7 emanating from a common central (in the case of this model) point. It is 8 8 derived as a special case of on the Benoit model for general branched 9 polymers\ [#CITBenoit]_ as also used by Richter ''et. al.''\ [#CITRichter]_9 polymers\ [#CITBenoit]_ as also used by Richter *et al.*\ [#CITRichter]_ 10 10 11 11 For a star with $f$ arms the scattering intensity $I(q)$ is calculated as -
sasmodels/models/surface_fractal.py
r48462b0 r30b60d2 9 9 10 10 .. math:: 11 :nowrap: 11 12 13 \begin{align*} 12 14 I(q) &= \text{scale} \times P(q)S(q) + \text{background} \\ 13 15 P(q) &= F(qR)^2 \\ … … 15 17 S(q) &= \Gamma(5-D_S)\xi^{\,5-D_S}\left[1+(q\xi)^2 \right]^{-(5-D_S)/2} 16 18 \sin\left[-(5-D_S) \tan^{-1}(q\xi) \right] q^{-1} \\ 17 \text{scale} &= \text{scale _factor}\, N V^2(\rho_\text{particle} - \rho_\text{solvent})^2 \\19 \text{scale} &= \text{scale factor}\, N V^1(\rho_\text{particle} - \rho_\text{solvent})^2 \\ 18 20 V &= \frac{4}{3}\pi R^3 21 \end{align*} 19 22 20 23 where $R$ is the radius of the building block, $D_S$ is the **surface** fractal -
sasmodels/product.py
r8f04da4 r765eb0e 68 68 translate_name = dict((old.id, new.id) for old, new 69 69 in zip(s_pars.kernel_parameters[1:], s_list)) 70 demo = {}71 demo.update(p_info.demo.items())72 demo.update((translate_name[k], v) for k, v in s_info.demo.items()73 if k not in ("background", "scale") and not k.startswith(ER_ID))74 70 combined_pars = p_pars.kernel_parameters + s_list 75 71 parameters = ParameterTable(combined_pars) 76 72 parameters.max_pd = p_pars.max_pd + s_pars.max_pd 73 def random(): 74 combined_pars = p_info.random() 75 s_names = set(par.id for par in s_pars.kernel_parameters[1:]) 76 s = s_info.random() 77 combined_pars.update((translate_name[k], v) 78 for k, v in s_info.random().items() 79 if k in s_names) 80 return combined_pars 77 81 78 82 model_info = ModelInfo() 79 model_info.id = ' *'.join((p_id, s_id))80 model_info.name = ' *'.join((p_name, s_name))83 model_info.id = '@'.join((p_id, s_id)) 84 model_info.name = '@'.join((p_name, s_name)) 81 85 model_info.filename = None 82 86 model_info.title = 'Product of %s and %s'%(p_name, s_name) … … 85 89 model_info.category = "custom" 86 90 model_info.parameters = parameters 91 model_info.random = random 87 92 #model_info.single = p_info.single and s_info.single 88 93 model_info.structure_factor = False … … 95 100 # TODO: delegate random to p_info, s_info 96 101 #model_info.random = lambda: {} 97 model_info.demo = demo 98 99 ## Show the parameter table with the demo values 102 103 ## Show the parameter table 100 104 #from .compare import get_pars, parlist 101 105 #print("==== %s ====="%model_info.name) 102 #values = get_pars(model_info , use_demo=True)106 #values = get_pars(model_info) 103 107 #print(parlist(model_info, values, is2d=True)) 104 108 return model_info … … 126 130 self.P = P 127 131 self.S = S 132 self.dtype = P.dtype 128 133 129 134 def make_kernel(self, q_vectors): -
sasmodels/sasview_model.py
r724257c rbcdd6c9 120 120 else: 121 121 model_info = modelinfo.make_model_info(kernel_module) 122 model = _make_model_from_info(model_info)122 model = make_model_from_info(model_info) 123 123 model.timestamp = getmtime(path) 124 124 … … 142 142 143 143 144 def make_model_from_info(model_info): 145 # type: (ModelInfo) -> SasviewModelType 146 """ 147 Convert *model_info* into a SasView model wrapper. 148 """ 149 def __init__(self, multiplicity=None): 150 SasviewModel.__init__(self, multiplicity=multiplicity) 151 attrs = _generate_model_attributes(model_info) 152 attrs['__init__'] = __init__ 153 attrs['filename'] = model_info.filename 154 ConstructedModel = type(model_info.name, (SasviewModel,), attrs) # type: SasviewModelType 155 return ConstructedModel 156 157 144 158 def _make_standard_model(name): 145 159 # type: (str) -> SasviewModelType … … 153 167 kernel_module = generate.load_kernel_module(name) 154 168 model_info = modelinfo.make_model_info(kernel_module) 155 return _make_model_from_info(model_info)156 157 169 return make_model_from_info(model_info) 170 171 158 172 def _register_old_models(): 159 173 # type: () -> None … … 187 201 model_info = product.make_product_info(form_factor._model_info, 188 202 structure_factor._model_info) 189 ConstructedModel = _make_model_from_info(model_info)203 ConstructedModel = make_model_from_info(model_info) 190 204 return ConstructedModel() 191 205 192 def _make_model_from_info(model_info):193 # type: (ModelInfo) -> SasviewModelType194 """195 Convert *model_info* into a SasView model wrapper.196 """197 def __init__(self, multiplicity=None):198 SasviewModel.__init__(self, multiplicity=multiplicity)199 attrs = _generate_model_attributes(model_info)200 attrs['__init__'] = __init__201 attrs['filename'] = model_info.filename202 ConstructedModel = type(model_info.name, (SasviewModel,), attrs) # type: SasviewModelType203 return ConstructedModel204 206 205 207 def _generate_model_attributes(model_info): … … 603 605 if hasattr(self._model_info, "composition") \ 604 606 and self._model_info.composition is not None: 605 p_model = _make_model_from_info(self._model_info.composition[1][0])()606 s_model = _make_model_from_info(self._model_info.composition[1][1])()607 p_model = make_model_from_info(self._model_info.composition[1][0])() 608 s_model = make_model_from_info(self._model_info.composition[1][1])() 607 609 return p_model, s_model 608 610
Note: See TracChangeset
for help on using the changeset viewer.