Index: .gitignore
===================================================================
--- .gitignore	(revision 2a55a6f2f24f911b7394865b206431a89f96ead0)
+++ .gitignore	(revision 8ae853293022b5081a1e1a8c26f74eaa2b3f8a13)
@@ -11,5 +11,5 @@
 /doc/api/
 /doc/model/
-/doc/ref/models
+/doc/guide/models
 .mplconfig
 /pylint_violations.txt
Index: doc/conf.py
===================================================================
--- doc/conf.py	(revision 40a87fa5096610e24c3ead10299f609e99f093f2)
+++ doc/conf.py	(revision 8ae853293022b5081a1e1a8c26f74eaa2b3f8a13)
@@ -42,4 +42,7 @@
              ]
 
+# Redirect mathjax to a different CDN
+mathjax_path = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML"
+
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
Index: doc/developer/calculator.rst
===================================================================
--- doc/developer/calculator.rst	(revision e822c97dbba0cc80549b06c762412cd27ba38358)
+++ doc/developer/calculator.rst	(revision 2e66ef55022b7fe939fdb5874c2c919d97e01b2c)
@@ -7,7 +7,7 @@
 model calculator which implements the polydispersity and magnetic SLD
 calculations.  There are three separate implementations of this layer,
-*kernelcl.py* for OpenCL, which operates on a single Q value at a time,
-*kerneldll.c* for the DLL, which loops over a vector of Q values, and
-*kernelpy.py* for python models which operates on vector Q values.
+:mod:`kernelcl` for OpenCL, which operates on a single Q value at a time,
+:mod:`kerneldll` for the DLL, which loops over a vector of Q values, and
+:mod:`kernelpy` for python models which operates on vector Q values.
 
 Each implementation provides three different calls *Iq*, *Iqxy* and *Imagnetic*
Index: doc/developer/index.rst
===================================================================
--- doc/developer/index.rst	(revision b85be2da3b04a7ce8ef87e2a85a44572b2b1480c)
+++ doc/developer/index.rst	(revision 2e66ef55022b7fe939fdb5874c2c919d97e01b2c)
@@ -7,3 +7,4 @@
    :maxdepth: 4
 
+   overview.rst
    calculator.rst
