source: sasview/src/sas/sasgui/perspectives/fitting/media/plugin.rst @ b2a3814

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since b2a3814 was b2a3814, checked in by smk78, 5 years ago

Added note about how to view code blocks that might be cropped in the
default window size.

  • Property mode set to 100644
File size: 30.1 KB
RevLine 
[05829fb]1.. _Writing_a_Plugin:
2
[7f23423]3Writing a Plugin Model
4======================
[05829fb]5
[b2a3814]6.. note:: If some code blocks are not readable, expand the documentation window
7
[7f23423]8Overview
9^^^^^^^^
10
11You can write your own model and save it to the the SasView
[05829fb]12*plugin_models* folder
13
[7f23423]14  *C:\\Users\\[username]\\.sasview\\plugin_models* (on Windows)
[05829fb]15
16The next time SasView is started it will compile the plugin and add
[7f23423]17it to the list of *Customized Models* in a FitPage.  It is recommended that an
[05829fb]18existing model be used as a template.
19
20SasView has three ways of writing models:
21
22- As a pure python model : Example -
23  `broadpeak.py <https://github.com/SasView/sasmodels/blob/master/sasmodels/models/broad_peak.py>`_
24- As a python model with embedded C : Example -
25  `sphere.py <https://github.com/SasView/sasmodels/blob/master/sasmodels/models/sphere.py>`_
26- As a python wrapper with separate C code : Example -
27  `cylinder.py <https://github.com/SasView/sasmodels/blob/master/sasmodels/models/cylinder.py>`_,
28  `cylinder.c <https://github.com/SasView/sasmodels/blob/master/sasmodels/models/cylinder.c>`_
29
[3d164b9]30The built-in modules are available in the *sasmodels-data\\models* subdirectory
[7f23423]31of your SasView installation folder.  On Windows, this will be something like
32*C:\\Program Files (x86)\\SasView\\sasmodels-data\\models*.  On Mac OSX, these will be within
[05829fb]33the application bundle as
34*/Applications/SasView 4.0.app/Contents/Resources/sasmodels-data/models*.
35
[7f23423]36Other models are available for download from our
37`Model Marketplace <http://marketplace.sasview.org/>`_. You can contribute your own models to the
38Marketplace aswell.
39
[05829fb]40Create New Model Files
41^^^^^^^^^^^^^^^^^^^^^^
42
[3d164b9]43In the *~\\.sasview\\plugin_models* directory, copy the appropriate files
[05829fb]44(using the examples above as templates) to mymodel.py (and mymodel.c, etc)
45as required, where "mymodel" is the name for the model you are creating.
46
47*Please follow these naming rules:*
48
[7f23423]49- No capitalization and thus no CamelCase
[3d164b9]50- If necessary use underscore to separate words (i.e. barbell not BarBell or
[05829fb]51  broad_peak not BroadPeak)
[cbbb6a4]52- Do not include “modelâ€ᅵ in the name (i.e. barbell not BarBellModel)
[05829fb]53
54
55Edit New Model Files
56^^^^^^^^^^^^^^^^^^^^
57
[7f23423]58Model Contents
59..............
60
[05829fb]61The model interface definition is in the .py file.  This file contains:
62
63- a **model name**:
64   - this is the **name** string in the *.py* file
65   - titles should be:
66
67    - all in *lower* case
68    - without spaces (use underscores to separate words instead)
69    - without any capitalization or CamelCase
[7f23423]70    - without incorporating the word "model"
[05829fb]71    - examples: *barbell* **not** *BarBell*; *broad_peak* **not** *BroadPeak*;
72      *barbell* **not** *BarBellModel*
73
74- a **model title**:
75   - this is the **title** string in the *.py* file
76   - this is a one or two line description of the model, which will appear
[7f23423]77     at the start of the model documentation and as a tooltip in the SasView GUI
[05829fb]78
79- a **short discription**:
80   - this is the **description** string in the *.py* file
81   - this is a medium length description which appears when you click
[7f23423]82     *Description* on the model FitPage
[05829fb]83
84- a **parameter table**:
85   - this will be auto-generated from the *parameters* in the *.py* file
86
87- a **long description**:
88   - this is ReStructuredText enclosed between the r""" and """ delimiters
89     at the top of the *.py* file
[7f23423]90   - what you write here is abstracted into the SasView help documentation
91   - this is what other users will refer to when they want to know what your model does;
92     so please be helpful!
[05829fb]93
94- a **definition** of the model:
95   - as part of the **long description**
96
97- a **formula** defining the function the model calculates:
98   - as part of the **long description**
99
100- an **explanation of the parameters**:
101   - as part of the **long description**
102   - explaining how the symbols in the formula map to the model parameters
103
104- a **plot** of the function, with a **figure caption**:
[7f23423]105   - this is automatically generated from your default parameters
[05829fb]106
107- at least one **reference**:
108   - as part of the **long description**
109   - specifying where the reader can obtain more information about the model
110
111- the **name of the author**
112   - as part of the **long description**
113   - the *.py* file should also contain a comment identifying *who*
114     converted/created the model file
115
[3d164b9]116Models that do not conform to these requirements will *never* be incorporated
117into the built-in library.
118
[05829fb]119More complete documentation for the sasmodels package can be found at
120`<http://www.sasview.org/sasmodels>`_. In particular,
121`<http://www.sasview.org/sasmodels/api/generate.html#module-sasmodels.generate>`_
122describes the structure of a model.
123
124
125Model Documentation
126...................
127
128The *.py* file starts with an r (for raw) and three sets of quotes
129to start the doc string and ends with a second set of three quotes.
130For example::
131
132    r"""
133    Definition
134    ----------
135
136    The 1D scattering intensity of the sphere is calculated in the following
137    way (Guinier, 1955)
138
139    .. math::
140
141        I(q) = \frac{\text{scale}}{V} \cdot \left[
142            3V(\Delta\rho) \cdot \frac{\sin(qr) - qr\cos(qr))}{(qr)^3}
143            \right]^2 + \text{background}
144
145    where *scale* is a volume fraction, $V$ is the volume of the scatterer,
146    $r$ is the radius of the sphere and *background* is the background level.
147    *sld* and *sld_solvent* are the scattering length densities (SLDs) of the
148    scatterer and the solvent respectively, whose difference is $\Delta\rho$.
149
150    You can included figures in your documentation, as in the following
151    figure for the cylinder model.
152
153    .. figure:: img/cylinder_angle_definition.jpg
154
155        Definition of the angles for oriented cylinders.
156
157    References
158    ----------
159
160    A Guinier, G Fournet, *Small-Angle Scattering of X-Rays*,
161    John Wiley and Sons, New York, (1955)
162    """
163
164This is where the FULL documentation for the model goes (to be picked up by
165the automatic documentation system).  Although it feels odd, you
166should start the documentation immediately with the **definition**---the model
167name, a brief description and the parameter table are automatically inserted
168above the definition, and the a plot of the model is automatically inserted
169before the **reference**.
170
171Figures can be included using the *figure* command, with the name
172of the *.png* file containing the figure and a caption to appear below the
173figure.  Figure numbers will be added automatically.
174
175See this `Sphinx cheat sheet <http://matplotlib.org/sampledoc/cheatsheet.html>`_
176for a quick guide to the documentation layout commands, or the
177`Sphinx Documentation <http://www.sphinx-doc.org/en/stable/>`_ for
178complete details.
179
180The model should include a **formula** written using LaTeX markup.
[7f23423]181The example above uses the *math* command to make a displayed equation.  You
[05829fb]182can also use *\$formula\$* for an inline formula. This is handy for defining
183the relationship between the model parameters and formula variables, such
184as the phrase "\$r\$ is the radius" used above.  The live demo MathJax
185page `<http://www.mathjax.org/>`_ is handy for checking that the equations
[7f23423]186will look like you intend.
[05829fb]187
188Math layout uses the `amsmath <http://www.ams.org/publications/authors/tex/amslatex>`_
189package for aligning equations (see amsldoc.pdf on that page for complete documentation).
190You will automatically be in an aligned environment, with blank lines separating
191the lines of the equation.  Place an ampersand before the operator on which to
192align.  For example::
193
194    .. math::
195
196      x + y &= 1 \\
197      y &= x - 1
198
199produces
200
201.. math::
202
203      x + y &= 1 \\
204      y &= x - 1
205
206If you need more control, use::
207
208    .. math::
209        :nowrap:
210
211
212Model Definition
213................
214
215Following the documentation string, there are a series of definitions::
216
217    name = "sphere"  # optional: defaults to the filename without .py
[7f23423]218
[05829fb]219    title = "Spheres with uniform scattering length density"
[7f23423]220
[05829fb]221    description = """\
222    P(q)=(scale/V)*[3V(sld-sld_solvent)*(sin(qr)-qr cos(qr))
223                    /(qr)^3]^2 + background
224        r: radius of sphere
225        V: The volume of the scatter
226        sld: the SLD of the sphere
227        sld_solvent: the SLD of the solvent
228    """
[7f23423]229
[05829fb]230    category = "shape:sphere"
[7f23423]231
[05829fb]232    single = True   # optional: defaults to True
[7f23423]233
[05829fb]234    opencl = False  # optional: defaults to False
[7f23423]235
[05829fb]236    structure_factor = False  # optional: defaults to False
237
238**name = "mymodel"** defines the name of the model that is shown to the user.
239If it is not provided, it will use the name of the model file, with '_'
240replaced by spaces and the parts capitalized.  So *adsorbed_layer.py* will
241become *Adsorbed Layer*.  The predefined models all use the name of the
242model file as the name of the model, so the default may be changed.
243
244**title = "short description"** is short description of the model which
245is included after the model name in the automatically generated documentation.
[7f23423]246The title can also be used for a tooltip.
[05829fb]247
248**description = """doc string"""** is a longer description of the model. It
[7f23423]249shows up when you press the "Description" button of the SasView FitPage.
[05829fb]250It should give a brief description of the equation and the parameters
251without the need to read the entire model documentation. The triple quotes
252allow you to write the description over multiple lines. Keep the lines
253short since the GUI will wrap each one separately if they are too long.
[7f23423]254**Make sure the parameter names in the description match the model definition!**
[05829fb]255
256**category = "shape:sphere"** defines where the model will appear in the
257model documentation.  In this example, the model will appear alphabetically
[7f23423]258in the list of spheroid models in the *Shape* category.
[05829fb]259
260**single = True** indicates that the model can be run using single
261precision floating point values.  Set it to False if the numerical
262calculation for the model is unstable, which is the case for about 20 of
263the built in models.  It is worthwhile modifying the calculation to support
264single precision, allowing models to run up to 10 times faster.  The
265section `Test_Your_New_Model`_  describes how to compare model values for
266single vs. double precision so you can decide if you need to set
267single to False.
268
269**opencl = False** indicates that the model should not be run using OpenCL.
270This may be because the model definition includes code that cannot be
271compiled for the GPU (for example, goto statements).  It can also be used
272for large models which can't run on most GPUs.  This flag has not been
273used on any of the built in models; models which were failing were
274streamlined so this flag was not necessary.
275
276**structure_factor = True** indicates that the model can be used as a
277structure factor to account for interactions between particles.  See
278`Form_Factors`_ for more details.
279
280Model Parameters
281................
282
283Next comes the parameter table.  For example::
284
285    # pylint: disable=bad-whitespace, line-too-long
286    #   ["name",        "units", default, [min, max], "type",    "description"],
287    parameters = [
288        ["sld",         "1e-6/Ang^2",  1, [-inf, inf], "sld",    "Layer scattering length density"],
289        ["sld_solvent", "1e-6/Ang^2",  6, [-inf, inf], "sld",    "Solvent scattering length density"],
290        ["radius",      "Ang",        50, [0, inf],    "volume", "Sphere radius"],
291    ]
[31d7803]292    # pylint: enable=bad-whitespace, line-too-long
[05829fb]293
294**parameters = [["name", "units", default, [min,max], "type", "tooltip"],...]**
[7f23423]295defines the parameters that form the model.
[05829fb]296
[7f23423]297**Note: The order of the parameters in the definition will be the order of the
298parameters in the user interface and the order of the parameters in Iq(),
299Iqxy() and form_volume(). And** *scale* **and** *background* **parameters are
300implicit to all models, so they do not need to be included in the parameter table.**
[05829fb]301
[7f23423]302- **"name"** is the name of the parameter shown on the FitPage.
[05829fb]303
304  - parameter names should follow the mathematical convention; e.g.,
[7f23423]305    *radius_core* not *core_radius*, or *sld_solvent* not *solvent_sld*.
306
[05829fb]307  - model parameter names should be consistent between different models,
308    so *sld_solvent*, for example, should have exactly the same name
[7f23423]309    in every model.
310
[05829fb]311  - to see all the parameter names currently in use, type the following in the
312    python shell/editor under the Tools menu::
313
314       import sasmodels.list_pars
315       sasmodels.list_pars.list_pars()
316
317    *re-use* as many as possible!!!
[7f23423]318
[05829fb]319  - use "name[n]" for multiplicity parameters, where *n* is the name of
320    the parameter defining the number of shells/layers/segments, etc.
321
322- **"units"** are displayed along with the parameter name
323
[7f23423]324  - every parameter should have units; use "None" if there are no units.
325
[05829fb]326  - **sld's should be given in units of 1e-6/Ang^2, and not simply
327    1/Ang^2 to be consistent with the builtin models.  Adjust your formulas
328    appropriately.**
[7f23423]329
[05829fb]330  - fancy units markup is available for some units, including::
331
332        Ang, 1/Ang, 1/Ang^2, 1e-6/Ang^2, degrees, 1/cm, Ang/cm, g/cm^3, mg/m^2
333
334  - the list of units is defined in the variable *RST_UNITS* within
335    `sasmodels/generate.py <https://github.com/SasView/sasmodels/tree/master/sasmodels/generate.py>`_
336
337    - new units can be added using the macros defined in *doc/rst_prolog*
338      in the sasmodels source.
339    - units should be properly formatted using sub-/super-scripts
340      and using negative exponents instead of the / operator, though
341      the unit name should use the / operator for consistency.
[7f23423]342    - please post a message to the SasView developers mailing list with your changes.
[05829fb]343
[7f23423]344- **default** is the initial value for the parameter.
[05829fb]345
346  - **the parameter default values are used to auto-generate a plot of
347    the model function in the documentation.**
348
[7f23423]349- **[min, max]** are the lower and upper limits on the parameter.
350
351  - lower and upper limits can be any number, or *-inf* or *inf*.
[05829fb]352
353  - the limits will show up as the default limits for the fit making it easy,
354    for example, to force the radius to always be greater than zero.
355
[7f23423]356- **"type"** can be one of: "", "sld", "volume", or "orientation".
[05829fb]357
358  - "sld" parameters can have magnetic moments when fitting magnetic models;
359    depending on the spin polarization of the beam and the $q$ value being
360    examined, the effective sld for that material will be used to compute the
[7f23423]361    scattered intensity.
362
[05829fb]363  - "volume" parameters are passed to Iq(), Iqxy(), and form_volume(), and
364    have polydispersity loops generated automatically.
[7f23423]365
[05829fb]366  - "orientation" parameters are only passed to Iqxy(), and have angular
367    dispersion.
368
369
370Model Computation
371.................
372
373Models can be defined as pure python models, or they can be a mixture of
374python and C models.  C models are run on the GPU if it is available,
375otherwise they are compiled and run on the CPU.
376
377Models are defined by the scattering kernel, which takes a set of parameter
378values defining the shape, orientation and material, and returns the
379expected scattering. Polydispersity and angular dispersion are defined
380by the computational infrastructure.  Any parameters defined as "volume"
381parameters are polydisperse, with polydispersity defined in proportion
382to their value.  "orientation" parameters use angular dispersion defined
383in degrees, and are not relative to the current angle.
384
385Based on a weighting function $G(x)$ and a number of points $n$, the
386computed value is
387
388.. math::
389
390     \hat I(q)
391     = \frac{\int G(x) I(q, x)\,dx}{\int G(x) V(x)\,dx}
392     \approx \frac{\sum_{i=1}^n G(x_i) I(q,x_i)}{\sum_{i=1}^n G(x_i) V(x_i)}
393
394That is, the indivdual models do not need to include polydispersity
395calculations, but instead rely on numerical integration to compute the
396appropriately smeared pattern.   Angular dispersion values over polar angle
397$\theta$ requires an additional $\cos \theta$ weighting due to decreased
398arc length for the equatorial angle $\phi$ with increasing latitude.
399
400Python Models
401.............
402
[7f23423]403For pure python models, define the *Iq* function::
[05829fb]404
405      import numpy as np
406      from numpy import cos, sin, ...
407
408      def Iq(q, par1, par2, ...):
409          return I(q, par1, par2, ...)
410      Iq.vectorized = True
411
412The parameters *par1, par2, ...* are the list of non-orientation parameters
413to the model in the order that they appear in the parameter table.
[7f23423]414**Note that the autogenerated model file uses** *x* **rather than** *q*.
[05829fb]415
416The *.py* file should import trigonometric and exponential functions from
[7f23423]417numpy rather than from math.  This lets us evaluate the model for the whole
[05829fb]418range of $q$ values at once rather than looping over each $q$ separately in
419python.  With $q$ as a vector, you cannot use if statements, but must instead
420do tricks like
421
422::
423
424     a = x*q*(q>0) + y*q*(q<=0)
425
426or
427
428::
429
430     a = np.empty_like(q)
431     index = q>0
432     a[index] = x*q[index]
433     a[~index] = y*q[~index]
434
435which sets $a$ to $q \cdot x$ if $q$ is positive or $q \cdot y$ if $q$
436is zero or negative. If you have not converted your function to use $q$
437vectors, you can set the following and it will only receive one $q$
438value at a time::
439
440    Iq.vectorized = False
441
442Return np.NaN if the parameters are not valid (e.g., cap_radius < radius in
443barbell).  If I(q; pars) is NaN for any $q$, then those parameters will be
444ignored, and not included in the calculation of the weighted polydispersity.
445
446Similar to *Iq*, you can define *Iqxy(qx, qy, par1, par2, ...)* where the
447parameter list includes any orientation parameters.  If *Iqxy* is not defined,
448then it will default to *Iqxy = Iq(sqrt(qx**2+qy**2), par1, par2, ...)*.
449
450Models should define *form_volume(par1, par2, ...)* where the parameter
451list includes the *volume* parameters in order.  This is used for a weighted
452volume normalization so that scattering is on an absolute scale.  If
[7f23423]453*form_volume* is not defined, then the default *form_volume = 1.0* will be
[05829fb]454used.
455
456Embedded C Models
457.................
458
[7f23423]459Like pure python models, inline C models need to define an *Iq* function::
[05829fb]460
461    Iq = """
462        return I(q, par1, par2, ...);
463    """
464
465This expands into the equivalent C code::
466
467    #include <math.h>
468    double Iq(double q, double par1, double par2, ...);
469    double Iq(double q, double par1, double par2, ...)
470    {
471        return I(q, par1, par2, ...);
472    }
473
474The C model operates on a single $q$ value at a time.  The code will be
475run in parallel across different $q$ values, either on the graphics card
476or the processor.
477
478Rather than returning NAN from Iq, you must define the *INVALID(v)*.  The
479*v* parameter lets you access all the parameters in the model using
480*v.par1*, *v.par2*, etc. For example::
481
482    #define INVALID(v) (v.bell_radius < v.radius)
483
484*Iqxy* is similar to *Iq*, except it uses parameters *qx, qy* instead of *q*,
485and it includes orientation parameters. As in python models, *form_volume*
486includes only the volume parameters.  *Iqxy* will default to
487*Iq(sqrt(qx**2 + qy**2), par1, ...)* and *form_volume* will default to 1.0.
488
489The C code follows the C99 standard, including the usual math functions,
490as defined in
491`OpenCL <https://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/mathFunctions.html>`_.
492
493The standard constants and functions include the following::
494
495    M_PI = pi
496    M_PI_2 = pi/2
497    M_PI_4 = pi/4
498    M_E = e
499    M_SQRT1_2 = 1/sqrt(2)
500    NAN = NaN
501    INFINITY = 1/0
502    erf(x) = error function
503    erfc(x) = 1-erf(x)
504    expm1(x) = exp(x) - 1
505    tgamma(x) = gamma function
506
507Some non-standard constants and functions are also provided::
508
509    M_PI_180 = pi/180
510    M_4PI_3 = 4pi/3
511    square(x) = x*x
512    cube(x) = x*x*x
513    sinc(x) = sin(x)/x, with sin(0)/0 -> 1
514    SINCOS(x, s, c) sets s=sin(angle) and c=cos(angle)
515    powr(x, y) = x^y for x >= 0
516    pown(x, n) = x^n for n integer
517
518**source=['lib/fn.c', ...]** includes the listed C source files in the
519program before *Iq* and *Iqxy* are defined. This allows you to extend the
520library of available C functions. Additional special functions and
521scattering calculations are defined in
522`sasmodels/models/lib <https://github.com/SasView/sasmodels/tree/master/sasmodels/models/lib>`_,
523including::
524
525    sph_j1c(x) = 3 j1(x)/x = 3 (sin(x) - x cos(x))/x^3  [spherical bessel function]
526    sas_J1c(x) = 2 J1(x)/x  [bessel function of the first kind]
527    sas_gamma(x) = gamma function  [tgamma is unstable below 1]
528    sas_erf(x) = error function [erf is broken on some Intel OpenCL drivers]
529    sas_erfc(x) = 1-erf(x)
530    sas_J0(x) = J0(x)
531    sas_J1(x) = J1(x)
532    sas_JN(x) = JN(x)
533    Si(x) = integral sin(z)/z from 0 to x
534    Gauss76Wt = gaussian quadrature weights for 76 point integral
535    Gauss76Z = gaussian quadrature values for 76 point integral
536
537These functions have been tuned to be fast and numerically stable down
538to $q=0$ even in single precision.  In some cases they work around bugs
[7f23423]539which appear on some platforms but not others. So use them where needed!!!
[05829fb]540
541Models are defined using double precision declarations for the
542parameters and return values.  Declarations and constants will be converted
543to float or long double depending on the precision requested.
[7f23423]544
[05829fb]545**Floating point constants must include the decimal point.**  This allows us
546to convert values such as 1.0 (double precision) to 1.0f (single precision)
547so that expressions that use these values are not promoted to double precision
548expressions.  Some graphics card drivers are confused when functions
549that expect floating point values are passed integers, such as 4*atan(1); it
550is safest to not use integers in floating point expressions.  Even better,
551use the builtin constant M_PI rather than 4*atan(1); it is faster and smaller!
552
553FLOAT_SIZE is the number of bytes in the converted variables. If your
554algorithm depends on precision (which is not uncommon for numerical
555algorithms), use the following::
556
557    #if FLOAT_SIZE>4
558    ... code for double precision ...
559    #else
560    ... code for single precision ...
561    #endif
562
563A value defined as SAS_DOUBLE will stay double precision; this should
[7f23423]564not be used since some graphics cards do not support double precision.
[05829fb]565
566
567External C Models
568.................
569
570External C models are very much like embedded C models, except that
571*Iq*, *Iqxy* and *form_volume* are defined in an external source file
572loaded using the *source=[...]*  method. You need to supply the function
573declarations for each of these that you need instead of building them
574automatically from the parameter table.
575
576
577.. _Form_Factors:
578
579Form Factors
580............
581
582Away from the dilute limit you can estimate scattering including
583particle-particle interactions using $I(q) = P(q)*S(q)$ where $P(q)$
584is the form factor and $S(q)$ is the structure factor.  The simplest
585structure factor is the *hardsphere* interaction, which
586uses the effective radius of the form factor as an input to the structure
587factor model.  The effective radius is the average radius of the
588form averaged over all the polydispersity values.
589
[31d7803]590::
591
592    def ER(radius, thickness):
593        """Effective radius of a core-shell sphere."""
594        return radius + thickness
595
596Now consider the *core_shell_sphere*, which has a simple effective radius
[05829fb]597equal to the radius of the core plus the thickness of the shell, as
598shown above. Given polydispersity over *(r1, r2, ..., rm)* in radius and
599*(t1, t2, ..., tn)* in thickness, *ER* is called with a mesh
600grid covering all possible combinations of radius and thickness.
601That is, *radius* is *(r1, r2, ..., rm, r1, r2, ..., rm, ...)*
602and *thickness* is *(t1, t1, ... t1, t2, t2, ..., t2, ...)*.
603The *ER* function returns one effective radius for each combination.
604The effective radius calculator weights each of these according to
605the polydispersity distributions and calls the structure factor
606with the average *ER*.
607
608::
609
610    def VR(radius, thickness):
611        """Sphere and shell volumes for a core-shell sphere."""
612        whole = 4.0/3.0 * pi * (radius + thickness)**3
613        core = 4.0/3.0 * pi * radius**3
614        return whole, whole - core
615
616Core-shell type models have an additional volume ratio which scales
617the structure factor.  The *VR* function returns the volume of
618the whole sphere and the volume of the shell. Like *ER*, there is
619one return value for each point in the mesh grid.
620
[31d7803]621*NOTE: we may be removing or modifying this feature soon. As of the
622time of writing, core-shell sphere returns (1., 1.) for VR, giving a volume
623ratio of 1.0.*
[05829fb]624
625Unit Tests
626..........
627
628THESE ARE VERY IMPORTANT. Include at least one test for each model and
629PLEASE make sure that the answer value is correct (i.e. not a random number).
630
631::
632
633    tests = [
634        [{}, 0.2, 0.726362],
635        [{"scale": 1., "background": 0., "sld": 6., "sld_solvent": 1.,
636          "radius": 120., "radius_pd": 0.2, "radius_pd_n":45},
637         0.2, 0.228843],
638        [{"radius": 120., "radius_pd": 0.2, "radius_pd_n":45}, "ER", 120.],
639        [{"radius": 120., "radius_pd": 0.2, "radius_pd_n":45}, "VR", 1.],
640    ]
641
642
643**tests=[[{parameters}, q, result], ...]** is a list of lists.
644Each list is one test and contains, in order:
645
646- a dictionary of parameter values. This can be {} using the default
647  parameters, or filled with some parameters that will be different
[cbbb6a4]648  from the default, such as {‘radius’:10.0, ‘sld’:4}. Unlisted parameters
[05829fb]649  will be given the default values.
650- the input $q$ value or tuple of $(q_x, q_y)$ values.
651- the output $I(q)$ or $I(q_x,q_y)$ expected of the model for the parameters
652  and input value given.
653- input and output values can themselves be lists if you have several
654  $q$ values to test for the same model parameters.
655- for testing *ER* and *VR*, give the inputs as "ER" and "VR" respectively;
656  the output for *VR* should be the sphere/shell ratio, not the individual
657  sphere and shell values.
658
659.. _Test_Your_New_Model:
660
661Test Your New Model
662^^^^^^^^^^^^^^^^^^^
663
[e925f61]664Installed SasView
665.................
666
[05829fb]667If you are editing your model from the SasView GUI, you can test it
[cbbb6a4]668by selecting *Run > Check Model* from the *Model Editor* menu bar. An
[05829fb]669*Info* box will appear with the results of the compilation and a
670check that the model runs.
671
[e925f61]672
673Built SasView
674.............
675
[05829fb]676If the model compiles and runs, you can next run the unit tests that
[31d7803]677you have added using the **test =** values. Switch to the *Shell* tab
[05829fb]678and type the following::
679
680    from sasmodels.model_test import run_one
681    run_one("~/.sasview/plugin_models/model.py")
682
683This should print::
684
685    test_model_python (sasmodels.model_test.ModelTestCase) ... ok
686
687To check whether single precision is good enough, type the following::
688
689    from sasmodels.compare import main
690    main("~/.sasview/plugin_models/model.py")
691
692This will pop up a plot showing the difference between single precision
693and double precision on a range of $q$ values.
694
695::
696
697  demo = dict(scale=1, background=0,
698              sld=6, sld_solvent=1,
699              radius=120,
700              radius_pd=.2, radius_pd_n=45)
701
702**demo={'par': value, ...}** in the model file sets the default values for
703the comparison. You can include polydispersity parameters such as
704*radius_pd=0.2, radius_pd_n=45* which would otherwise be zero.
705
706The options to compare are quite extensive; type the following for help::
707
708    main()
709
710Options will need to be passed as separate strings.
711For example to run your model with a random set of parameters::
712
713    main("-random", "-pars", "~/.sasview/plugin_models/model.py")
714
715For the random models,
716
[31d7803]717- *sld* will be in the range (-0.5,10.5),
718- angles (*theta, phi, psi*) will be in the range (-180,180),
719- angular dispersion will be in the range (0,45),
720- polydispersity will be in the range (0,1)
721- other values will be in the range (0, 2\ *v*), where *v* is the value of the parameter in demo.
[05829fb]722
[31d7803]723Dispersion parameters *n*\, *sigma* and *type* will be unchanged from demo so that
[05829fb]724run times are predictable.
725
726If your model has 2D orientational calculation, then you should also
727test with::
728
729    main("-2d", "~/.sasview/plugin_models/model.py")
730
731
[e925f61]732Clean Lint - (Developer Version Only)
733^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[05829fb]734
[e925f61]735**NB: For now we are not providing pylint with the installer version of SasView;
736so unless you have a SasView build environment available, you can ignore this section!**
[05829fb]737
738Run the lint check with::
739
740    python -m pylint --rcfile=extra/pylint.rc ~/.sasview/plugin_models/model.py
741
742We are not aiming for zero lint just yet, only keeping it to a minimum.
743For now, don't worry too much about *invalid-name*. If you really want a
744variable name *Rg* for example because $R_g$ is the right name for the model
745parameter then ignore the lint errors.  Also, ignore *missing-docstring*
746for standard model functions *Iq*, *Iqxy*, etc.
747
[31d7803]748We will have delinting sessions at the SasView Code Camps, where we can
[05829fb]749decide on standards for model files, parameter names, etc.
750
[31d7803]751For now, you can tell pylint to ignore things.  For example, to align your
[05829fb]752parameters in blocks::
753
754    # pylint: disable=bad-whitespace,line-too-long
755    #   ["name",                  "units", default, [lower, upper], "type", "description"],
756    parameters = [
757        ["contrast_factor",       "barns",    10.0,  [-inf, inf], "", "Contrast factor of the polymer"],
758        ["bjerrum_length",        "Ang",       7.1,  [0, inf],    "", "Bjerrum length"],
759        ["virial_param",          "1/Ang^2",  12.0,  [-inf, inf], "", "Virial parameter"],
760        ["monomer_length",        "Ang",      10.0,  [0, inf],    "", "Monomer length"],
761        ["salt_concentration",    "mol/L",     0.0,  [-inf, inf], "", "Concentration of monovalent salt"],
762        ["ionization_degree",     "",          0.05, [0, inf],    "", "Degree of ionization"],
763        ["polymer_concentration", "mol/L",     0.7,  [0, inf],    "", "Polymer molar concentration"],
764        ]
765    # pylint: enable=bad-whitespace,line-too-long
766
767Don't put in too many pylint statements, though, since they make the code ugly.
768
[e925f61]769Check The Docs - (Developer Version Only)
770^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[05829fb]771
772You can get a rough idea of how the documentation will look using the
773following::
774
775    from sasmodels.generate import view_html
776    view_html('~/.sasview/plugin_models/model.py')
777
778This does not use the same styling as the SasView docs, but it will allow
779you to check that your ReStructuredText and LaTeX formatting.  Here are
780some tools to help with the inevitable syntax errors:
781
782- `Sphinx cheat sheet <http://matplotlib.org/sampledoc/cheatsheet.html>`_
783- `Sphinx Documentation <http://www.sphinx-doc.org/en/stable/>`_
784- `MathJax <http://www.mathjax.org/>`_
785- `amsmath <http://www.ams.org/publications/authors/tex/amslatex>`_
786
[31d7803]787There is also a neat online WYSIWYG ReStructuredText editor at http://rst.ninjs.org\ .
788
[e925f61]789Share Your Model!
790^^^^^^^^^^^^^^^^^
[05829fb]791
792Once compare and the unit test(s) pass properly and everything is done,
793consider adding your model to the
[e925f61]794`Model Marketplace <http://marketplace.sasview.org/>`_ so that others may use it!
Note: See TracBrowser for help on using the repository browser.