Index: doc/developer/overview.rst
===================================================================
--- doc/developer/overview.rst	(revision 2e66ef55022b7fe939fdb5874c2c919d97e01b2c)
+++ doc/developer/overview.rst	(revision 2e66ef55022b7fe939fdb5874c2c919d97e01b2c)
@@ -0,0 +1,81 @@
+.. py:currentmodule:: sasmodels
+
+***************************
+Code Overview
+***************************
+
+Computational kernels
+---------------------
+
+At the heart of *sasmodels* are the individual computational kernels.  These
+functions take a particular $q$ value and a set of parameter values and
+return the expected scattering for that $q$. The instructions for writing
+a kernel are documented in :ref:`Writing_a_Plugin`.  The source code for
+the kernels is stored in :mod:`sasmodels.models`.
+
+The primary interface to the models is through :mod:`sasmodels.core`, which
+provides functions for listing available models, loading the model definition
+and compiling the model.  Use :func:`sasmodels.core.load_model` to load in
+a model definition and compile it.
+
+The computational kernels are difficult to call directly, but an example
+was provided in :ref:`Scripting_Interface`.
+
+The code for loading the kernel is in
+:mod:`sasmodels.generate`, but a big part of it, which is interpreting the
+definition, lives in :mod:`sasmodels.modelinfo`.  This defines the properties
+of the model in :class:`sasmodels.modelinfo.ModelInfo`, the available
+model parameters in :class:`sasmodels.modelinfo.ParameterTable` and the
+individual parameter attributes such as units and hard limits in
+:class:`sasmodels.modelinfo.Parameter`.
+
+The kernel functions for the most part do not define polydispersity,
+resolution functions or magnetism.  Instead, code for these is generated in
+:mod:`sasmodels.generate`
+
+
+
+Sasview kernels:
+
+* :mod:`
+    ('kernel', 'Evaluator type definitions'),
+    ('kernelcl', 'OpenCL model evaluator'),
+    ('kerneldll', 'Ctypes model evaluator'),
+    ('kernelpy', 'Python model evaluator'),
+
+Bumps fitting routines:
+
+* :mod:`sasmodels.bumps_model` is a wrapper around
+    ('bumps_model', 'Bumps interface'),
+    ('direct_model', 'Simple interface'),
+
+
+Utility functions:
+
+* :mod:`sasmodels` provides :func:`sasmodels.__init__.data_files` for the installer.
+* :mod:`sasmodels.rst2html` provides tools for converting model docs to html and viewing
+  the html.  When run as a main program, it can display arbitrary rst files.
+* :mod:`sasmodels.exception` annotates the current exception with a context string,
+  such as "while opening myfile.dat" without adjusting the traceback.
+
+
+And so on::
+
+
+    ('compare_many', 'Batch compare models on different compute engines'),
+    ('compare', 'Compare models on different compute engines'),
+    ('convert', 'Sasview to sasmodel converter'),
+    ('core', 'Model access'),
+    ('data', 'Data layout and plotting routines'),
+    ('details', 'Parameter packing for kernel calls'),
+    ('generate', 'Model parser'),
+    ('list_pars', 'Identify all parameters in all models'),
+    ('mixture', 'Mixture model evaluator'),
+    ('model_test', 'Unit test support'),
+    ('modelinfo', 'Parameter and model definitions'),
+    ('product', 'Product model evaluator'),
+    ('resolution', '1-D resolution functions'),
+    ('resolution2d', '2-D resolution functions'),
+    ('sasview_model', 'Sasview interface'),
+    ('sesans', 'SESANS calculation routines'),
+    ('weights', 'Distribution functions'),
Index: doc/genapi.py
===================================================================
--- doc/genapi.py	(revision a5b8477c53695e7df03ecec7346f0c1bd770d3f7)
+++ doc/genapi.py	(revision 2e66ef55022b7fe939fdb5874c2c919d97e01b2c)
@@ -2,5 +2,5 @@
 import os.path
 
-MODULE_TEMPLATE=""".. Autogenerated by genmods.py
+MODULE_TEMPLATE = """.. Autogenerated by genmods.py
 
 ******************************************************************************
@@ -19,5 +19,5 @@
 """
 
-INDEX_TEMPLATE=""".. Autogenerated by genmods.py
+INDEX_TEMPLATE = """.. Autogenerated by genmods.py
 
 .. _api-index:
@@ -46,17 +46,18 @@
         os.makedirs(dir)
 
-    for module,name in modules:
-        with open(os.path.join(dir,module+'.rst'), 'w') as f:
+    for module, name in modules:
+        with open(os.path.join(dir, module+'.rst'), 'w') as f:
             f.write(MODULE_TEMPLATE%locals())
 
-    rsts = "\n   ".join(module+'.rst' for module,name in modules)
-    with open(os.path.join(dir,'index.rst'),'w') as f:
+    rsts = "\n   ".join(module+'.rst' for module, name in modules)
+    with open(os.path.join(dir, 'index.rst'), 'w') as f:
         f.write(INDEX_TEMPLATE%locals())
 
 
-modules=[
-    #('__init__', 'Top level namespace'),
+modules = [
+    ('__init__', 'Sasmodels package'),
     #('alignment', 'GPU data alignment [unused]'),
     ('bumps_model', 'Bumps interface'),
+    ('compare_many', 'Batch compare models on different compute engines'),
     ('compare', 'Compare models on different compute engines'),
     ('convert', 'Sasview to sasmodel converter'),
@@ -66,5 +67,4 @@
     ('direct_model', 'Simple interface'),
     ('exception', 'Annotate exceptions'),
-    #('frozendict', 'Freeze a dictionary to make it immutable'),
     ('generate', 'Model parser'),
     ('kernel', 'Evaluator type definitions'),
@@ -79,10 +79,10 @@
     ('resolution', '1-D resolution functions'),
     ('resolution2d', '2-D resolution functions'),
+    ('rst2html', 'Convert doc strings the web pages'),
     ('sasview_model', 'Sasview interface'),
     ('sesans', 'SESANS calculation routines'),
-    #('transition', 'Model stepper for automatic model selection'),
     ('weights', 'Distribution functions'),
 ]
-package='sasmodels'
-package_name='Reference'
+package = 'sasmodels'
+package_name = 'Reference'
 genfiles(package, package_name, modules)
Index: doc/gentoc.py
===================================================================
--- doc/gentoc.py	(revision 40a87fa5096610e24c3ead10299f609e99f093f2)
+++ doc/gentoc.py	(revision 990d8dfe5ac399564bc0bb3b873c5a1b56d4e573)
@@ -16,5 +16,5 @@
     from sasmodels.modelinfo import ModelInfo
 
-TEMPLATE="""\
+TEMPLATE = """\
 ..
     Generated from doc/gentoc.py -- DO NOT EDIT --
@@ -30,5 +30,5 @@
 """
 
-MODEL_TOC_PATH = "ref/models"
+MODEL_TOC_PATH = "guide/models"
 
 def _make_category(category_name, label, title, parent=None):
@@ -65,15 +65,16 @@
         # assume model is in sasmodels/models/name.py, and ignore the full path
         model_name = basename(item)[:-3]
-        if model_name.startswith('_'): continue
+        if model_name.startswith('_'):
+            continue
         model_info = load_model_info(model_name)
         if model_info.category is None:
             print("Missing category for", item, file=sys.stderr)
         else:
-            category.setdefault(model_info.category,[]).append(model_name)
+            category.setdefault(model_info.category, []).append(model_name)
 
     # Check category names
-    for k,v in category.items():
+    for k, v in category.items():
         if len(v) == 1:
-            print("Category %s contains only %s"%(k,v[0]), file=sys.stderr)
+            print("Category %s contains only %s"%(k, v[0]), file=sys.stderr)
 
     # Generate category files for the table of contents.
@@ -86,16 +87,17 @@
     # alphabetical order before them.
 
-    if not exists(MODEL_TOC_PATH): mkdir(MODEL_TOC_PATH)
+    if not exists(MODEL_TOC_PATH):
+        mkdir(MODEL_TOC_PATH)
     model_toc = _make_category(
-        'index',  'Models', 'Model Functions')
+        'index', 'Models', 'Model Functions')
     #shape_toc = _make_category(
     #    'shape',  'Shapes', 'Shape Functions', model_toc)
     free_toc = _make_category(
-        'shape-independent',  'Shape-independent',
+        'shape-independent', 'Shape-independent',
         'Shape-Independent Functions')
     struct_toc = _make_category(
-        'structure-factor',  'Structure-factor', 'Structure Factors')
-    custom_toc = _make_category(
-        'custom-models',  'Custom-models', 'Custom Models')
+        'structure-factor', 'Structure-factor', 'Structure Factors')
+    #custom_toc = _make_category(
+    #    'custom-models', 'Custom-models', 'Custom Models')
 
     # remember to top level categories
@@ -105,16 +107,16 @@
         'shape-independent':free_toc,
         'structure-factor': struct_toc,
-        'custom': custom_toc,
+        #'custom': custom_toc,
         }
 
     # Process the model lists
-    for k,v in sorted(category.items()):
+    for k, v in sorted(category.items()):
         if ':' in k:
-            cat,subcat = k.split(':')
+            cat, subcat = k.split(':')
             _maybe_make_category(cat, v, cat_files, model_toc)
             cat_file = cat_files[cat]
-            label = "-".join((cat,subcat))
+            label = "-".join((cat, subcat))
             filename = label
-            title = subcat.capitalize()+" Functions"
+            title = subcat.capitalize() + " Functions"
             sub_toc = _make_category(filename, label, title, cat_file)
             for model in sorted(v):
@@ -130,9 +132,10 @@
     _add_subcategory('shape-independent', model_toc)
     _add_subcategory('structure-factor', model_toc)
-    _add_subcategory('custom-models', model_toc)
+    #_add_subcategory('custom-models', model_toc)
 
     # Close the top-level category files
     #model_toc.close()
-    for f in cat_files.values(): f.close()
+    for f in cat_files.values():
+        f.close()
 
 
Index: doc/guide/gpu/gpu_computations.rst
===================================================================
--- doc/guide/gpu/gpu_computations.rst	(revision 8ae853293022b5081a1e1a8c26f74eaa2b3f8a13)
+++ doc/guide/gpu/gpu_computations.rst	(revision 8ae853293022b5081a1e1a8c26f74eaa2b3f8a13)
@@ -0,0 +1,73 @@
+.. _models-computation:
+
+****************
+GPU Computations
+****************
+sasmodels evaluations can run on your graphics card (GPU) or they can run
+on the processor (CPU). In general, calculations performed on the GPU will run faster.
+
+To run on the GPU, your computer must have OpenCL drivers installed.
+For information about OpenCL installation see this
+:ref:`opencl-installation` guidance.
+
+Where the model is evaluated is a little bit complicated.
+If the model has the line *single=False* then it requires double precision.
+If the GPU is single precision only, then it will try running via OpenCL
+on the CPU.  If the OpenCL driver is not available for the CPU then
+it will run as a normal program on the CPU.
+
+For models with a large number of parameters or with a lot of code,
+the GPU may be too small to run the program effectively.
+In this case, you should try simplifying the model, maybe breaking it
+into several different modules so that you don't need *IF* statements in your code.
+If it is still too big, you can set *opencl=False* in the model file and
+the model will only run as a normal program on the CPU.
+This will not usually be necessary.
+
+Device Selection
+................
+If you have multiple GPU devices you can tell SasView which device to use.
+By default, SasView looks for one GPU and one CPU device
+from available OpenCL platforms.
+
+OpenCL devices can be set from OpenCL options dialog in Fitting menu or as
+enviromental variables.
+
+**If you don't want to use OpenCL, you can select "No OpenCL" option from**
+**GUI dialog or set *SAS_OPENCL=None* in your environment settings**
+**This will only use normal programs.**
+
+SasView prefers AMD or NVIDIA drivers for GPU, and prefers Intel or
+Apple drivers for CPU. Both GPU and CPU are included on the assumption that CPU
+is always available and supports double precision.
+
+The device order is important: GPU is checked before CPU on the assumption that
+it will be faster. By examining ~/sasview.log you can see which device SasView
+chose to run the model.
+
+If you want to use one of the other devices, you can select it from OpenCL
+options dialog (accessible from Fitting menu) or run the following from
+the python console in SasView::
+
+    import pyopencl as cl
+    cl.create_some_context()
+
+This will provide a menu of different OpenCL drivers available.
+When one is selected, it will say "set PYOPENCL_CTX=..."
+Use that value as the value of *SAS_OPENCL*.
+
+Compiler Selection
+..................
+For models run as normal programs, you may need to specify a compiler.
+This is done using the SAS_COMPILER environment variable.
+Set it to *tinycc* for the tinycc compiler, *msvc* for the
+Microsoft Visual C compiler, or *mingw* for the MinGW compiler.
+TinyCC is provided with SasView so that is the default.
+If you want one of the other compilers, be sure to have it available
+in your *PATH* so SasView can find it!
+
+
+*Document History*
+
+| 2016-10-08 Steve King
+| 2017-05-07 Paul Kienzle
Index: doc/guide/gpu/opencl_installation.rst
===================================================================
--- doc/guide/gpu/opencl_installation.rst	(revision 990d8dfe5ac399564bc0bb3b873c5a1b56d4e573)
+++ doc/guide/gpu/opencl_installation.rst	(revision 990d8dfe5ac399564bc0bb3b873c5a1b56d4e573)
@@ -0,0 +1,70 @@
+.. _opencl-installation:
+
+*******************
+OpenCL Installation
+*******************
+*Warning! GPU devices do not in general offer the same level of memory
+protection as CPU devices. If your code attempts to write outside allocated
+memory buffers unpredicatable behaviour may result (eg, your video display
+may freeze, or your system may crash, etc). Do not install OpenCL drivers
+ithout first checking for known issues (eg, some computer manufacturers
+install modified graphics drivers so replacing these may not be a good
+idea!). If in doubt, seek advice from an IT professional before proceeding
+further.*
+
+1. Check if you have OpenCL already installed
+=============================================
+
+Windows
+.......
+    The following instructions are based on
+    http://web.engr.oregonstate.edu/~mjb/cs475/DoIHaveOpenCL.pdf
+
+    * Go to: Start -> Control Panel -> System & Security -> Administrative Tools
+    * Double Click on Computer Managment
+    * Click on Device Manager
+    * Click open Display Adapters
+    * Right-click on available adapter and select Properties
+    * Click on Driver
+    * Go to Driver Details
+    * Scroll down and see if OpenCL is installed (look for OpenCL*.dll files)
+
+Mac OSX
+.......
+    For OS X operating systems higher than 10.6 OpenCL is shipped along with
+    the system.
+
+    However, OpenCL has had a rocky history on Macs. Apple provide a useful
+    compatibility table at https://support.apple.com/en-us/HT202823
+
+
+2. Installation
+===============
+
+Windows
+.......
+    Depending on the graphic card in your system, drivers
+    can be obtained from different sources:
+
+    * NVIDIA: https://developer.nvidia.com/opencl
+    * AMD: http://developer.amd.com/tools-and-sdks/opencl-zone/
+
+Mac OSX
+.......
+    N/A
+
+ You cannot download OpenCL driver updates for your Mac. They are packaged
+ with the normal quarterly OS X updates from Apple.
+
+
+.. note::
+    Intel provides OpenCL drivers for Intel processors at
+    https://software.intel.com/en-us/articles/opencl-drivers
+    These can sometimes make use of special vector instructions across multiple
+    processors, so it is worth installing if the GPU does not support double
+    precision. You can install this driver alongside the GPU driver for NVIDIA
+    or AMD.
+
+
+.. note::
+    This help document was last changed by Steve King, 08Oct2016
Index: doc/guide/index.rst
===================================================================
--- doc/guide/index.rst	(revision bb6f0f3f04f718187ac81a56563b8bb7a1d216af)
+++ doc/guide/index.rst	(revision 2e66ef55022b7fe939fdb5874c2c919d97e01b2c)
@@ -1,38 +1,18 @@
-**********
-SAS Models
-**********
+****************
+SAS Models Guide
+****************
 
-Small angle X-ray and Neutron (SAXS and SANS) scattering examines the
-scattering patterns produced by a beam travelling through the sample
-and scattering at low angles.  The scattering is computed as a function
-of $q_x$ and $q_y$, which for a given beam wavelength corresponds to
-particular scattering angles. Each pixel on the detector corresponds to
-a different scattering angle. If the sample is unoriented, the scattering
-pattern will appear as rings on the detector.  In this case, a circular
-average can be taken with 1-dimension data at $q = \surd (q_x^2 + q_y^2)$
-compared to the orientationally averaged SAS scattering pattern.
+.. toctree::
+   :numbered: 4
+   :maxdepth: 4
 
-Models have certain features in common.
-
-Every model has a *scale* and a *background*.
-
-Talk about orientation, with diagrams for orientation so that we don't need
-a link on every model page?
-
-.. _orientation:
-
-.. figure: img/orientation1.jpg
-
-    Orientation in 3D
-
-.. figure: img/orientation2.jpg
-
-    Orientation cross sections
-
-Talk about polydispersity.
-
-Talk about magnetism, converting the magnetism help file to inline text here,
-with links so that models can point back to it.
-
-Need to talk about structure factors even though we don't have any
-implemented yet.
+   intro.rst
+   install.rst
+   pd/polydispersity.rst
+   resolution.rst
+   magnetism/magnetism.rst
+   sesans/sans_to_sesans.rst
+   sesans/sesans_fitting.rst
+   plugin.rst
+   scripting.rst
+   refs.rst
Index: doc/guide/install.rst
===================================================================
--- doc/guide/install.rst	(revision 990d8dfe5ac399564bc0bb3b873c5a1b56d4e573)
+++ doc/guide/install.rst	(revision 990d8dfe5ac399564bc0bb3b873c5a1b56d4e573)
@@ -0,0 +1,186 @@
+********************
+sasmodels Setup
+********************
+
+
+sasmodels Installation
+**********************
+Sasmodels can be installed using a simple pip installation::
+
+    # Won't work yet! For now follow the developer instructions below.
+    $ pip install sasmodels
+
+There are a number of dependent python packages which need to be installed
+separately::
+
+    numpy
+    scipy
+    opencl (for speed if your system has OpenCL drivers)
+    tinycc (windows only, if no C compiler and no OpenCL)
+
+When using sasmodels to fit data::
+
+    sasview (for loading data)
+    bumps (for fitting)
+    matplotlib (for displaying results)
+
+For development and testing it is handy to have some additional packages::
+
+    nose (for testing)
+    xmlrunner (for testing)
+    matplotlib (for showing models)
+    docutils (for showing model docs)
+    sphinx (for building docs)
+    wx ([optional] for adjusting parameters interactively)
+
+**Developer Installation**
+
+Developers will need to clone the sasmodels reposistory from github::
+
+    $ git clone https://github.com/sasview/sasmodels.git
+
+or if you have a github account::
+
+    $ git clone git@github.com:sasview/sasmodels.git
+
+Sasmodels can be run in-place by including the sasmodels directory on the
+python path.  There are numerous ways to do this which will not be outlined
+here.  It will be easiest to install the package in "develop" mode using::
+
+    $ cd sasmodels
+    $ python setup.py develop
+
+This will allow you to edit the files in the package and have the changes
+show up immediately in python the next time you load your program.
+
+OpenCL Installation
+*******************
+*Warning! GPU devices do not in general offer the same level of memory
+protection as CPU devices. If your code attempts to write outside allocated
+memory buffers unpredicatable behaviour may result (eg, your video display
+may freeze, or your system may crash, etc). Do not install OpenCL drivers
+ithout first checking for known issues (eg, some computer manufacturers
+install modified graphics drivers so replacing these may not be a good
+idea!). If in doubt, seek advice from an IT professional before proceeding
+further.*
+
+Check if you have OpenCL already installed
+==========================================
+
+**Windows**
+
+The following instructions are based on
+http://web.engr.oregonstate.edu/~mjb/cs475/DoIHaveOpenCL.pdf
+
+* Go to: Start -> Control Panel -> System & Security -> Administrative Tools
+* Double Click on Computer Managment
+* Click on Device Manager
+* Click open Display Adapters
+* Right-click on available adapter and select Properties
+* Click on Driver
+* Go to Driver Details
+* Scroll down and see if OpenCL is installed (look for OpenCL*.dll files)
+
+**Mac OSX**
+
+For OS X operating systems higher than 10.6 OpenCL is shipped along with
+the system.
+
+However, OpenCL has had a rocky history on Macs. Apple provide a useful
+compatibility table at https://support.apple.com/en-us/HT202823
+
+
+Installation
+============
+
+**Windows**
+
+Depending on the graphic card in your system, drivers
+can be obtained from different sources:
+
+* NVIDIA: https://developer.nvidia.com/opencl
+* AMD: http://developer.amd.com/tools-and-sdks/opencl-zone/
+
+
+**Mac OSX**
+
+N/A
+
+You cannot download OpenCL driver updates for your Mac. They are packaged
+with the normal quarterly OS X updates from Apple.
+
+
+.. note::
+    Intel provides OpenCL drivers for Intel processors at
+    https://software.intel.com/en-us/articles/opencl-drivers
+    These can sometimes make use of special vector instructions across multiple
+    processors, so it is worth installing if the GPU does not support double
+    precision. You can install this driver alongside the GPU driver for NVIDIA
+    or AMD.
+
+
+GPU Selection
+*************
+
+sasmodels evaluations can run on your graphics card (GPU) or they can run
+on the processor (CPU). In general, calculations performed on the GPU will run faster.
+
+To run on the GPU, your computer must have OpenCL drivers installed.
+For information about OpenCL installation see this
+:ref:`opencl-installation` guidance.
+
+Where the model is evaluated is a little bit complicated.
+If the model has the line *single=False* then it requires double precision.
+If the GPU is single precision only, then it will try running via OpenCL
+on the CPU.  If the OpenCL driver is not available for the CPU then
+it will run as a normal program on the CPU.
+
+For models with a large number of parameters or with a lot of code,
+the GPU may be too small to run the program effectively.
+In this case, you should try simplifying the model, maybe breaking it
+into several different modules so that you don't need *IF* statements in your code.
+If it is still too big, you can set *opencl=False* in the model file and
+the model will only run as a normal program on the CPU.
+This will not usually be necessary.
+
+Device Selection
+================
+If you have multiple GPU devices you can tell SasView which device to use.
+By default, SasView looks for one GPU and one CPU device
+from available OpenCL platforms.
+
+SasView prefers AMD or NVIDIA drivers for GPU, and prefers Intel or
+Apple drivers for CPU. Both GPU and CPU are included on the assumption that CPU
+is always available and supports double precision.
+
+The device order is important: GPU is checked before CPU on the assumption that
+it will be faster. By examining ~/sasview.log you can see which device SasView
+chose to run the model.
+
+**If you don't want to use OpenCL, you can set** *SAS_OPENCL=None*
+**in your environment settings, and it will only use normal programs.**
+
+If you want to use one of the other devices, you can run the following
+from the python console in SasView::
+
+    import pyopencl as cl
+    cl.create_some_context()
+
+This will provide a menu of different OpenCL drivers available.
+When one is selected, it will say "set PYOPENCL_CTX=..."
+Use that value as the value of *SAS_OPENCL*.
+
+Compiler Selection
+==================
+For models run as normal programs, you may need to specify a compiler.
+This is done using the SAS_COMPILER environment variable.
+Set it to *tinycc* for the tinycc compiler, *msvc* for the
+Microsoft Visual C compiler, or *mingw* for the MinGW compiler.
+TinyCC is provided with SasView so that is the default.
+If you want one of the other compilers, be sure to have it available
+in your *PATH* so SasView can find it!
+
+
+*Document History*
+
+| 2017-05-17 Paul Kienzle
Index: doc/guide/intro.rst
===================================================================
--- doc/guide/intro.rst	(revision 8ae853293022b5081a1e1a8c26f74eaa2b3f8a13)
+++ doc/guide/intro.rst	(revision 8ae853293022b5081a1e1a8c26f74eaa2b3f8a13)
@@ -0,0 +1,59 @@
+
+.. _models-intro:
+
+************
+Introduction
+************
+
+This software provides form factors for various particle shapes and computes
+resolution, polydispersity and angular dispersion. After giving a mathematical
+definition of each model, we show the list of parameters available to the user.
+Validation plots for each model are also presented.
+
+To easily compare to the scattering intensity measured in experiments, we
+normalize the form factors by the volume of the particle
+
+.. math::
+
+    P(\vec q) = \frac{P_o(\vec q)}{V} = \frac{1}{V} F(\vec q) F^*(\vec q)
+
+with
+
+.. math::
+
+    F(\vec q) = \int\int\int dV\rho(\vec r) e^{-i\vec q \cdot \vec r}
+
+where $P_0(\vec q)$ is the un-normalized form factor, $\rho(\vec r)$ is
+the scattering length density at a given point in space and the integration
+is done over the volume $V$ of the scatterer.
+
+For systems without inter-particle interference, the form factors we provide
+can be related to the scattering intensity by the particle volume fraction
+
+.. math::
+
+    I(\vec q) = \Phi P(\vec q)
+
+Our so-called 1D scattering intensity functions provide $P(Q)$ for the case
+where the scatterer is randomly oriented. In that case, the scattering
+intensity only depends on the length of $Q$ . The intensity measured on
+the plane of the SAS detector will have an azimuthal symmetry around $Q=0$.
+
+Our so-called 2D scattering intensity functions provide $P(Q,\phi)$ for an
+oriented system as a function of a $q$ vector in the plane of the detector.
+We define the angle $\phi$ as the angle between the $q$ vector and the
+horizontal ($x$) axis of the plane of the detector.
+
+For information about polarised and magnetic scattering, see :ref:`magnetism`.
+
+The models are used within the SasView package.  Instructions on how to
+use SasView itself are available separately.
+
+Many of our models use the form factor calculations as implemented in the
+C-library provided by the NIST Center for Neutron Research and thus some
+content and figures in this document are originated from or shared with
+the NIST SANS Igor-based analysis package.
+
+*Document History*
+
+| 2017-05-07 Paul Kienzle
Index: doc/guide/magnetism/magnetism.rst
===================================================================
--- doc/guide/magnetism/magnetism.rst	(revision 990d8dfe5ac399564bc0bb3b873c5a1b56d4e573)
+++ doc/guide/magnetism/magnetism.rst	(revision 990d8dfe5ac399564bc0bb3b873c5a1b56d4e573)
@@ -0,0 +1,94 @@
+.. _magnetism:
+
+Polarisation/Magnetic Scattering
+================================
+
+Models which define a scattering length density parameter can be evaluated
+ as magnetic models. In general, the scattering length density (SLD =
+ $\beta$) in each region where the SLD is uniform, is a combination of the
+ nuclear and magnetic SLDs and, for polarised neutrons, also depends on the
+ spin states of the neutrons.
+
+For magnetic scattering, only the magnetization component $\mathbf{M_\perp}$
+perpendicular to the scattering vector $\mathbf{Q}$ contributes to the magnetic
+scattering length.
+
+
+.. figure::
+    mag_img/mag_vector.bmp
+
+The magnetic scattering length density is then
+
+.. math::
+    \beta_M = \dfrac{\gamma r_0}{2\mu_B}\sigma \cdot
+    \mathbf{M_\perp} = D_M\sigma \cdot \mathbf{M_\perp}
+
+where $\gamma = -1.913$ is the gyromagnetic ratio, $\mu_B$ is the
+Bohr magneton, $r_0$ is the classical radius of electron, and $\sigma$
+is the Pauli spin.
+
+Assuming that incident neutrons are polarized parallel (+) and anti-parallel (-)
+to the $x'$ axis, the possible spin states after the sample are then
+
+No spin-flips (+ +) and (- -)
+
+Spin-flips    (+ -) and (- +)
+
+.. figure::
+    mag_img/M_angles_pic.bmp
+
+If the angles of the $Q$ vector and the spin-axis $x'$ to the $x$ - axis are
+$\phi$ and $\theta_{up}$, respectively, then, depending on the spin state of the
+neutrons, the scattering length densities, including the nuclear scattering
+length density ($\beta{_N}$) are
+
+.. math::
+    \beta_{\pm\pm} =  \beta_N \mp D_M M_{\perp x'}
+    \text{ when there are no spin-flips}
+
+and
+
+.. math::
+    \beta_{\pm\mp} =  -D_M (M_{\perp y'} \pm iM_{\perp z'})
+    \text{ when there are}
+
+where
+
+.. math::
+    M_{\perp x'} = M_{0q_x}\cos(\theta_{up})+M_{0q_y}\sin(\theta_{up}) \\
+    M_{\perp y'} = M_{0q_y}\cos(\theta_{up})-M_{0q_x}\sin(\theta_{up}) \\
+    M_{\perp z'} = M_{0z} \\
+    M_{0q_x} = (M_{0x}\cos\phi - M_{0y}\sin\phi)\cos\phi \\
+    M_{0q_y} = (M_{0y}\sin\phi - M_{0x}\cos\phi)\sin\phi
+
+Here, $M_{0x}$, $M_{0x}$, $M_{0z}$ are the x, y and z components
+of the magnetization vector given in the laboratory xyz frame given by
+
+.. math::
+    M_{0x} = M_0\cos\theta_M\cos\phi_M \\
+    M_{0y} = M_0\sin\theta_M \\
+    M_{0z} = -M_0\cos\theta_M\sin\phi_M
+
+and the magnetization angles $\theta_M$ and $\phi_M$ are defined in
+the figure above.
+
+The user input parameters are:
+
+===========   ================================================================
+ M0_sld        = $D_M M_0$
+ Up_theta      = $\theta_{up}$
+ M_theta       = $\theta_M$
+ M_phi         = $\phi_M$
+ Up_frac_i     = (spin up)/(spin up + spin down) neutrons *before* the sample
+ Up_frac_f     = (spin up)/(spin up + spin down) neutrons *after* the sample
+===========   ================================================================
+
+.. note::
+    The values of the 'Up_frac_i' and 'Up_frac_f' must be in the range 0 to 1.
+
+.. note::
+    This help document was last changed by Steve King, 02May2015
+
+* Document History *
+
+| 2017-05-08 Paul Kienzle
Index: doc/guide/pd/polydispersity.rst
===================================================================
--- doc/guide/pd/polydispersity.rst	(revision 990d8dfe5ac399564bc0bb3b873c5a1b56d4e573)
+++ doc/guide/pd/polydispersity.rst	(revision 990d8dfe5ac399564bc0bb3b873c5a1b56d4e573)
@@ -0,0 +1,224 @@
+.. pd_help.rst
+
+.. This is a port of the original SasView html help file to ReSTructured text
+.. by S King, ISIS, during SasView CodeCamp-III in Feb 2015.
+
+.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+
+Polydispersity Distributions
+----------------------------
+
+With some models in sasmodels we can calculate the average form factor for a
+population of particles that exhibit size and/or orientational
+polydispersity. The resultant form factor is normalized by the average
+particle volume such that
+
+.. math::
+
+  P(q) = \text{scale} \langle F^* F \rangle / V + \text{background}
+
+where $F$ is the scattering amplitude and $\langle\cdot\rangle$ denotes an
+average over the size distribution.
+
+Each distribution is characterized by its center $\bar x$, its width $\sigma$,
+the number of sigmas $N_\sigma$ to include from the tails, and the number of
+points used to compute the average. The center of the distribution is set by the
+value of the model parameter.  Volume parameters have polydispersity *PD*
+(not to be confused with a molecular weight distributions in polymer science)
+leading to a size distribution of width $\text{PD} = \sigma / \bar x$, but
+orientation parameters use an angular distributions of width $\sigma$.
+$N_\sigma$ determines how far into the tails to evaluate the distribution, with
+larger values of $N_\sigma$ required for heavier tailed distributions.
+The scattering in general falls rapidly with $qr$ so the usual assumption
+that $G(r - 3\sigma_r)$ is tiny and therefore $f(r - 3\sigma_r)G(r - 3\sigma_r)$
+will not contribute much to the average may not hold when particles are large.
+This, too, will require increasing $N_\sigma$.
+
+Users should note that the averaging computation is very intensive. Applying
+polydispersion to multiple parameters at the same time or increasing the
+number of points in the distribution will require patience! However, the
+calculations are generally more robust with more data points or more angles.
+
+The following five distribution functions are provided:
+
+*  *Rectangular Distribution*
+*  *Gaussian Distribution*
+*  *Lognormal Distribution*
+*  *Schulz Distribution*
+*  *Array Distribution*
+
+These are all implemented as *number-average* distributions.
+
+.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+
+Rectangular Distribution
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+The Rectangular Distribution is defined as
+
+.. math::
+
+    f(x) = \frac{1}{\text{Norm}}
+    \begin{cases}
+      1 & \text{for } |x - \bar x| \leq w \\
+      0 & \text{for } |x - \bar x| > w
+    \end{cases}
+
+where $\bar x$ is the mean of the distribution, $w$ is the half-width, and
+*Norm* is a normalization factor which is determined during the numerical
+calculation.
+
+Note that the standard deviation and the half width $w$ are different!
+
+The standard deviation is
+
+.. math:: \sigma = w / \sqrt{3}
+
+whilst the polydispersity is
+
+.. math:: \text{PD} = \sigma / \bar x
+
+.. figure:: pd_rectangular.jpg
+
+    Rectangular distribution.
+
+.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+
+Gaussian Distribution
+^^^^^^^^^^^^^^^^^^^^^
+
+The Gaussian Distribution is defined as
+
+.. math::
+
+    f(x) = \frac{1}{\text{Norm}}
+           \exp\left(-\frac{(x - \bar x)^2}{2\sigma^2}\right)
+
+where $\bar x$ is the mean of the distribution and *Norm* is a normalization factor
+which is determined during the numerical calculation.
+
+The polydispersity is
+
+.. math:: \text{PD} = \sigma / \bar x
+
+.. figure:: pd_gaussian.jpg
+
+    Normal distribution.
+
+.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+
+Lognormal Distribution
+^^^^^^^^^^^^^^^^^^^^^^
+
+The Lognormal Distribution is defined as
+
+.. math::
+
+    f(x) = \frac{1}{\text{Norm}}
+           \frac{1}{xp}\exp\left(-\frac{(\ln(x) - \mu)^2}{2p^2}\right)
+
+where $\mu=\ln(x_\text{med})$ when $x_\text{med}$ is the median value of the
+distribution, and *Norm* is a normalization factor which will be determined
+during the numerical calculation.
+
+The median value for the distribution will be the value given for the respective
+size parameter, for example, *radius=60*.
+
+The polydispersity is given by $\sigma$
+
+.. math:: \text{PD} = p
+
+For the angular distribution
+
+.. math:: p = \sigma / x_\text{med}
+
+The mean value is given by $\bar x = \exp(\mu+ p^2/2)$. The peak value
+is given by $\max x = \exp(\mu - p^2)$.
+
+.. figure:: pd_lognormal.jpg
+
+    Lognormal distribution.
+
+This distribution function spreads more, and the peak shifts to the left, as
+$p$ increases, so it requires higher values of $N_\sigma$ and more points
+in the distribution.
+
+.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+
+Schulz Distribution
+^^^^^^^^^^^^^^^^^^^
+
+The Schulz distribution is defined as
+
+.. math::
+
+    f(x) = \frac{1}{\text{Norm}}
+           (z+1)^{z+1}(x/\bar x)^z\frac{\exp[-(z+1)x/\bar x]}{\bar x\Gamma(z+1)}
+
+where $\bar x$ is the mean of the distribution and *Norm* is a normalization
+factor which is determined during the numerical calculation, and $z$ is a
+measure of the width of the distribution such that
+
+.. math:: z = (1-p^2) / p^2
+
+The polydispersity is
+
+.. math:: p = \sigma / \bar x
+
+Note that larger values of PD might need larger number of points and $N_\sigma$.
+For example, at PD=0.7 and radius=60 |Ang|, Npts>=160 and Nsigmas>=15 at least.
+
+.. figure:: pd_schulz.jpg
+
+    Schulz distribution.
+
+For further information on the Schulz distribution see:
+M Kotlarchyk & S-H Chen, *J Chem Phys*, (1983), 79, 2461.
+
+.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+
+Array Distribution
+^^^^^^^^^^^^^^^^^^
+
+This user-definable distribution should be given as as a simple ASCII text
+file where the array is defined by two columns of numbers: $x$ and $f(x)$.
+The $f(x)$ will be normalized to 1 during the computation.
+
+Example of what an array distribution file should look like:
+
+====  =====
+ 30    0.1
+ 32    0.3
+ 35    0.4
+ 36    0.5
+ 37    0.6
+ 39    0.7
+ 41    0.9
+====  =====
+
+Only these array values are used computation, therefore the parameter value
+given for the model will have no affect, and will be ignored when computing
+the average.  This means that any parameter with an array distribution will
+not be fittable.
+
+.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+
+Note about DLS polydispersity
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Many commercial Dynamic Light Scattering (DLS) instruments produce a size
+polydispersity parameter, sometimes even given the symbol $p$! This
+parameter is defined as the relative standard deviation coefficient of
+variation of the size distribution and is NOT the same as the polydispersity
+parameters in the Lognormal and Schulz distributions above (though they all
+related) except when the DLS polydispersity parameter is <0.13.
+
+For more information see:
+S King, C Washington & R Heenan, *Phys Chem Chem Phys*, (2005), 7, 143
+
+.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+
+*Document History*
+
+| 2015-05-01 Steve King
+| 2017-05-08 Paul Kienzle
Index: doc/guide/plugin.rst
===================================================================
--- doc/guide/plugin.rst	(revision 990d8dfe5ac399564bc0bb3b873c5a1b56d4e573)
+++ doc/guide/plugin.rst	(revision 990d8dfe5ac399564bc0bb3b873c5a1b56d4e573)
@@ -0,0 +1,1018 @@
+.. _Writing_a_Plugin:
+
+Writing a Plugin Model
+======================
+
+Overview
+^^^^^^^^
+
+In addition to the models provided with the sasmodels package, you are free to
+create your own models.
+
+Models can be of three types:
+
+- A pure python model : Example -
+  `broadpeak.py <https://github.com/SasView/sasmodels/blob/master/sasmodels/models/broad_peak.py>`_
+
+- A python model with embedded C : Example -
+  `sphere.py <https://github.com/SasView/sasmodels/blob/master/sasmodels/models/sphere.py>`_
+
+- A python wrapper with separate C code : Example -
+  `cylinder.py <https://github.com/SasView/sasmodels/blob/master/sasmodels/models/cylinder.py>`_,
+  `cylinder.c <https://github.com/SasView/sasmodels/blob/master/sasmodels/models/cylinder.c>`_
+
+When using SasView, plugin models should be saved to the SasView
+*plugin_models* folder *C:\\Users\\{username}\\.sasview\\plugin_models*
+(on Windows) or */Users/{username}/.sasview\\plugin_models* (on Mac).
+The next time SasView is started it will compile the plugin and add
+it to the list of *Plugin Models* in a FitPage.  Scripts can load
+the models from anywhere.
+
+The built-in modules are available in the *models* subdirectory
+of the sasmodels package.  For SasView on Windows, these will
+be found in *C:\\Program Files (x86)\\SasView\\sasmodels-data\\models*.
+On Mac OSX, these will be within the application bundle as
+*/Applications/SasView 4.0.app/Contents/Resources/sasmodels-data/models*.
+
+Other models are available for download from the
+`Model Marketplace <http://marketplace.sasview.org/>`_. You can contribute your
+own models to the Marketplace as well.
+
+Create New Model Files
+^^^^^^^^^^^^^^^^^^^^^^
+
+Copy the appropriate files to your plugin models directory (we recommend
+using the examples above as templates) as mymodel.py (and mymodel.c, etc)
+as required, where "mymodel" is the name for the model you are creating.
+
+*Please follow these naming rules:*
+
+- No capitalization and thus no CamelCase
+- If necessary use underscore to separate words (i.e. barbell not BarBell or
+  broad_peak not BroadPeak)
+- Do not include "model" in the name (i.e. barbell not BarBellModel)
+
+
+Edit New Model Files
+^^^^^^^^^^^^^^^^^^^^
+
+Model Contents
+..............
+
+The model interface definition is in the .py file.  This file contains:
+
+- a **model name**:
+   - this is the **name** string in the *.py* file
+   - titles should be:
+
+    - all in *lower* case
+    - without spaces (use underscores to separate words instead)
+    - without any capitalization or CamelCase
+    - without incorporating the word "model"
+    - examples: *barbell* **not** *BarBell*; *broad_peak* **not** *BroadPeak*;
+      *barbell* **not** *BarBellModel*
+
+- a **model title**:
+   - this is the **title** string in the *.py* file
+   - this is a one or two line description of the model, which will appear
+     at the start of the model documentation and as a tooltip in the SasView GUI
+
+- a **short discription**:
+   - this is the **description** string in the *.py* file
+   - this is a medium length description which appears when you click
+     *Description* on the model FitPage
+
+- a **parameter table**:
+   - this will be auto-generated from the *parameters* in the *.py* file
+
+- a **long description**:
+   - this is ReStructuredText enclosed between the r""" and """ delimiters
+     at the top of the *.py* file
+   - what you write here is abstracted into the SasView help documentation
+   - this is what other users will refer to when they want to know what
+     your model does; so please be helpful!
+
+- a **definition** of the model:
+   - as part of the **long description**
+
+- a **formula** defining the function the model calculates:
+   - as part of the **long description**
+
+- an **explanation of the parameters**:
+   - as part of the **long description**
+   - explaining how the symbols in the formula map to the model parameters
+
+- a **plot** of the function, with a **figure caption**:
+   - this is automatically generated from your default parameters
+
+- at least one **reference**:
+   - as part of the **long description**
+   - specifying where the reader can obtain more information about the model
+
+- the **name of the author**
+   - as part of the **long description**
+   - the *.py* file should also contain a comment identifying *who*
+     converted/created the model file
+
+Models that do not conform to these requirements will *never* be incorporated
+into the built-in library.
+
+More complete documentation for the sasmodels package can be found at
+`<http://www.sasview.org/sasmodels>`_. In particular,
+`<http://www.sasview.org/sasmodels/api/generate.html#module-sasmodels.generate>`_
+describes the structure of a model.
+
+
+Model Documentation
+...................
+
+The *.py* file starts with an r (for raw) and three sets of quotes
+to start the doc string and ends with a second set of three quotes.
+For example::
+
+    r"""
+    Definition
+    ----------
+
+    The 1D scattering intensity of the sphere is calculated in the following
+    way (Guinier, 1955)
+
+    .. math::
+
+        I(q) = \frac{\text{scale}}{V} \cdot \left[
+            3V(\Delta\rho) \cdot \frac{\sin(qr) - qr\cos(qr))}{(qr)^3}
+            \right]^2 + \text{background}
+
+    where *scale* is a volume fraction, $V$ is the volume of the scatterer,
+    $r$ is the radius of the sphere and *background* is the background level.
+    *sld* and *sld_solvent* are the scattering length densities (SLDs) of the
+    scatterer and the solvent respectively, whose difference is $\Delta\rho$.
+
+    You can included figures in your documentation, as in the following
+    figure for the cylinder model.
+
+    .. figure:: img/cylinder_angle_definition.jpg
+
+        Definition of the angles for oriented cylinders.
+
+    References
+    ----------
+
+    A Guinier, G Fournet, *Small-Angle Scattering of X-Rays*,
+    John Wiley and Sons, New York, (1955)
+    """
+
+This is where the FULL documentation for the model goes (to be picked up by
+the automatic documentation system).  Although it feels odd, you
+should start the documentation immediately with the **definition**---the model
+name, a brief description and the parameter table are automatically inserted
+above the definition, and the a plot of the model is automatically inserted
+before the **reference**.
+
+Figures can be included using the *figure* command, with the name
+of the *.png* file containing the figure and a caption to appear below the
+figure.  Figure numbers will be added automatically.
+
+See this `Sphinx cheat sheet <http://matplotlib.org/sampledoc/cheatsheet.html>`_
+for a quick guide to the documentation layout commands, or the
+`Sphinx Documentation <http://www.sphinx-doc.org/en/stable/>`_ for
+complete details.
+
+The model should include a **formula** written using LaTeX markup.
+The example above uses the *math* command to make a displayed equation.  You
+can also use *\$formula\$* for an inline formula. This is handy for defining
+the relationship between the model parameters and formula variables, such
+as the phrase "\$r\$ is the radius" used above.  The live demo MathJax
+page `<http://www.mathjax.org/>`_ is handy for checking that the equations
+will look like you intend.
+
+Math layout uses the `amsmath <http://www.ams.org/publications/authors/tex/amslatex>`_
+package for aligning equations (see amsldoc.pdf on that page for complete
+documentation). You will automatically be in an aligned environment, with
+blank lines separating the lines of the equation.  Place an ampersand before
+the operator on which to align.  For example::
+
+    .. math::
+
+      x + y &= 1 \\
+      y &= x - 1
+
+produces
+
+.. math::
+
+      x + y &= 1 \\
+      y &= x - 1
+
+If you need more control, use::
+
+    .. math::
+        :nowrap:
+
+
+Model Definition
+................
+
+Following the documentation string, there are a series of definitions::
+
+    name = "sphere"  # optional: defaults to the filename without .py
+
+    title = "Spheres with uniform scattering length density"
+
+    description = """\
+    P(q)=(scale/V)*[3V(sld-sld_solvent)*(sin(qr)-qr cos(qr))
+                    /(qr)^3]^2 + background
+        r: radius of sphere
+        V: The volume of the scatter
+        sld: the SLD of the sphere
+        sld_solvent: the SLD of the solvent
+    """
+
+    category = "shape:sphere"
+
+    single = True   # optional: defaults to True
+
+    opencl = False  # optional: defaults to False
+
+    structure_factor = False  # optional: defaults to False
+
+**name = "mymodel"** defines the name of the model that is shown to the user.
+If it is not provided, it will use the name of the model file, with '_'
+replaced by spaces and the parts capitalized.  So *adsorbed_layer.py* will
+become *Adsorbed Layer*.  The predefined models all use the name of the
+model file as the name of the model, so the default may be changed.
+
+**title = "short description"** is short description of the model which
+is included after the model name in the automatically generated documentation.
+The title can also be used for a tooltip.
+
+**description = """doc string"""** is a longer description of the model. It
+shows up when you press the "Description" button of the SasView FitPage.
+It should give a brief description of the equation and the parameters
+without the need to read the entire model documentation. The triple quotes
+allow you to write the description over multiple lines. Keep the lines
+short since the GUI will wrap each one separately if they are too long.
+**Make sure the parameter names in the description match the model definition!**
+
+**category = "shape:sphere"** defines where the model will appear in the
+model documentation.  In this example, the model will appear alphabetically
+in the list of spheroid models in the *Shape* category.
+
+**single = True** indicates that the model can be run using single
+precision floating point values.  Set it to False if the numerical
+calculation for the model is unstable, which is the case for about 20 of
+the built in models.  It is worthwhile modifying the calculation to support
+single precision, allowing models to run up to 10 times faster.  The
+section `Test_Your_New_Model`_  describes how to compare model values for
+single vs. double precision so you can decide if you need to set
+single to False.
+
+**opencl = False** indicates that the model should not be run using OpenCL.
+This may be because the model definition includes code that cannot be
+compiled for the GPU (for example, goto statements).  It can also be used
+for large models which can't run on most GPUs.  This flag has not been
+used on any of the built in models; models which were failing were
+streamlined so this flag was not necessary.
+
+**structure_factor = True** indicates that the model can be used as a
+structure factor to account for interactions between particles.  See
+`Form_Factors`_ for more details.
+
+Model Parameters
+................
+
+Next comes the parameter table.  For example::
+
+    # pylint: disable=bad-whitespace, line-too-long
+    #   ["name",        "units", default, [min, max], "type",    "description"],
+    parameters = [
+        ["sld",         "1e-6/Ang^2",  1, [-inf, inf], "sld",    "Layer scattering length density"],
+        ["sld_solvent", "1e-6/Ang^2",  6, [-inf, inf], "sld",    "Solvent scattering length density"],
+        ["radius",      "Ang",        50, [0, inf],    "volume", "Sphere radius"],
+    ]
+    # pylint: enable=bad-whitespace, line-too-long
+
+**parameters = [["name", "units", default, [min,max], "type", "tooltip"],...]**
+defines the parameters that form the model.
+
+**Note: The order of the parameters in the definition will be the order of the
+parameters in the user interface and the order of the parameters in Iq(),
+Iqxy() and form_volume(). And** *scale* **and** *background* **parameters are
+implicit to all models, so they do not need to be included in the parameter table.**
+
+- **"name"** is the name of the parameter shown on the FitPage.
+
+  - parameter names should follow the mathematical convention; e.g.,
+    *radius_core* not *core_radius*, or *sld_solvent* not *solvent_sld*.
+
+  - model parameter names should be consistent between different models,
+    so *sld_solvent*, for example, should have exactly the same name
+    in every model.
+
+  - to see all the parameter names currently in use, type the following in the
+    python shell/editor under the Tools menu::
+
+       import sasmodels.list_pars
+       sasmodels.list_pars.list_pars()
+
+    *re-use* as many as possible!!!
+
+  - use "name[n]" for multiplicity parameters, where *n* is the name of
+    the parameter defining the number of shells/layers/segments, etc.
+
+- **"units"** are displayed along with the parameter name
+
+  - every parameter should have units; use "None" if there are no units.
+
+  - **sld's should be given in units of 1e-6/Ang^2, and not simply
+    1/Ang^2 to be consistent with the builtin models.  Adjust your formulas
+    appropriately.**
+
+  - fancy units markup is available for some units, including::
+
+        Ang, 1/Ang, 1/Ang^2, 1e-6/Ang^2, degrees, 1/cm, Ang/cm, g/cm^3, mg/m^2
+
+  - the list of units is defined in the variable *RST_UNITS* within
+    `sasmodels/generate.py <https://github.com/SasView/sasmodels/tree/master/sasmodels/generate.py>`_
+
+    - new units can be added using the macros defined in *doc/rst_prolog*
+      in the sasmodels source.
+    - units should be properly formatted using sub-/super-scripts
+      and using negative exponents instead of the / operator, though
+      the unit name should use the / operator for consistency.
+    - please post a message to the SasView developers mailing list with your changes.
+
+- **default** is the initial value for the parameter.
+
+  - **the parameter default values are used to auto-generate a plot of
+    the model function in the documentation.**
+
+- **[min, max]** are the lower and upper limits on the parameter.
+
+  - lower and upper limits can be any number, or *-inf* or *inf*.
+
+  - the limits will show up as the default limits for the fit making it easy,
+    for example, to force the radius to always be greater than zero.
+
+  - these are hard limits defining the valid range of parameter values;
+    polydisperity distributions will be truncated at the limits.
+
+- **"type"** can be one of: "", "sld", "volume", or "orientation".
+
+  - "sld" parameters can have magnetic moments when fitting magnetic models;
+    depending on the spin polarization of the beam and the $q$ value being
+    examined, the effective sld for that material will be used to compute the
+    scattered intensity.
+
+  - "volume" parameters are passed to Iq(), Iqxy(), and form_volume(), and
+    have polydispersity loops generated automatically.
+
+  - "orientation" parameters are only passed to Iqxy(), and have angular
+    dispersion.
+
+
+Model Computation
+.................
+
+Models can be defined as pure python models, or they can be a mixture of
+python and C models.  C models are run on the GPU if it is available,
+otherwise they are compiled and run on the CPU.
+
+Models are defined by the scattering kernel, which takes a set of parameter
+values defining the shape, orientation and material, and returns the
+expected scattering. Polydispersity and angular dispersion are defined
+by the computational infrastructure.  Any parameters defined as "volume"
+parameters are polydisperse, with polydispersity defined in proportion
+to their value.  "orientation" parameters use angular dispersion defined
+in degrees, and are not relative to the current angle.
+
+Based on a weighting function $G(x)$ and a number of points $n$, the
+computed value is
+
+.. math::
+
+     \hat I(q)
+     = \frac{\int G(x) I(q, x)\,dx}{\int G(x) V(x)\,dx}
+     \approx \frac{\sum_{i=1}^n G(x_i) I(q,x_i)}{\sum_{i=1}^n G(x_i) V(x_i)}
+
+That is, the indivdual models do not need to include polydispersity
+calculations, but instead rely on numerical integration to compute the
+appropriately smeared pattern.   Angular dispersion values over polar angle
+$\theta$ requires an additional $\cos \theta$ weighting due to decreased
+arc length for the equatorial angle $\phi$ with increasing latitude.
+
+Python Models
+.............
+
+For pure python models, define the *Iq* function::
+
+      import numpy as np
+      from numpy import cos, sin, ...
+
+      def Iq(q, par1, par2, ...):
+          return I(q, par1, par2, ...)
+      Iq.vectorized = True
+
+The parameters *par1, par2, ...* are the list of non-orientation parameters
+to the model in the order that they appear in the parameter table.
+**Note that the autogenerated model file uses** *x* **rather than** *q*.
+
+The *.py* file should import trigonometric and exponential functions from
+numpy rather than from math.  This lets us evaluate the model for the whole
+range of $q$ values at once rather than looping over each $q$ separately in
+python.  With $q$ as a vector, you cannot use if statements, but must instead
+do tricks like
+
+::
+
+     a = x*q*(q>0) + y*q*(q<=0)
+
+or
+
+::
+
+     a = np.empty_like(q)
+     index = q>0
+     a[index] = x*q[index]
+     a[~index] = y*q[~index]
+
+which sets $a$ to $q \cdot x$ if $q$ is positive or $q \cdot y$ if $q$
+is zero or negative. If you have not converted your function to use $q$
+vectors, you can set the following and it will only receive one $q$
+value at a time::
+
+    Iq.vectorized = False
+
+Return np.NaN if the parameters are not valid (e.g., cap_radius < radius in
+barbell).  If I(q; pars) is NaN for any $q$, then those parameters will be
+ignored, and not included in the calculation of the weighted polydispersity.
+
+Similar to *Iq*, you can define *Iqxy(qx, qy, par1, par2, ...)* where the
+parameter list includes any orientation parameters.  If *Iqxy* is not defined,
+then it will default to *Iqxy = Iq(sqrt(qx**2+qy**2), par1, par2, ...)*.
+
+Models should define *form_volume(par1, par2, ...)* where the parameter
+list includes the *volume* parameters in order.  This is used for a weighted
+volume normalization so that scattering is on an absolute scale.  If
+*form_volume* is not defined, then the default *form_volume = 1.0* will be
+used.
+
+Embedded C Models
+.................
+
+Like pure python models, inline C models need to define an *Iq* function::
+
+    Iq = """
+        return I(q, par1, par2, ...);
+    """
+
+This expands into the equivalent C code::
+
+    #include <math.h>
+    double Iq(double q, double par1, double par2, ...);
+    double Iq(double q, double par1, double par2, ...)
+    {
+        return I(q, par1, par2, ...);
+    }
+
+*Iqxy* is similar to *Iq*, except it uses parameters *qx, qy* instead of *q*,
+and it includes orientation parameters.
+
+*form_volume* defines the volume of the shape. As in python models, it
+includes only the volume parameters.
+
+*Iqxy* will default to *Iq(sqrt(qx**2 + qy**2), par1, ...)* and
+*form_volume* will default to 1.0.
+
+**source=['fn.c', ...]** includes the listed C source files in the
+program before *Iq* and *Iqxy* are defined. This allows you to extend the
+library of C functions available to your model.
+
+Models are defined using double precision declarations for the
+parameters and return values.  When a model is run using single
+precision or long double precision, each variable is converted
+to the target type, depending on the precision requested.
+
+**Floating point constants must include the decimal point.**  This allows us
+to convert values such as 1.0 (double precision) to 1.0f (single precision)
+so that expressions that use these values are not promoted to double precision
+expressions.  Some graphics card drivers are confused when functions
+that expect floating point values are passed integers, such as 4*atan(1); it
+is safest to not use integers in floating point expressions.  Even better,
+use the builtin constant M_PI rather than 4*atan(1); it is faster and smaller!
+
+The C model operates on a single $q$ value at a time.  The code will be
+run in parallel across different $q$ values, either on the graphics card
+or the processor.
+
+Rather than returning NAN from Iq, you must define the *INVALID(v)*.  The
+*v* parameter lets you access all the parameters in the model using
+*v.par1*, *v.par2*, etc. For example::
+
+    #define INVALID(v) (v.bell_radius < v.radius)
+
+Special Functions
+.................
+
+The C code follows the C99 standard, with the usual math functions,
+as defined in
+`OpenCL <https://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/mathFunctions.html>`_.
+This includes the following:
+
+    M_PI, M_PI_2, M_PI_4, M_SQRT1_2, M_E:
+        $\pi$, $\pi/2$, $\pi/4$, $1/\sqrt{2}$ and Euler's constant $e$
+    exp, log, pow(x,y), expm1, sqrt:
+        Power functions $e^x$, $\ln x$, $x^y$, $e^x - 1$, $\sqrt{x}$.
+        The function expm1(x) is accurate across all $x$, including $x$
+        very close to zero.
+    sin, cos, tan, asin, acos, atan:
+        Trigonometry functions and inverses, operating on radians.
+    sinh, cosh, tanh, asinh, acosh, atanh:
+        Hyperbolic trigonometry functions.
+    atan2(y,x):
+        Angle from the $x$\ -axis to the point $(x,y)$, which is equal to
+        $\tan^{-1}(y/x)$ corrected for quadrant.  That is, if $x$ and $y$ are
+        both negative, then atan2(y,x) returns a value in quadrant III where
+        atan(y/x) would return a value in quadrant I. Similarly for
+        quadrants II and IV when $x$ and $y$ have opposite sign.
+    fmin(x,y), fmax(x,y), trunc, rint:
+        Floating point functions.  rint(x) returns the nearest integer.
+    NAN:
+        NaN, Not a Number, $0/0$.  Use isnan(x) to test for NaN.  Note that
+        you cannot use :code:`x == NAN` to test for NaN values since that
+        will always return false.  NAN does not equal NAN!
+    INFINITY:
+        $\infty, 1/0$.  Use isinf(x) to test for infinity, or isfinite(x)
+        to test for finite and not NaN.
+    erf, erfc, tgamma, lgamma:  **do not use**
+        Special functions that should be part of the standard, but are missing
+        or inaccurate on some platforms. Use sas_erf, sas_erfc and sas_gamma
+        instead (see below). Note: lgamma(x) has not yet been tested.
+
+Some non-standard constants and functions are also provided:
+
+    M_PI_180, M_4PI_3:
+        $\frac{\pi}{180}$, $\frac{4\pi}{3}$
+    SINCOS(x, s, c):
+        Macro which sets s=sin(x) and c=cos(x). The variables *c* and *s*
+        must be declared first.
+    square(x):
+        $x^2$
+    cube(x):
+        $x^3$
+    sas_sinx_x(x):
+        $\sin(x)/x$, with limit $\sin(0)/0 = 1$.
+    powr(x, y):
+        $x^y$ for $x \ge 0$; this is faster than general $x^y$ on some GPUs.
+    pown(x, n):
+        $x^n$ for $n$ integer; this is faster than general $x^n$ on some GPUs.
+    FLOAT_SIZE:
+        The number of bytes in a floating point value.  Even though all
+        variables are declared double, they may be converted to single
+        precision float before running. If your algorithm depends on
+        precision (which is not uncommon for numerical algorithms), use
+        the following::
+
+            #if FLOAT_SIZE>4
+            ... code for double precision ...
+            #else
+            ... code for single precision ...
+            #endif
+    SAS_DOUBLE:
+        A replacement for :code:`double` so that the declared variable will
+        stay double precision; this should generally not be used since some
+        graphics cards do not support double precision.  There is no provision
+        for forcing a constant to stay double precision.
+
+The following special functions and scattering calculations are defined in
+`sasmodels/models/lib <https://github.com/SasView/sasmodels/tree/master/sasmodels/models/lib>`_.
+These functions have been tuned to be fast and numerically stable down
+to $q=0$ even in single precision.  In some cases they work around bugs
+which appear on some platforms but not others, so use them where needed.
+Add the files listed in :code:`source = ["lib/file.c", ...]` to your *model.py*
+file in the order given, otherwise these functions will not be available.
+
+    polevl(x, c, n):
+        Polynomial evaluation $p(x) = \sum_{i=0}^n c_i x^i$ using Horner's
+        method so it is faster and more accurate.
+
+        $c = \{c_n, c_{n-1}, \ldots, c_0 \}$ is the table of coefficients,
+        sorted from highest to lowest.
+
+        :code:`source = ["lib/polevl.c", ...]` (`link to code <https://github.com/SasView/sasmodels/tree/master/sasmodels/models/lib/polevl.c>`_)
+
+    p1evl(x, c, n):
+        Evaluation of normalized polynomial $p(x) = x^n + \sum_{i=0}^{n-1} c_i x^i$
+        using Horner's method so it is faster and more accurate.
+
+        $c = \{c_{n-1}, c_{n-2} \ldots, c_0 \}$ is the table of coefficients,
+        sorted from highest to lowest.
+
+        :code:`source = ["lib/polevl.c", ...]`
+        (`link to code <https://github.com/SasView/sasmodels/tree/master/sasmodels/models/lib/polevl.c>`_)
+
+    sas_gamma(x):
+        Gamma function $\text{sas_gamma}(x) = \Gamma(x)$.
+
+        The standard math function, tgamma(x) is unstable for $x < 1$
+        on some platforms.
+
+        :code:`source = ["lib/sasgamma.c", ...]`
+        (`link to code <https://github.com/SasView/sasmodels/tree/master/sasmodels/models/lib/sas_gamma.c>`_)
+
+    sas_erf(x), sas_erfc(x):
+        Error function
+        $\text{sas_erf}(x) = \frac{2}{\sqrt\pi}\int_0^x e^{-t^2}\,dt$
+        and complementary error function
+        $\text{sas_erfc}(x) = \frac{2}{\sqrt\pi}\int_x^{\infty} e^{-t^2}\,dt$.
+
+        The standard math functions erf(x) and erfc(x) are slower and broken
+        on some platforms.
+
+        :code:`source = ["lib/polevl.c", "lib/sas_erf.c", ...]`
+        (`link to error functions' code <https://github.com/SasView/sasmodels/tree/master/sasmodels/models/lib/sas_erf.c>`_)
+
+    sas_J0(x):
+        Bessel function of the first kind $\text{sas_J0}(x)=J_0(x)$ where
+        $J_0(x) = \frac{1}{\pi}\int_0^\pi \cos(x\sin(\tau))\,d\tau$.
+
+        The standard math function j0(x) is not available on all platforms.
+
+        :code:`source = ["lib/polevl.c", "lib/sas_J0.c", ...]`
+        (`link to Bessel function's code <https://github.com/SasView/sasmodels/tree/master/sasmodels/models/lib/sas_J0.c>`_)
+
+    sas_J1(x):
+        Bessel function of the first kind  $\text{sas_J1}(x)=J_1(x)$ where
+        $J_1(x) = \frac{1}{\pi}\int_0^\pi \cos(\tau - x\sin(\tau))\,d\tau$.
+
+        The standard math function j1(x) is not available on all platforms.
+
+        :code:`source = ["lib/polevl.c", "lib/sas_J1.c", ...]`
+        (`link to Bessel function's code <https://github.com/SasView/sasmodels/tree/master/sasmodels/models/lib/sas_J1.c>`_)
+
+    sas_JN(n, x):
+        Bessel function of the first kind and integer order $n$:
+        $\text{sas_JN}(n, x)=J_n(x)$ where
+        $J_n(x) = \frac{1}{\pi}\int_0^\pi \cos(n\tau - x\sin(\tau))\,d\tau$.
+        If $n$ = 0 or 1, it uses sas_J0(x) or sas_J1(x), respectively.
+
+        The standard math function jn(n, x) is not available on all platforms.
+
+        :code:`source = ["lib/polevl.c", "lib/sas_J0.c", "lib/sas_J1.c", "lib/sas_JN.c", ...]`
+        (`link to Bessel function's code <https://github.com/SasView/sasmodels/tree/master/sasmodels/models/lib/sas_JN.c>`_)
+
+    sas_Si(x):
+        Sine integral $\text{Si}(x) = \int_0^x \tfrac{\sin t}{t}\,dt$.
+
+        This function uses Taylor series for small and large arguments:
+
+        For large arguments,
+
+        .. math::
+
+             \text{Si}(x) \sim \frac{\pi}{2}
+             - \frac{\cos(x)}{x}\left(1 - \frac{2!}{x^2} + \frac{4!}{x^4} - \frac{6!}{x^6} \right)
+             - \frac{\sin(x)}{x}\left(\frac{1}{x} - \frac{3!}{x^3} + \frac{5!}{x^5} - \frac{7!}{x^7}\right)
+
+        For small arguments,
+
+        .. math::
+
+           \text{Si}(x) \sim x
+           - \frac{x^3}{3\times 3!} + \frac{x^5}{5 \times 5!} - \frac{x^7}{7 \times 7!}
+           + \frac{x^9}{9\times 9!} - \frac{x^{11}}{11\times 11!}
+
+        :code:`source = ["lib/Si.c", ...]`
+        (`link to code <https://github.com/SasView/sasmodels/tree/master/sasmodels/models/lib/Si.c>`_)
+
+    sas_3j1x_x(x):
+        Spherical Bessel form
+        $\text{sph_j1c}(x) = 3 j_1(x)/x = 3 (\sin(x) - x \cos(x))/x^3$,
+        with a limiting value of 1 at $x=0$, where $j_1(x)$ is the spherical
+        Bessel function of the first kind and first order.
+
+        This function uses a Taylor series for small $x$ for numerical accuracy.
+
+        :code:`source = ["lib/sas_3j1x_x.c", ...]`
+        (`link to code <https://github.com/SasView/sasmodels/tree/master/sasmodels/models/lib/sas_3j1x_x.c>`_)
+
+
+    sas_2J1x_x(x):
+        Bessel form $\text{sas_J1c}(x) = 2 J_1(x)/x$, with a limiting value
+        of 1 at $x=0$, where $J_1(x)$ is the Bessel function of first kind
+        and first order.
+
+        :code:`source = ["lib/polevl.c", "lib/sas_J1.c", ...]`
+        (`link to Bessel form's code <https://github.com/SasView/sasmodels/tree/master/sasmodels/models/lib/sas_J1.c>`_)
+
+
+    Gauss76Z[i], Gauss76Wt[i]:
+        Points $z_i$ and weights $w_i$ for 76-point Gaussian quadrature, respectively,
+        computing $\int_{-1}^1 f(z)\,dz \approx \sum_{i=1}^{76} w_i\,f(z_i)$.
+
+        Similar arrays are available in :code:`gauss20.c` for 20-point
+        quadrature and in :code:`gauss150.c` for 150-point quadrature.
+
+        :code:`source = ["lib/gauss76.c", ...]`
+        (`link to code <https://github.com/SasView/sasmodels/tree/master/sasmodels/models/lib/gauss76.c>`_)
+
+
+
+Problems with C models
+......................
+
+The graphics processor (GPU) in your computer is a specialized computer tuned
+for certain kinds of problems.  This leads to strange restrictions that you
+need to be aware of.  Your code may work fine on some platforms or for some
+models, but then return bad values on other platforms.  Some examples of
+particular problems:
+
+  **(1) Code is too complex, or uses too much memory.** GPU devices only
+  have a limited amount of memory available for each processor. If you run
+  programs which take too much memory, then rather than running multiple
+  values in parallel as it usually does, the GPU may only run a single
+  version of the code at a time, making it slower than running on the CPU.
+  It may fail to run on some platforms, or worse, cause the screen to go
+  blank or the system to reboot.
+
+  **(2) Code takes too long.** Because GPU devices are used for the computer
+  display, the OpenCL drivers are very careful about the amount of time they
+  will allow any code to run. For example, on OS X, the model will stop
+  running after 5 seconds regardless of whether the computation is complete.
+  You may end up with only some of your 2D array defined, with the rest
+  containing random data. Or it may cause the screen to go blank or the
+  system to reboot.
+
+  **(3) Memory is not aligned**. The GPU hardware is specialized to operate
+  on multiple values simultaneously. To keep the GPU simple the values in
+  memory must be aligned with the different GPU compute engines. Not
+  following these rules can lead to unexpected values being loaded into
+  memory, and wrong answers computed. The conclusion from a very long and
+  strange debugging session was that any arrays that you declare in your
+  model should be a multiple of four. For example::
+
+      double Iq(q, p1, p2, ...)
+      {
+          double vector[8];  // Only going to use seven slots, but declare 8
+          ...
+      }
+
+The first step when your model is behaving strangely is to set
+**single=False**. This automatically restricts the model to only run on the
+CPU, or on high-end GPU cards. There can still be problems even on high-end
+cards, so you can force the model off the GPU by setting **opencl=False**.
+This runs the model as a normal C program without any GPU restrictions so
+you know that strange results are probably from your code rather than the
+environment. Once the code is debugged, you can compare your output to the
+output on the GPU.
+
+Although it can be difficult to get your model to work on the GPU, the reward
+can be a model that runs 1000x faster on a good card.  Even your laptop may
+show a 50x improvement or more over the equivalent pure python model.
+
+External C Models
+.................
+
+External C models are very much like embedded C models, except that
+*Iq*, *Iqxy* and *form_volume* are defined in an external source file
+loaded using the *source=[...]* statement. You need to supply the function
+declarations for each of these that you need instead of building them
+automatically from the parameter table.
+
+
+.. _Form_Factors:
+
+Form Factors
+............
+
+Away from the dilute limit you can estimate scattering including
+particle-particle interactions using $I(q) = P(q)*S(q)$ where $P(q)$
+is the form factor and $S(q)$ is the structure factor.  The simplest
+structure factor is the *hardsphere* interaction, which
+uses the effective radius of the form factor as an input to the structure
+factor model.  The effective radius is the average radius of the
+form averaged over all the polydispersity values.
+
+::
+
+    def ER(radius, thickness):
+        """Effective radius of a core-shell sphere."""
+        return radius + thickness
+
+Now consider the *core_shell_sphere*, which has a simple effective radius
+equal to the radius of the core plus the thickness of the shell, as
+shown above. Given polydispersity over *(r1, r2, ..., rm)* in radius and
+*(t1, t2, ..., tn)* in thickness, *ER* is called with a mesh
+grid covering all possible combinations of radius and thickness.
+That is, *radius* is *(r1, r2, ..., rm, r1, r2, ..., rm, ...)*
+and *thickness* is *(t1, t1, ... t1, t2, t2, ..., t2, ...)*.
+The *ER* function returns one effective radius for each combination.
+The effective radius calculator weights each of these according to
+the polydispersity distributions and calls the structure factor
+with the average *ER*.
+
+::
+
+    def VR(radius, thickness):
+        """Sphere and shell volumes for a core-shell sphere."""
+        whole = 4.0/3.0 * pi * (radius + thickness)**3
+        core = 4.0/3.0 * pi * radius**3
+        return whole, whole - core
+
+Core-shell type models have an additional volume ratio which scales
+the structure factor.  The *VR* function returns the volume of
+the whole sphere and the volume of the shell. Like *ER*, there is
+one return value for each point in the mesh grid.
+
+*NOTE: we may be removing or modifying this feature soon. As of the
+time of writing, core-shell sphere returns (1., 1.) for VR, giving a volume
+ratio of 1.0.*
+
+Unit Tests
+..........
+
+THESE ARE VERY IMPORTANT. Include at least one test for each model and
+PLEASE make sure that the answer value is correct (i.e. not a random number).
+
+::
+
+    tests = [
+        [{}, 0.2, 0.726362],
+        [{"scale": 1., "background": 0., "sld": 6., "sld_solvent": 1.,
+          "radius": 120., "radius_pd": 0.2, "radius_pd_n":45},
+         0.2, 0.228843],
+        [{"radius": 120., "radius_pd": 0.2, "radius_pd_n":45}, "ER", 120.],
+        [{"radius": 120., "radius_pd": 0.2, "radius_pd_n":45}, "VR", 1.],
+    ]
+
+
+**tests=[[{parameters}, q, result], ...]** is a list of lists.
+Each list is one test and contains, in order:
+
+- a dictionary of parameter values. This can be *{}* using the default
+  parameters, or filled with some parameters that will be different from the
+  default, such as *{"radius":10.0, "sld":4}*. Unlisted parameters will
+  be given the default values.
+- the input $q$ value or tuple of $(q_x, q_y)$ values.
+- the output $I(q)$ or $I(q_x,q_y)$ expected of the model for the parameters
+  and input value given.
+- input and output values can themselves be lists if you have several
+  $q$ values to test for the same model parameters.
+- for testing *ER* and *VR*, give the inputs as "ER" and "VR" respectively;
+  the output for *VR* should be the sphere/shell ratio, not the individual
+  sphere and shell values.
+
+.. _Test_Your_New_Model:
+
+Test Your New Model
+^^^^^^^^^^^^^^^^^^^
+
+Minimal Testing
+...............
+
+From SasView either open the Python shell (*Tools* > *Python Shell/Editor*)
+or the plugin editor (*Fitting* > *Plugin Model Operations* > *Advanced
+Plugin Editor*), load your model, and then select *Run > Check Model* from
+the menu bar. An *Info* box will appear with the results of the compilation
+and a check that the model runs.
+
+If you are not using sasmodels from SasView, skip this step.
+
+Recommended Testing
+...................
+
+If the model compiles and runs, you can next run the unit tests that
+you have added using the **test =** values.
+
+From SasView, switch to the *Shell* tab and type the following::
+
+    from sasmodels.model_test import run_one
+    run_one("~/.sasview/plugin_models/model.py")
+
+This should print::
+
+    test_model_python (sasmodels.model_test.ModelTestCase) ... ok
+
+To check whether single precision is good enough, type the following::
+
+    from sasmodels.compare import main as compare
+    compare("~/.sasview/plugin_models/model.py")
+
+This will pop up a plot showing the difference between single precision
+and double precision on a range of $q$ values.
+
+::
+
+  demo = dict(scale=1, background=0,
+              sld=6, sld_solvent=1,
+              radius=120,
+              radius_pd=.2, radius_pd_n=45)
+
+**demo={'par': value, ...}** in the model file sets the default values for
+the comparison. You can include polydispersity parameters such as
+*radius_pd=0.2, radius_pd_n=45* which would otherwise be zero.
+
+These commands can also be run directly in the python interpreter:
+
+    $ python -m sasmodels.model_test -v ~/.sasview/plugin_models/model.py
+    $ python -m sasmodels.compare ~/.sasview/plugin_models/model.py
+
+The options to compare are quite extensive; type the following for help::
+
+    compare()
+
+Options will need to be passed as separate strings.
+For example to run your model with a random set of parameters::
+
+    compare("-random", "-pars", "~/.sasview/plugin_models/model.py")
+
+For the random models,
+
+- *sld* will be in the range (-0.5,10.5),
+- angles (*theta, phi, psi*) will be in the range (-180,180),
+- angular dispersion will be in the range (0,45),
+- polydispersity will be in the range (0,1)
+- other values will be in the range (0, 2\ *v*), where *v* is the value
+  of the parameter in demo.
+
+Dispersion parameters *n*\, *sigma* and *type* will be unchanged from
+demo so that run times are more predictable (polydispersity calculated
+across multiple parameters can be very slow).
+
+If your model has 2D orientational calculation, then you should also
+test with::
+
+    compare("-2d", "~/.sasview/plugin_models/model.py")
+
+Check The Docs
+^^^^^^^^^^^^^^
+
+You can get a rough idea of how the documentation will look using the
+following::
+
+    compare("-help", "~/.sasview/plugin_models/model.py")
+
+This does not use the same styling as the rest of the docs, but it will
+allow you to check that your ReStructuredText and LaTeX formatting.
+Here are some tools to help with the inevitable syntax errors:
+
+- `Sphinx cheat sheet <http://matplotlib.org/sampledoc/cheatsheet.html>`_
+- `Sphinx Documentation <http://www.sphinx-doc.org/en/stable/>`_
+- `MathJax <http://www.mathjax.org/>`_
+- `amsmath <http://www.ams.org/publications/authors/tex/amslatex>`_
+
+There is also a neat online WYSIWYG ReStructuredText editor at
+http://rst.ninjs.org\ .
+
+
+Clean Lint - (Developer Version Only)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+**NB: For now we are not providing pylint with the installer version
+of SasView; so unless you have a SasView build environment available,
+you can ignore this section!**
+
+Run the lint check with::
+
+    python -m pylint --rcfile=extra/pylint.rc ~/.sasview/plugin_models/model.py
+
+We are not aiming for zero lint just yet, only keeping it to a minimum.
+For now, don't worry too much about *invalid-name*. If you really want a
+variable name *Rg* for example because $R_g$ is the right name for the model
+parameter then ignore the lint errors.  Also, ignore *missing-docstring*
+for standard model functions *Iq*, *Iqxy*, etc.
+
+We will have delinting sessions at the SasView Code Camps, where we can
+decide on standards for model files, parameter names, etc.
+
+For now, you can tell pylint to ignore things.  For example, to align your
+parameters in blocks::
+
+    # pylint: disable=bad-whitespace,line-too-long
+    #   ["name",                  "units", default, [lower, upper], "type", "description"],
+    parameters = [
+        ["contrast_factor",       "barns",    10.0,  [-inf, inf], "", "Contrast factor of the polymer"],
+        ["bjerrum_length",        "Ang",       7.1,  [0, inf],    "", "Bjerrum length"],
+        ["virial_param",          "1/Ang^2",  12.0,  [-inf, inf], "", "Virial parameter"],
+        ["monomer_length",        "Ang",      10.0,  [0, inf],    "", "Monomer length"],
+        ["salt_concentration",    "mol/L",     0.0,  [-inf, inf], "", "Concentration of monovalent salt"],
+        ["ionization_degree",     "",          0.05, [0, inf],    "", "Degree of ionization"],
+        ["polymer_concentration", "mol/L",     0.7,  [0, inf],    "", "Polymer molar concentration"],
+        ]
+    # pylint: enable=bad-whitespace,line-too-long
+
+Don't put in too many pylint statements, though, since they make the code ugly.
+
+Share Your Model!
+^^^^^^^^^^^^^^^^^
+
+Once compare and the unit test(s) pass properly and everything is done,
+consider adding your model to the
+`Model Marketplace <http://marketplace.sasview.org/>`_ so that others may use it!
+
+.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+
+*Document History*
+
+| 2016-10-25 Steve King
+| 2017-05-07 Paul Kienzle - Moved from sasview to sasmodels docs
Index: doc/guide/refs.rst
===================================================================
--- doc/guide/refs.rst	(revision 8ae853293022b5081a1e1a8c26f74eaa2b3f8a13)
+++ doc/guide/refs.rst	(revision 8ae853293022b5081a1e1a8c26f74eaa2b3f8a13)
@@ -0,0 +1,35 @@
+.. _models-refs:
+
+**********
+References
+**********
+
+*Small-Angle Scattering of X-Rays*
+A Guinier and G Fournet
+John Wiley & Sons, New York (1955)
+
+P Stckel, R May, I Strell, Z Cejka, W Hoppe, H Heumann, W Zillig and H Crespi
+*Eur. J. Biochem.*, 112, (1980), 411-417
+
+G Porod
+in *Small Angle X-ray Scattering*
+(editors) O Glatter and O Kratky
+Academic Press (1982)
+
+*Structure Analysis by Small-Angle X-Ray and Neutron Scattering*
+L.A Feigin and D I Svergun
+Plenum Press, New York (1987)
+
+S Hansen
+*J. Appl. Cryst.* 23, (1990), 344-346
+
+S J Henderson
+*Biophys. J.* 70, (1996), 1618-1627
+
+B C McAlister and B P Grady
+*J. Appl. Cryst.* 31, (1998), 594-599
+
+S R Kline
+*J Appl. Cryst.* 39(6), (2006), 895
+
+**Also see the references at the end of the each model function descriptions.**
Index: doc/guide/resolution.rst
===================================================================
--- doc/guide/resolution.rst	(revision 990d8dfe5ac399564bc0bb3b873c5a1b56d4e573)
+++ doc/guide/resolution.rst	(revision 990d8dfe5ac399564bc0bb3b873c5a1b56d4e573)
@@ -0,0 +1,294 @@
+.. sm_help.rst
+
+.. This is a port of the original SasView html help file to ReSTructured text
+.. by S King, ISIS, during SasView CodeCamp-III in Feb 2015.
+
+
+.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+
+Resolution Functions
+====================
+
+Sometimes the instrumental geometry used to acquire the experimental data has
+an impact on the clarity of features in the reduced scattering curve. For
+example, peaks or fringes might be slightly broadened. This is known as
+*Q resolution smearing*. To compensate for this effect one can either try and
+remove the resolution contribution - a process called *desmearing* - or add the
+resolution contribution into a model calculation/simulation (which by definition
+will be exact) to make it more representative of what has been measured
+experimentally - a process called *smearing*. sasmodels does the latter.
+
+Both smearing and desmearing rely on functions to describe the resolution
+effect. sasmodels provides three smearing algorithms:
+
+*  *Slit Smearing*
+*  *Pinhole Smearing*
+*  *2D Smearing*
+
+The $Q$ resolution values should be determined by the data reduction software
+for the instrument and stored with the data file.  If not, they will need to
+be set manually before fitting.
+
+
+.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+
+Slit Smearing
+-------------
+
+**This type of smearing is normally only encountered with data from X-ray Kratky**
+**cameras or X-ray/neutron Bonse-Hart USAXS/USANS instruments.**
+
+The slit-smeared scattering intensity is defined by
+
+.. math::
+    I_s = \frac{1}{\text{Norm}}
+          \int_{-\infty}^{\infty} dv\, W_v(v)
+          \int_{-\infty}^{\infty} du\, W_u(u)\,
+          I\left(\sqrt{(q+v)^2 + |u|^2}\right)
+
+where *Norm* is given by
+
+.. math:: \int_{-\infty}^{\infty} dv\, W_v(v) \int_{-\infty}^{\infty} du\, W_u(u)
+
+**[Equation 1]**
+
+The functions $W_v(v)$ and $W_u(u)$ refer to the slit width weighting
+function and the slit height weighting determined at the given $q$ point,
+respectively. It is assumed that the weighting function is described by a
+rectangular function, such that
+
+.. math:: W_v(v) = \delta(|v| \leq \Delta q_v)
+
+**[Equation 2]**
+
+and
+
+.. math:: W_u(u) = \delta(|u| \leq \Delta q_u)
+
+**[Equation 3]**
+
+so that $\Delta q_\alpha = \int_0^\infty d\alpha\, W_\alpha(\alpha)$
+for $\alpha$ as $v$ and $u$.
+
+Here $\Delta q_u$ and $\Delta q_v$ stand for the the slit height (FWHM/2)
+and the slit width (FWHM/2) in $q$ space.
+
+This simplifies the integral in Equation 1 to
+
+.. math::
+
+    I_s(q) = \frac{2}{\text{Norm}}
+             \int_{-\Delta q_v}^{\Delta q_v} dv
+             \int_{0}^{\Delta q_u}
+             du\, I\left(\sqrt{(q+v)^2 + u^2}\right)
+
+**[Equation 4]**
+
+which may be solved numerically, depending on the nature of
+$\Delta q_u$ and $\Delta q_v$.
+
+Solution 1
+^^^^^^^^^^
+
+**For** $\Delta q_v = 0$ **and** $\Delta q_u = \text{constant}$
+
+.. math::
+
+    I_s(q) \approx \int_0^{\Delta q_u} du\, I\left(\sqrt{q^2+u^2}\right)
+           = \int_0^{\Delta q_u} d\left(\sqrt{q'^2-q^2}\right)\, I(q')
+
+For discrete $q$ values, at the $q$ values of the data points and at the $q$
+values extended up to $q_N = q_i + \Delta q_v$ the smeared
+intensity can be approximately calculated as
+
+.. math::
+
+    I_s(q_i)
+    \approx \sum_{j=i}^{N-1} \left[\sqrt{q_{j+1}^2 - q_i^2} - \sqrt{q_j^2 - q_i^2}\right]\, I(q_j)
+            \sum_{j=1}^{N-1} W_{ij}\, I(q_j)
+
+**[Equation 5]**
+
+where $W_{ij} = 0$ for $I_s$ when $j < i$ or $j > N-1$.
+
+Solution 2
+^^^^^^^^^^
+
+**For** $\Delta q_v = \text{constant}$ **and** $\Delta q_u = 0$
+
+Similar to Case 1
+
+.. math::
+
+    I_s(q_i)
+    \approx \sum_{j=p}^{N-1} [q_{j+1} - q_i]\, I(q_j)
+    \approx \sum_{j=p}^{N-1} W_{ij}\, I(q_j)
+
+for $q_p = q_i - \Delta q_v$ and $q_N = q_i + \Delta q_v$
+
+**[Equation 6]**
+
+where $W_{ij} = 0$ for $I_s$ when $j < p$ or $j > N-1$.
+
+Solution 3
+^^^^^^^^^^
+
+**For** $\Delta q_v = \text{constant}$ **and** $\Delta q_u = \text{constant}$
+
+In this case, the best way is to perform the integration of Equation 1
+numerically for both slit height and slit width. However, the numerical
+integration is imperfect unless a large number of iterations, say, at
+least 10000 by 10000 for each element of the matrix $W$, is performed.
+This is usually too slow for routine use.
+
+An alternative approach is used in sasmodels which assumes
+slit width << slit height. This method combines Solution 1 with the
+numerical integration for the slit width. Then
+
+.. math::
+
+    I_s(q_i)
+    &\approx \sum_{j=p}^{N-1} \sum_{k=-L}^L
+            \left[\sqrt{q_{j+1}^2 - (q_i + (k\Delta q_v/L))^2}
+                  - \sqrt{q_j^2 - (q_i + (k\Delta q_v/L))^2}\right]
+            (\Delta q_v/L)\, I(q_j) \\
+    &\approx \sum_{j=p}^{N-1} W_{ij}\,I(q_j)
+
+**[Equation 7]**
+
+for $q_p = q_i - \Delta q_v$ and $q_N = q_i + \Delta q_v$
+
+where $W_{ij} = 0$ for $I_s$ when $j < p$ or $j > N-1$.
+
+.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+
+Pinhole Smearing
+----------------
+
+**This is the type of smearing normally encountered with data from synchrotron**
+**SAXS cameras and SANS instruments.**
+
+The pinhole smearing computation is performed in a similar fashion to the slit-
+smeared case above except that the weight function used is a Gaussian. Thus
+Equation 6 becomes
+
+.. math::
+
+    I_s(q_i)
+    &\approx \sum_{j=0}^{N-1}[\operatorname{erf}(q_{j+1})
+                - \operatorname{erf}(q_j)]\, I(q_j) \\
+    &\approx \sum_{j=0}^{N-1} W_{ij}\, I(q_j)
+
+**[Equation 8]**
+
+.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+
+2D Smearing
+-----------
+
+The 2D smearing computation is performed in a similar fashion to the 1D pinhole
+smearing above except that the weight function used is a 2D elliptical Gaussian.
+Thus
+
+.. math::
+
+  I_s(x_0,\, y_0)
+  &= A\iint dx'dy'\,
+     \exp \left[ -\left(\frac{(x'-x_0')^2}{2\sigma_{x_0'}^2}
+                      + \frac{(y'-y_0')^2}{2\sigma_{y_0'}}\right)\right] I(x',\, y') \\
+  &= A\sigma_{x_0'}\sigma_{y_0'}\iint dX dY\,
+     \exp\left[-\frac{(X^2+Y^2)}{2}\right] I(\sigma_{x_0'}X x_0',\, \sigma_{y_0'} Y + y_0') \\
+  &= A\sigma_{x_0'}\sigma_{y_0'}\iint dR d\Theta\,
+     R\exp\left(-\frac{R^2}{2}\right) I(\sigma_{x_0'}R\cos\Theta + x_0',\, \sigma_{y_0'}R\sin\Theta+y_0')
+
+**[Equation 9]**
+
+In Equation 9, $x_0 = q \cos(\theta)$, $y_0 = q \sin(\theta)$, and
+the primed axes are all in the coordinate rotated by an angle $\theta$ about
+the $z$\ -axis (see the figure below) so that
+$x'_0 = x_0 \cos(\theta) + y_0 \sin(\theta)$ and
+$y'_0 = -x_0 \sin(\theta) + y_0 \cos(\theta)$.
+Note that the rotation angle is zero for a $x$\ -\ $y$ symmetric
+elliptical Gaussian distribution. The $A$ is a normalization factor.
+
+.. figure:: resolution_2d_rotation.gif
+
+    Coordinate axis rotation for 2D resolution calculation.
+
+Now we consider a numerical integration where each of the bins in $\theta$
+and $R$ are *evenly* (this is to simplify the equation below) distributed
+by $\Delta \theta$ and $\Delta R$ respectively, and it is further assumed
+that $I(x',y')$ is constant within the bins. Then
+
+.. math::
+
+   I_s(x_0,\, y_0)
+    &\approx A \sigma_{x'_0}\sigma_{y'_0}\sum_i^n
+        \Delta\Theta\left[\exp\left(\frac{(R_i-\Delta R/2)^2}{2}\right)
+                    - \exp\left(\frac{(R_i + \Delta R/2)^2}{2}\right)\right]
+                    I(\sigma_{x'_0} R_i\cos\Theta_i+x'_0,\, \sigma_{y'_0}R_i\sin\Theta_i + y'_0) \\
+    &\approx \sum_i^n W_i\, I(\sigma_{x'_0} R_i \cos\Theta_i + x'_0,\, \sigma_{y'_0}R_i\sin\Theta_i + y'_0)
+
+**[Equation 10]**
+
+Since the weighting factor on each of the bins is known, it is convenient to
+transform $x'$\ -\ $y'$ back to $x$\ -\ $y$ coordinates (by rotating it
+by $-\theta$ around the $z$\ -axis).
+
+Then, for a polar symmetric smear
+
+.. math::
+
+    I_s(x_0,\, y_0) \approx \sum_i^n W_i\,
+        I(x'\cos\theta - y'\sin\theta,\, x'sin\theta + y'\cos\theta)
+
+**[Equation 11]**
+
+where
+
+.. math::
+
+    x' &= \sigma_{x'_0} R_i \cos\Theta_i + x'_0 \\
+    y' &= \sigma_{y'_0} R_i \sin\Theta_i + y'_0 \\
+    x'_0 &= q = \sqrt{x_0^2 + y_0^2} \\
+    y'_0 &= 0
+
+while for a $x$\ -\ $y$ symmetric smear
+
+.. math::
+
+    I_s(x_0,\, y_0) \approx \sum_i^n W_i\, I(x',\, y')
+
+**[Equation 12]**
+
+where
+
+.. math::
+
+    x' &= \sigma_{x'_0} R_i \cos\Theta_i + x'_0 \\
+    y' &= \sigma_{y'_0} R_i \sin\Theta_i + y'_0 \\
+    x'_0 &= x_0 = q_x \\
+    y'_0 &= y_0 = q_y
+
+
+The current version of sasmodels uses Equation 11 for 2D smearing, assuming
+that all the Gaussian weighting functions are aligned in the polar coordinate.
+
+.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+
+Weighting & Normalization
+-------------------------
+
+In all the cases above, the weighting matrix $W$ is calculated on the first
+call to a smearing function, and includes ~60 $q$ values (finely and evenly
+binned) below (>0) and above the $q$ range of data in order to smear all
+data points for a given model and slit/pinhole size. The *Norm* factor is
+found numerically with the weighting matrix and applied on the computation
+of $I_s$.
+
+.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+
+*Document History*
+
+| 2015-05-01 Steve King
+| 2017-05-08 Paul Kienzle
Index: doc/guide/scripting.rst
===================================================================
--- doc/guide/scripting.rst	(revision 2e66ef55022b7fe939fdb5874c2c919d97e01b2c)
+++ doc/guide/scripting.rst	(revision 2e66ef55022b7fe939fdb5874c2c919d97e01b2c)
@@ -0,0 +1,106 @@
+.. _Scripting_Interface:
+
+*******************
+Scripting Interface
+*******************
+
+Need some basic details here of how to load models and data via script, evaluate
+them at given parameter values and run bumps fits.
+
+The key functions are :func:`sasmodels.core.load_model` for loading the
+model definition and compiling the kernel and
+:func:`sasmodels.data.load_data` for calling sasview to load the data. Need
+the data because that defines the resolution function and the q values to
+evaluate. If there is no data, then use :func:`sasmodels.data.empty_data1D`
+or :func:`sasmodels.data.empty_data2D` to create some data with a given $q$.
+
+Using sasmodels through bumps
+=============================
+
+With the data and the model, you can wrap it in a *bumps* model with
+class:`sasmodels.bumps_model.Model` and create an
+class:`sasmodels.bump_model.Experiment` that you can fit with the *bumps*
+interface. Here is an example from the *example* directory such as
+*example/model.py*::
+
+    import sys
+    from bumps.names import *
+    from sasmodels.core import load_model
+    from sasmodels.bumps_model import Model, Experiment
+    from sasmodels.data import load_data, set_beam_stop, set_top
+
+    """ IMPORT THE DATA USED """
+    radial_data = load_data('DEC07267.DAT')
+    set_beam_stop(radial_data, 0.00669, outer=0.025)
+    set_top(radial_data, -.0185)
+
+    kernel = load_model("ellipsoid")
+
+    model = Model(kernel,
+        scale=0.08,
+        radius_polar=15, radius_equatorial=800,
+        sld=.291, sld_solvent=7.105,
+        background=0,
+        theta=90, phi=0,
+        theta_pd=15, theta_pd_n=40, theta_pd_nsigma=3,
+        radius_polar_pd=0.222296, radius_polar_pd_n=1, radius_polar_pd_nsigma=0,
+        radius_equatorial_pd=.000128, radius_equatorial_pd_n=1, radius_equatorial_pd_nsigma=0,
+        phi_pd=0, phi_pd_n=20, phi_pd_nsigma=3,
+        )
+
+    # SET THE FITTING PARAMETERS
+    model.radius_polar.range(15, 1000)
+    model.radius_equatorial.range(15, 1000)
+    model.theta_pd.range(0, 360)
+    model.background.range(0,1000)
+    model.scale.range(0, 10)
+
+    #cutoff = 0     # no cutoff on polydisperisity loops
+    #cutoff = 1e-5  # default cutoff
+    cutoff = 1e-3  # low precision cutoff
+    M = Experiment(data=radial_data, model=model, cutoff=cutoff)
+    problem = FitProblem(M)
+
+Assume that bumps has been installed and the bumps command is available.
+Maybe need to set the path to sasmodels/sasview
+using *PYTHONPATH=path/to/sasmodels:path/to/sasview/src*.
+To run the model use the *bumps* program::
+
+    $ bumps example/model.py --preview
+
+Using sasmodels directly
+========================
+
+Bumps has a notion of parameter boxes in which you can set and retrieve
+values.  Instead of using bumps, you can create a directly callable function
+with :class:`sasmodels.direct_model.DirectModel`.  The resulting object *f*
+will be callable as *f(par=value, ...)*, returning the $I(q)$ for the $q$
+values in the data.  Polydisperse parameters use the same naming conventions
+as in the bumps model, with e.g., radius_pd being the polydispersity associated
+with radius.
+
+Getting a simple function that you can call on a set of q values and return
+a result is not so simple.  Since the time critical use case (fitting) involves
+calling the function over and over with identical $q$ values, we chose to
+optimize the call by only transfering the $q$ values to the GPU once at the
+start of the fit.  We do this by creating a :class:`sasmodels.kernel.Kernel`
+object from the :class:`sasmodels.kernel.KernelModel` returned from
+:func:`sasmodels.core.load_model` using the
+:meth:`sasmodels.kernel.KernelModel.make_kernel` method.  What it actual
+does depends on whether it is running as a DLL, as OpenCL or as a pure
+python kernel.  Once the kernel is in hand, we can then marshal a set of
+parameters into a :class:`sasmodels.details.CallDetails` object and ship it to
+the kernel using the :func:`sansmodels.direct_model.call_kernel` function.  An
+example should help, *example/cylinder_eval.py*::
+
+    from numpy import logspace
+    from matplotlib import pyplot as plt
+    from sasmodels.core import load_model
+    from sasmodels.direct_model import call_kernel
+
+    model = load_model('cylinder')
+    q = logspace(-3, -1, 200)
+    kernel = model.make_kernel([q])
+    Iq = call_kernel(kernel, dict(radius=200.))
+    plt.loglog(q, Iq)
+    plt.show()
Index: doc/guide/sesans/sans_to_sesans.rst
===================================================================
--- doc/guide/sesans/sans_to_sesans.rst	(revision 8ae853293022b5081a1e1a8c26f74eaa2b3f8a13)
+++ doc/guide/sesans/sans_to_sesans.rst	(revision 8ae853293022b5081a1e1a8c26f74eaa2b3f8a13)
@@ -0,0 +1,31 @@
+.. currentmodule:: sasmodels
+.. Wim Bouwman, DUT, written at codecamp-V, Oct2016
+
+.. _SESANS:
+
+SANS to SESANS conversion
+=========================
+
+The conversion from SANS into SESANS in absolute units is a simple Hankel
+transformation when all the small-angle scattered neutrons are detected.
+First we calculate the Hankel transform including the absolute intensities by
+
+.. math:: G(\delta) = 2 \pi \int_0^{\infty} J_0(Q \delta) \frac{d \Sigma}{d \Omega} (Q) Q dQ \!,
+
+in which :math:`J_0` is the zeroth order Bessel function, :math:`\delta`
+the spin-echo length, :math:`Q` the wave vector transfer and :math:`\frac{d \Sigma}{d \Omega} (Q)`
+the scattering cross section in absolute units. This is a 1-dimensional
+integral, which can be rather fast. In the numerical calculation we integrate
+from :math:`Q_{min} = 0.1 \times 2 \pi / R_{max}` in which :math:`R_{max}`
+will be model dependent. We determined the factor 0.1 by varying its value
+until the value of the integral was stable. This happened at a value of 0.3.
+The have a safety margin of a factor of three we have choosen the value 0.1.
+For the solid sphere we took 3 times the radius for :math:`R_{max}`. The real
+integration is performed to :math:`Q_{max}` which is an instrumental parameter
+that is read in from the measurement file. From the equation above we can
+calculate the polarisation that we measure in a SESANS experiment:
+
+.. math:: P(\delta) = e^{t \left( \frac{ \lambda}{2 \pi} \right)^2 \left(G(\delta) - G(0) \right)} \!,
+
+in which :math:`t` is the thickness of the sample and :math:`\lambda` is
+the wavelength of the neutrons.
Index: doc/guide/sesans/sesans_fitting.rst
===================================================================
--- doc/guide/sesans/sesans_fitting.rst	(revision 8ae853293022b5081a1e1a8c26f74eaa2b3f8a13)
+++ doc/guide/sesans/sesans_fitting.rst	(revision 8ae853293022b5081a1e1a8c26f74eaa2b3f8a13)
@@ -0,0 +1,149 @@
+.. currentmodule:: sasmodels
+.. Wim Bouwman, DUT, written at codecamp-V, Oct2016
+
+.. _sesans_fitting:
+
+Fitting SESANS Data
+===================
+
+.. note::
+
+    A proper installation of the developers setup of SasView
+    (http://trac.sasview.org/wiki/AnacondaSetup) is a prerequisite for
+    using these instructions.
+
+It is possible to fit SESANS measurements from the command line in Python.
+
+Simple Fits
+...........
+In the folder sasmodels/example the file sesans_sphere_2micron.py gives
+an example of how to fit a shape to a measurement.
+
+The command::
+
+  >python fit_sesans.py sesans_sphere_2micron.py
+
+then results in a GUI from which you can control the fit.
+
+.. image:: sesans_img/SphereLineFitSasView.png
+
+All the parameters and names in sesans_sphere_2micron.py (shown below) can
+be adjusted to fit your own problem::
+
+  """
+  This is a data file  used to load in sesans data and fit it using the bumps engine
+  """
+  from bumps.names import *
+
+  import sesansfit
+
+  # Enter the model name to use
+  model_name = "sphere"
+
+  # DO NOT MODIFY THIS LINE
+  model = sesansfit.get_bumps_model(model_name)
+
+  # Enter any custom parameters
+  # name = Parameter(initial_value, name='name')
+  phi = Parameter(0.0855, name='phi')
+  # Add the parameters to this list that should be displayed in the fitting window
+  custom_params = {"phi" : phi}
+
+  # SESANS data file name
+  sesans_file = "spheres2micron.ses"
+
+  # Initial parameter values (if other than defaults)
+  # "model_parameter_name" : value
+  initial_vals = {
+    "sld" : 1.41,
+    "radius" : 10000,
+    "sld_solvent" : 2.70,
+  }
+
+  # Ranges for parameters if other than default
+  # "model_parameter_name" : [min, max]
+  param_range = {
+    "phi" : [0.001, 0.5],
+    "radius" : [100, 100000]
+  }
+
+  # Constraints
+  # model.param_name = f(other params)
+  # EXAMPLE: model.scale = model.radius*model.radius*(1 - phi) - where radius
+  # and scale are model functions and phi is a custom parameter
+  model.scale = phi*(1-phi)
+
+  # Send to the fitting engine
+  # DO NOT MODIFY THIS LINE
+  problem = sesansfit.sesans_fit(sesans_file, model, initial_vals, custom_params, param_range)
+
+Incorporating a Structure Factor
+................................
+An example of how to also include a structure factor can be seen in the
+following example taken from Washington et al., *Soft Matter*\, (2014), 10, 3016
+(dx.doi.org/10.1039/C3SM53027B). These are time-of-flight measurements, which
+is the reason that not the polarisation is plotted, but the
+:math:`\frac{log(P/P_0)}{\lambda^2}` . The sample is a dispersion of
+core-shell colloids at a high volume fraction with hard sphere interactions.
+
+The fit can be started by::
+
+ >python fit_sesans.py sesans_parameters_css-hs.py
+
+This yields after the fitting:
+
+.. image:: sesans_img/HardSphereLineFitSasView.png
+
+The code sesans_parameters_css-hs.py can then be used as a template for a
+fitting problem with a structure factor::
+
+ """
+ This is a data file  used to load in sesans data and fit it using the bumps engine
+ """
+ from bumps.names import *
+
+ import sesansfit
+
+ # Enter the model name to use
+ model_name = "core_shell_sphere*hardsphere"
+
+ # DO NOT MODIFY THIS LINE
+ model = sesansfit.get_bumps_model(model_name)
+
+ # Enter any custom parameters
+ phi = Parameter(0.45, name='phi')
+ pen = Parameter(0.95, name='solvent penetration')
+ custom_params = {"phi" : phi, "pen" : pen}
+
+ # SESANS data file
+ sesans_file = "core_shell.ses"
+
+ # Initial parameter values (if other than defaults)
+ initial_vals = {
+    "sld_core" : 1.05,
+    "sld_shell" : 2.88*pen-0.05*(1-pen),
+    "sld_solvent" : 2.88,
+    "radius" : 730,
+    "thickness" : 20,
+    "volfraction" : phi,
+    "scale" : (1-phi)
+ }
+
+ # Ranges for parameters if other than default
+ param_range = {
+    "phi" : [0.2, 0.5],
+    "pen" : [0,1],
+    "radius" : [500, 3000],
+    "thickness" : [0,200]
+ }
+
+ # Constraints
+ # model.param_name = f(other params)
+ # EXAMPLE: model.scale = model.radius*model.radius*(1 - phi) - where radius
+ # and scale are model functions and phi is a custom parameter
+ model.scale = phi*(1-phi)
+ model.volfraction = phi
+ model.shell_sld = pen*2.88
+
+ # Send to the fitting engine
+ problem = sesansfit.sesans_fit(sesans_file, model_name, initial_vals, custom_params, param_range)
Index: doc/index.rst
===================================================================
--- doc/index.rst	(revision 5e1d6b03bc600b110bbfd643b1751800e2c02a9e)
+++ doc/index.rst	(revision 8ae853293022b5081a1e1a8c26f74eaa2b3f8a13)
@@ -1,6 +1,18 @@
-Introduction
-============
+sasmodels
+=========
+Small angle X-ray and Neutron scattering (SAXS and SANS) examines the
+scattering patterns produced by a beam travelling through the sample
+and scattering at low angles.  The scattering is computed as a function
+of reciprocal space $q$, which arises from a combination of beam wavelength
+and scattering angles. Each pixel on the detector corresponds to
+a different scattering angle, and has a distinct $q_x$ and $q_y$. If the
+sample is unoriented, the scattering pattern will appear as rings on the
+detector.  In this case, a circular average can be taken with 1-dimension
+data at $q = \surd (q_x^2 + q_y^2)$ compared to the orientationally
+averaged SAS scattering pattern.
+
 The sasmodels package provides theory functions for small angle scattering
-calculations.
+calculations for different shapes, including the effects of resolution,
+polydispersity and orientational dispersion.
 
 .. htmlonly::
@@ -15,7 +27,6 @@
 
    guide/index.rst
+   guide/models/index.rst
    developer/index.rst
-   ref/index.rst
-   ref/models/index.rst
    api/index.rst
 
@@ -28,8 +39,2 @@
 .. htmlonly::
   * :ref:`search`
-
-
-
-
-  
-
Index: c/ref/gpu/gpu_computations.rst
===================================================================
--- doc/ref/gpu/gpu_computations.rst	(revision 7e74ed57a91063de083ff962e2ec8b458e004a4e)
+++ 	(revision )
@@ -1,71 +1,0 @@
-.. _models-computation:
-
-****************
-GPU Computations
-****************
-SasView model evaluations can run on your graphics card (GPU) or they can run
-on the processor (CPU). In general, calculations performed on the GPU will run faster.
-
-To run on the GPU, your computer must have OpenCL drivers installed.
-For information about OpenCL installation see this
-:ref:`opencl-installation` guidance.
-
-Where the model is evaluated is a little bit complicated.
-If the model has the line *single=False* then it requires double precision.
-If the GPU is single precision only, then it will try running via OpenCL
-on the CPU.  If the OpenCL driver is not available for the CPU then
-it will run as a normal program on the CPU.
-
-For models with a large number of parameters or with a lot of code,
-the GPU may be too small to run the program effectively.
-In this case, you should try simplifying the model, maybe breaking it
-into several different modules so that you don't need *IF* statements in your code.
-If it is still too big, you can set *opencl=False* in the model file and
-the model will only run as a normal program on the CPU.
-This will not usually be necessary.
-
-Device Selection
-................
-If you have multiple GPU devices you can tell SasView which device to use.
-By default, SasView looks for one GPU and one CPU device
-from available OpenCL platforms.
-
-OpenCL devices can be set from OpenCL options dialog in Fitting menu or as
-enviromental variables.
-
-**If you don't want to use OpenCL, you can select "No OpenCL" option from**
-**GUI dialog or set *SAS_OPENCL=None* in your environment settings**
-**This will only use normal programs.**
-
-SasView prefers AMD or NVIDIA drivers for GPU, and prefers Intel or
-Apple drivers for CPU. Both GPU and CPU are included on the assumption that CPU 
-is always available and supports double precision.
-
-The device order is important: GPU is checked before CPU on the assumption that
-it will be faster. By examining ~/sasview.log you can see which device SasView
-chose to run the model.
-
-If you want to use one of the other devices, you can select it from OpenCL
-options dialog (accessible from Fitting menu) or run the following from
-the python console in SasView::
-
-    import pyopencl as cl
-    cl.create_some_context()
-
-This will provide a menu of different OpenCL drivers available.
-When one is selected, it will say "set PYOPENCL_CTX=..."
-Use that value as the value of *SAS_OPENCL*.
-
-Compiler Selection
-..................
-For models run as normal programs, you may need to specify a compiler.
-This is done using the SAS_COMPILER environment variable.
-Set it to *tinycc* for the tinycc compiler, *msvc* for the
-Microsoft Visual C compiler, or *mingw* for the MinGW compiler.
-TinyCC is provided with SasView so that is the default.
-If you want one of the other compilers, be sure to have it available
-in your *PATH* so SasView can find it!
-
-
-.. note::
-    This help document was last changed by Steve King, 08Oct2016
Index: c/ref/gpu/opencl_installation.rst
===================================================================
--- doc/ref/gpu/opencl_installation.rst	(revision ec8b9a3e2841d6f1ececef27cda299f684cf8285)
+++ 	(revision )
@@ -1,59 +1,0 @@
-.. _opencl-installation:
-
-*******************
-OpenCL Installation
-*******************
-*Warning! GPU devices do not in general offer the same level of memory protection as CPU devices. If your code attempts to write outside allocated memory buffers unpredicatable behaviour may result (eg, your video display may freeze, or your system may crash, etc). Do not install OpenCL drivers without first checking for known issues (eg, some computer manufacturers install modified graphics drivers so replacing these may not be a good idea!). If in doubt, seek advice from an IT professional before proceeding further.*
-
-1. Check if you have OpenCL already installed
-=============================================
-
-Windows
-.......
-    The following instructions are based on
-    http://web.engr.oregonstate.edu/~mjb/cs475/DoIHaveOpenCL.pdf
-
-    * Go to: Start -> Control Panel -> System & Security -> Administrative Tools
-    * Double Click on Computer Managment
-    * Click on Device Manager
-    * Click open Display Adapters
-    * Right-click on available adapter and select Properties
-    * Click on Driver
-    * Go to Driver Details
-    * Scroll down and see if OpenCL is installed (look for OpenCL*.dll files)
-
-Mac OSX
-.......
-    For OS X operating systems higher than 10.6 OpenCL is shipped along with the system.
-
-    However, OpenCL has had a rocky history on Macs. Apple provide a useful compatibility table at https://support.apple.com/en-us/HT202823
-
-
-2. Installation
-===============
-
-Windows
-.......
-    Depending on the graphic card in your system, drivers
-    can be obtained from different sources:
-
-    * NVIDIA: https://developer.nvidia.com/opencl
-    * AMD: http://developer.amd.com/tools-and-sdks/opencl-zone/
-
-Mac OSX
-.......
-    N/A
-	
-	You cannot download OpenCL driver updates for your Mac. They are packaged with the normal quarterly OS X updates from Apple. 
-
-
-.. note::
-    Intel provides OpenCL drivers for Intel processors at     https://software.intel.com/en-us/articles/opencl-drivers 
-    These can sometimes make use of special vector instructions across multiple
-    processors, so it is worth installing if the GPU does not support double
-    precision. You can install this driver alongside the GPU driver for NVIDIA
-    or AMD.
-
-	
-.. note::
-    This help document was last changed by Steve King, 08Oct2016
Index: c/ref/index.rst
===================================================================
--- doc/ref/index.rst	(revision 9f12fbed66bab9196fec52997bd80899d65bc9a2)
+++ 	(revision )
@@ -1,16 +1,0 @@
-*******************
-SAS Model Reference
-*******************
-
-.. toctree::
-   :numbered: 4
-   :maxdepth: 4
-
-   intro.rst
-   refs.rst
-   gpu/gpu_computations.rst
-   gpu/opencl_installation.rst
-   magnetism/magnetism.rst
-   sesans/sans_to_sesans.rst
-   sesans/sesans_fitting.rst
-   
Index: c/ref/intro.rst
===================================================================
--- doc/ref/intro.rst	(revision 9f60c06d85ba919d831dd8784f26618e41931862)
+++ 	(revision )
@@ -1,47 +1,0 @@
-
-.. _models-intro:
-
-************
-Introduction
-************
-
-Many of our models use the form factor calculations implemented in a c-library provided by the NIST Center for Neutron
-Research and thus some content and figures in this document are originated from or shared with the NIST SANS Igor-based
-analysis package.
-
-This software provides form factors for various particle shapes. After giving a mathematical definition of each model,
-we show the list of parameters available to the user. Validation plots for each model are also presented.
-
-Instructions on how to use SasView itself are available separately.
-
-To easily compare to the scattering intensity measured in experiments, we normalize the form factors by the volume of
-the particle
-
-.. math::
-
-    P(\vec q) = \frac{P_o(\vec q)}{V} = \frac{1}{V} F(\vec q) F^*(\vec q)
-
-with
-
-    F(\vec q) = \int\int\int dV\rho(\vec r) e^{-i\vec q \cdot \vec r}
-
-where $P_0(\vec q)$ is the un-normalized form factor, $\rho(\vec r)$ is the scattering length density at a given
-point in space and the integration is done over the volume $V$ of the scatterer.
-
-For systems without inter-particle interference, the form factors we provide can be related to the scattering intensity
-by the particle volume fraction
-
-.. math::
-
-    I(\vec q) = \Phi P(\vec q)
-
-Our so-called 1D scattering intensity functions provide $P(Q)$ for the case where the scatterer is randomly oriented. In
-that case, the scattering intensity only depends on the length of $Q$ . The intensity measured on the plane of the SAS
-detector will have an azimuthal symmetry around $Q=0$.
-
-Our so-called 2D scattering intensity functions provide $P(Q,\phi)$ for an oriented system as a function of a
-$q$ vector in the plane of the detector. We define the angle $\phi$ as the angle between the $q$ vector and the horizontal
-($x$) axis of the plane of the detector.
-
-For information about polarised and magnetic scattering, see :ref:`magnetism`.
-
Index: c/ref/magnetism/magnetism.rst
===================================================================
--- doc/ref/magnetism/magnetism.rst	(revision deb854fa9e01c28c36f231466b343bb667d4e687)
+++ 	(revision )
@@ -1,99 +1,0 @@
-.. _magnetism:
-
-Polarisation/Magnetic Scattering
-=======================================================
-
-In earlier versions of SasView magnetic scattering was implemented in just five 
-(2D) models
-
-*  :ref:`sphere`
-*  :ref:`core-shell-sphere`
-*  :ref:`core-multi-shell`
-*  :ref:`cylinder`
-*  :ref:`parallelepiped`
-
-From SasView 4.x it is implemented on most models in the 'shape' category.
-
-In general, the scattering length density (SLD = $\beta$) in each region where the
-SLD is uniform, is a combination of the nuclear and magnetic SLDs and, for polarised
-neutrons, also depends on the spin states of the neutrons.
-
-For magnetic scattering, only the magnetization component $\mathbf{M_\perp}$
-perpendicular to the scattering vector $\mathbf{Q}$ contributes to the magnetic
-scattering length.
-
-
-.. figure::
-    mag_img/mag_vector.bmp
-
-The magnetic scattering length density is then
-
-.. math::
-    \beta_M = \dfrac{\gamma r_0}{2\mu_B}\sigma \cdot
-    \mathbf{M_\perp} = D_M\sigma \cdot \mathbf{M_\perp}
-
-where $\gamma = -1.913$ is the gyromagnetic ratio, $\mu_B$ is the
-Bohr magneton, $r_0$ is the classical radius of electron, and $\sigma$
-is the Pauli spin.
-
-Assuming that incident neutrons are polarized parallel (+) and anti-parallel (-)
-to the $x'$ axis, the possible spin states after the sample are then
-
-No spin-flips (+ +) and (- -)
-
-Spin-flips    (+ -) and (- +)
-
-.. figure::
-    mag_img/M_angles_pic.bmp
-
-If the angles of the $Q$ vector and the spin-axis $x'$ to the $x$ - axis are
-$\phi$ and $\theta_{up}$, respectively, then, depending on the spin state of the
-neutrons, the scattering length densities, including the nuclear scattering
-length density ($\beta{_N}$) are
-
-.. math::
-    \beta_{\pm\pm} =  \beta_N \mp D_M M_{\perp x'}
-    \text{ when there are no spin-flips}
-
-and
-
-.. math::
-    \beta_{\pm\mp} =  -D_M (M_{\perp y'} \pm iM_{\perp z'})
-    \text{ when there are}
-
-where
-
-.. math::
-    M_{\perp x'} = M_{0q_x}\cos(\theta_{up})+M_{0q_y}\sin(\theta_{up}) \\
-    M_{\perp y'} = M_{0q_y}\cos(\theta_{up})-M_{0q_x}\sin(\theta_{up}) \\
-    M_{\perp z'} = M_{0z} \\
-    M_{0q_x} = (M_{0x}\cos\phi - M_{0y}\sin\phi)\cos\phi \\
-    M_{0q_y} = (M_{0y}\sin\phi - M_{0x}\cos\phi)\sin\phi
-
-Here, $M_{0x}$, $M_{0x}$, $M_{0z}$ are the x, y and z components
-of the magnetization vector given in the laboratory xyz frame given by
-
-.. math::
-    M_{0x} = M_0\cos\theta_M\cos\phi_M \\
-    M_{0y} = M_0\sin\theta_M \\
-    M_{0z} = -M_0\cos\theta_M\sin\phi_M
-
-and the magnetization angles $\theta_M$ and $\phi_M$ are defined in
-the figure above.
-
-The user input parameters are:
-
-===========   ================================================================
- M0_sld        = $D_M M_0$
- Up_theta      = $\theta_{up}$
- M_theta       = $\theta_M$
- M_phi         = $\phi_M$
- Up_frac_i     = (spin up)/(spin up + spin down) neutrons *before* the sample
- Up_frac_f     = (spin up)/(spin up + spin down) neutrons *after* the sample
-===========   ================================================================
-
-.. note::
-    The values of the 'Up_frac_i' and 'Up_frac_f' must be in the range 0 to 1.
-
-.. note::
-    This help document was last changed by Steve King, 02May2015
Index: c/ref/refs.rst
===================================================================
--- doc/ref/refs.rst	(revision 61ba6233ec36e842d625c589deec77f689b2a9b6)
+++ 	(revision )
@@ -1,35 +1,0 @@
-.. _models-refs:
-
-**********
-References
-**********
-
-*Small-Angle Scattering of X-Rays*
-A Guinier and G Fournet
-John Wiley & Sons, New York (1955)
-
-P Stckel, R May, I Strell, Z Cejka, W Hoppe, H Heumann, W Zillig and H Crespi
-*Eur. J. Biochem.*, 112, (1980), 411-417
-
-G Porod
-in *Small Angle X-ray Scattering*
-(editors) O Glatter and O Kratky
-Academic Press (1982)
-
-*Structure Analysis by Small-Angle X-Ray and Neutron Scattering*
-L.A Feigin and D I Svergun
-Plenum Press, New York (1987)
-
-S Hansen
-*J. Appl. Cryst.* 23, (1990), 344-346
-
-S J Henderson
-*Biophys. J.* 70, (1996), 1618-1627
-
-B C McAlister and B P Grady
-*J. Appl. Cryst.* 31, (1998), 594-599
-
-S R Kline
-*J Appl. Cryst.* 39(6), (2006), 895
-
-**Also see the references at the end of the each model function descriptions.**
Index: c/ref/sesans/sans_to_sesans.rst
===================================================================
--- doc/ref/sesans/sans_to_sesans.rst	(revision 3330bb44faf647c84e605c5a75bed3f385a25a52)
+++ 	(revision )
@@ -1,26 +1,0 @@
-.. currentmodule:: sasmodels
-.. Wim Bouwman, DUT, written at codecamp-V, Oct2016
-
-.. _SESANS:
-
-SANS to SESANS conversion
-=========================
-
-The conversion from SANS into SESANS in absolute units is a simple Hankel transformation when all the small-angle scattered neutrons are detected.
-First we calculate the Hankel transform including the absolute intensities by
-
-.. math:: G(\delta) = 2 \pi \int_0^{\infty} J_0(Q \delta) \frac{d \Sigma}{d \Omega} (Q) Q dQ \!,
-
-in which :math:`J_0` is the zeroth order Bessel function, :math:`\delta` the spin-echo length, :math:`Q` the wave vector transfer
-and :math:`\frac{d \Sigma}{d \Omega} (Q)` the scattering cross section in absolute units.
-This is a 1-dimensional integral, which can be rather fast.
-In the numerical calculation we integrate from :math:`Q_{min} = 0.1 \times 2 \pi / R_{max}` in which :math:`R_{max}` will be model dependent.
-We determined the factor 0.1 by varying its value until the value of the integral was stable.
-This happened at a value of 0.3.  The have a safety margin of a factor of three we have choosen the value 0.1.
-For the solid sphere we took 3 times the radius for :math:`R_{max}`.
-The real integration is performed to :math:`Q_{max}` which is an instrumental parameter that is read in from the measurement file.
-From the equation above we can calculate the polarisation that we measure in a SESANS experiment:
-
-.. math:: P(\delta) = e^{t \left( \frac{ \lambda}{2 \pi} \right)^2 \left(G(\delta) - G(0) \right)} \!,
-
-in which :math:`t` is the thickness of the sample and :math:`\lambda` is the wavelength of the neutrons.
Index: c/ref/sesans/sesans_fitting.rst
===================================================================
--- doc/ref/sesans/sesans_fitting.rst	(revision 3330bb44faf647c84e605c5a75bed3f385a25a52)
+++ 	(revision )
@@ -1,140 +1,0 @@
-.. currentmodule:: sasmodels
-.. Wim Bouwman, DUT, written at codecamp-V, Oct2016
-
-.. _sesans_fitting:
-
-Fitting SESANS Data
-===================
-
-.. note:: A proper installation of the developers setup of SasView (http://trac.sasview.org/wiki/AnacondaSetup) is a prerequisite for using these instructions.
-
-It is possible to fit SESANS measurements from the command line in Python.
-
-Simple Fits
-...........
-In the folder sasmodels/example the file sesans_sphere_2micron.py gives an example of how to fit a shape to a measurement.
-
-The command::
-
-  >python fit_sesans.py sesans_sphere_2micron.py
-
-then results in a GUI from which you can control the fit.
-
-.. image:: sesans_img/SphereLineFitSasView.png
-
-All the parameters and names in sesans_sphere_2micron.py (shown below) can be adjusted to fit your own problem::
-
-  """
-  This is a data file  used to load in sesans data and fit it using the bumps engine
-  """
-  from bumps.names import *
-
-  import sesansfit
-
-  # Enter the model name to use
-  model_name = "sphere"
-
-  # DO NOT MODIFY THIS LINE
-  model = sesansfit.get_bumps_model(model_name)
-
-  # Enter any custom parameters
-  # name = Parameter(initial_value, name='name')
-  phi = Parameter(0.0855, name='phi')
-  # Add the parameters to this list that should be displayed in the fitting window
-  custom_params = {"phi" : phi}
-
-  # SESANS data file name
-  sesans_file = "spheres2micron.ses"
-
-  # Initial parameter values (if other than defaults)
-  # "model_parameter_name" : value
-  initial_vals = {
-    "sld" : 1.41,
-    "radius" : 10000,
-    "sld_solvent" : 2.70,
-  }
-
-  # Ranges for parameters if other than default
-  # "model_parameter_name" : [min, max]
-  param_range = {
-    "phi" : [0.001, 0.5],
-    "radius" : [100, 100000]
-  }
-
-  # Constraints
-  # model.param_name = f(other params)
-  # EXAMPLE: model.scale = model.radius*model.radius*(1 - phi) - where radius and scale are model functions and phi is
-  # a custom parameter
-  model.scale = phi*(1-phi)
-
-  # Send to the fitting engine
-  # DO NOT MODIFY THIS LINE
-  problem = sesansfit.sesans_fit(sesans_file, model, initial_vals, custom_params, param_range)
-
-Incorporating a Structure Factor
-................................
-An example of how to also include a structure factor can be seen in the following example taken from Washington et al., 
-*Soft Matter*\, (2014), 10, 3016 (dx.doi.org/10.1039/C3SM53027B). These are time-of-flight measurements, which is the 
-reason that not the polarisation is plotted, but the :math:`\frac{log(P/P_0)}{\lambda^2}` . The sample is a dispersion 
-of core-shell colloids at a high volume fraction with hard sphere interactions.
-
-The fit can be started by::
-
- >python fit_sesans.py sesans_parameters_css-hs.py
-
-This yields after the fitting:
-
-.. image:: sesans_img/HardSphereLineFitSasView.png
-
-The code sesans_parameters_css-hs.py can then be used as a template for a fitting problem with a structure factor::
-
- """
- This is a data file  used to load in sesans data and fit it using the bumps engine
- """
- from bumps.names import *
-
- import sesansfit
-
- # Enter the model name to use
- model_name = "core_shell_sphere*hardsphere"
-
- # DO NOT MODIFY THIS LINE
- model = sesansfit.get_bumps_model(model_name)
-
- # Enter any custom parameters
- phi = Parameter(0.45, name='phi')
- pen = Parameter(0.95, name='solvent penetration')
- custom_params = {"phi" : phi, "pen" : pen}
-
- # SESANS data file
- sesans_file = "core_shell.ses"
-
- # Initial parameter values (if other than defaults)
- initial_vals = {
-    "sld_core" : 1.05,
-    "sld_shell" : 2.88*pen-0.05*(1-pen),
-    "sld_solvent" : 2.88,
-    "radius" : 730,
-    "thickness" : 20,
-    "volfraction" : phi,
-    "scale" : (1-phi)
- }
-
- # Ranges for parameters if other than default
- param_range = {
-    "phi" : [0.2, 0.5],
-    "pen" : [0,1],
-    "radius" : [500, 3000],
-    "thickness" : [0,200]
- }
-
- # Constraints
- # model.param_name = f(other params)
- # EXAMPLE: model.scale = model.radius*model.radius*(1 - phi) - where radius and scale are model functions and phi is
- # a custom parameter
- model.scale = phi*(1-phi)
- model.volfraction = phi
- model.shell_sld = pen*2.88
-
- # Send to the fitting engine
- problem = sesansfit.sesans_fit(sesans_file, model_name, initial_vals, custom_params, param_range)
Index: example/cylinder_eval.py
===================================================================
--- example/cylinder_eval.py	(revision 2e66ef55022b7fe939fdb5874c2c919d97e01b2c)
+++ example/cylinder_eval.py	(revision 2e66ef55022b7fe939fdb5874c2c919d97e01b2c)
@@ -0,0 +1,18 @@
+"""
+Minimal example of calling a kernel for a specific set of q values.
+"""
+
+from numpy import logspace
+from matplotlib import pyplot as plt
+from sasmodels.core import load_model
+from sasmodels.direct_model import call_kernel
+
+model = load_model('cylinder')
+q = logspace(-3, -1, 200)
+kernel = model.make_kernel([q])
+Iq = call_kernel(kernel, dict(radius=200.))
+plt.loglog(q, Iq)
+plt.xlabel('q (1/A)')
+plt.ylabel('I(q)')
+plt.title('Cylinder with radius 200.')
+plt.show()
Index: example/model.py
===================================================================
--- example/model.py	(revision 1182da5952c5f1fedd003e65e6b154df780d0afb)
+++ example/model.py	(revision 2e66ef55022b7fe939fdb5874c2c919d97e01b2c)
@@ -17,17 +17,17 @@
 model = Model(kernel,
     scale=0.08,
-    r_polar=15, r_equatorial=800,
+    radius_polar=15, radius_equatorial=800,
     sld=.291, sld_solvent=7.105,
     background=0,
     theta=90, phi=0,
     theta_pd=15, theta_pd_n=40, theta_pd_nsigma=3,
-    r_polar_pd=0.222296, r_polar_pd_n=1, r_polar_pd_nsigma=0,
-    r_equatorial_pd=.000128, r_equatorial_pd_n=1, r_equatorial_pd_nsigma=0,
+    radius_polar_pd=0.222296, radius_polar_pd_n=1, radius_polar_pd_nsigma=0,
+    radius_equatorial_pd=.000128, radius_equatorial_pd_n=1, radius_equatorial_pd_nsigma=0,
     phi_pd=0, phi_pd_n=20, phi_pd_nsigma=3,
     )
 
 # SET THE FITTING PARAMETERS
-model.r_polar.range(15, 1000)
-model.r_equatorial.range(15, 1000)
+model.radius_polar.range(15, 1000)
+model.radius_equatorial.range(15, 1000)
 model.theta_pd.range(0, 360)
 model.background.range(0,1000)
Index: sasmodels/core.py
===================================================================
--- sasmodels/core.py	(revision 650c6d2665bcebbe07614117e6b9841191a18ea2)
+++ sasmodels/core.py	(revision 2e66ef55022b7fe939fdb5874c2c919d97e01b2c)
@@ -117,6 +117,8 @@
     Load model info and build model.
 
-    *model_name* is the name of the model as used by :func:`load_model_info`.
-    Additional keyword arguments are passed directly to :func:`build_model`.
+    *model_name* is the name of the model, or perhaps a model expression
+    such as sphere*hardsphere or sphere+cylinder.
+
+    *dtype* and *platform* are given by :func:`build_model`.
     """
     return build_model(load_model_info(model_name),
@@ -128,4 +130,7 @@
     """
     Load a model definition given the model name.
+
+    *model_name* is the name of the model, or perhaps a model expression
+    such as sphere*hardsphere or sphere+cylinder.
 
     This returns a handle to the module defining the model.  This can be
@@ -227,6 +232,17 @@
 
     Possible types include 'half', 'single', 'double' and 'quad'.  If the
-    type is 'fast', then this is equivalent to dtype 'single' with the
-    fast flag set to True.
+    type is 'fast', then this is equivalent to dtype 'single' but using
+    fast native functions rather than those with the precision level guaranteed
+    by the OpenCL standard.
+
+    Platform preference can be specfied ("ocl" vs "dll"), with the default
+    being OpenCL if it is availabe.  If the dtype name ends with '!' then
+    platform is forced to be DLL rather than OpenCL.
+
+    This routine ignores the preferences within the model definition.  This
+    is by design.  It allows us to test models in single precision even when
+    we have flagged them as requiring double precision so we can easily check
+    the performance on different platforms without having to change the model
+    definition.
     """
     # Assign default platform, overriding ocl with dll if OpenCL is unavailable
Index: sasmodels/resolution.py
===================================================================
--- sasmodels/resolution.py	(revision b32caaba897db3d9a33220584b9dca61f82df589)
+++ sasmodels/resolution.py	(revision 990d8dfe5ac399564bc0bb3b873c5a1b56d4e573)
@@ -437,5 +437,5 @@
     .. math::
 
-         \log \Delta q = (\log q_n - log q_1) / (n - 1)
+         \log \Delta q = (\log q_n - \log q_1) / (n - 1)
 
     From this we can compute the number of steps required to extend $q$
@@ -451,5 +451,5 @@
 
          n_\text{extend} = (n-1) (\log q_\text{max} - \log q_n)
-            / (\log q_n - log q_1)
+            / (\log q_n - \log q_1)
     """
     q = np.sort(q)
@@ -459,5 +459,6 @@
         log_delta_q = log(10.) / points_per_decade
     if q_min < q[0]:
-        if q_min < 0: q_min = q[0]*MINIMUM_ABSOLUTE_Q
+        if q_min < 0:
+            q_min = q[0]*MINIMUM_ABSOLUTE_Q
         n_low = log_delta_q * (log(q[0])-log(q_min))
         q_low = np.logspace(log10(q_min), log10(q[0]), np.ceil(n_low)+1)[:-1]
Index: sasmodels/rst2html.py
===================================================================
--- sasmodels/rst2html.py	(revision f2f54137cf0be59060fcf77f0a416d0fce0de7ac)
+++ sasmodels/rst2html.py	(revision 990d8dfe5ac399564bc0bb3b873c5a1b56d4e573)
@@ -38,5 +38,5 @@
     - mathml
     - mathjax
-    See `http://docutils.sourceforge.net/docs/user/config.html#math-output`_
+    See `<http://docutils.sourceforge.net/docs/user/config.html#math-output>`_
     for details.
 
@@ -211,7 +211,27 @@
     sys.exit(app.exec_())
 
+def can_use_qt():
+    """
+    Return True if QWebView exists.
+
+    Checks first in PyQt5 then in PyQt4
+    """
+    try:
+        from PyQt5.QtWebKitWidgets import QWebView
+        return True
+    except ImportError:
+        try:
+            from PyQt4.QtWebkit import QWebView
+            return True
+        except ImportError:
+            return False
+
 def view_help(filename, qt=False):
     import os
-    url="file:///"+os.path.abspath(filename).replace("\\","/")
+
+    if qt:
+        qt = can_use_qt()
+
+    url = "file:///"+os.path.abspath(filename).replace("\\", "/")
     if filename.endswith('.rst'):
         html = load_rst_as_html(filename)
