Index: doc/guide/pd/polydispersity.rst
===================================================================
--- doc/guide/pd/polydispersity.rst	(revision 1f058ea138185c6cca6e665e2b2fe668ace3e775)
+++ doc/guide/pd/polydispersity.rst	(revision a5a12caaceba1c450d16a4bf8a7fc30ceab60a04)
@@ -40,5 +40,5 @@
 calculations are generally more robust with more data points or more angles.
 
-The following five distribution functions are provided:
+The following six distribution functions are provided:
 
 *  *Rectangular Distribution*
@@ -47,4 +47,5 @@
 *  *Schulz Distribution*
 *  *Array Distribution*
+*  *Boltzmann Distribution*
 
 These are all implemented as *number-average* distributions.
@@ -181,5 +182,5 @@
 ^^^^^^^^^^^^^^^^^^
 
-This user-definable distribution should be given as as a simple ASCII text
+This user-definable distribution should be given 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.
@@ -200,5 +201,31 @@
 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.
+not be fitable.
+
+.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+
+Boltzmann Distribution
+^^^^^^^^^^^^^^^^^^^^^^
+
+The Boltzmann Distribution is defined as
+
+.. math::
+
+    f(x) = \frac{1}{\text{Norm}}
+           \exp\left(-\frac{ | x - \bar x | }{\sigma}\right)
+
+where $\bar x$ is the mean of the distribution and *Norm* is a normalization
+factor which is determined during the numerical calculation.
+The width is defined as
+
+.. math:: \sigma=\frac{k T}{E}
+
+which is the inverse Boltzmann factor,
+where $k$ is the Boltzmann constant, $T$ the temperature in Kelvin and $E$ a
+characteristic energy per particle.
+
+.. figure:: pd_boltzmann.jpg
+
+    Boltzmann distribution.
 
 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
Index: sasmodels/weights.py
===================================================================
--- sasmodels/weights.py	(revision f1a8811c147abcdc8d3fb84ee7e8a25fa91be625)
+++ sasmodels/weights.py	(revision a5a12caaceba1c450d16a4bf8a7fc30ceab60a04)
@@ -55,4 +55,8 @@
         """
         sigma = self.width * center if relative else self.width
+        if not relative:
+            # For orientation, the jitter is relative to 0 not the angle
+            center = 0
+            pass
         if sigma == 0 or self.npts < 2:
             if lb <= center <= ub:
@@ -186,4 +190,18 @@
         return x, px
 
+class BoltzmannDispersion(Dispersion):
+    r"""
+    Boltzmann dispersion, with $\sigma=k T/E$.
+
+    .. math::
+
+        w = \exp\left( -|x - c|/\sigma\right)
+    """
+    type = "boltzmann"
+    default = dict(npts=35, width=0, nsigmas=3)
+    def _weights(self, center, sigma, lb, ub):
+        x = self._linspace(center, sigma, lb, ub)
+        px = np.exp(-np.abs(x-center) / np.abs(sigma))
+        return x, px
 
 # dispersion name -> disperser lookup table.
@@ -196,4 +214,5 @@
     GaussianDispersion,
     SchulzDispersion,
+    BoltzmannDispersion
 ))
 
@@ -225,27 +244,27 @@
     obj = cls(n, width, nsigmas)
     v, w = obj.get_weights(value, limits[0], limits[1], relative)
-    return v, w
-
-
-def plot_weights(model_info, pairs):
-    # type: (ModelInfo, List[Tuple[np.ndarray, np.ndarray]]) -> None
+    return v, w/np.sum(w)
+
+
+def plot_weights(model_info, mesh):
+    # type: (ModelInfo, List[Tuple[float, np.ndarray, np.ndarray]]) -> None
     """
     Plot the weights returned by :func:`get_weights`.
 
-    *model_info* is
-    :param model_info:
-    :param pairs:
-    :return:
+    *model_info* defines model parameters, etc.
+
+    *mesh* is a list of tuples containing (*value*, *dispersity*, *weights*)
+    for each parameter, where (*dispersity*, *weights*) pairs are the
+    distributions to be plotted.
     """
     import pylab
 
-    if any(len(values)>1 for values, weights in pairs):
+    if any(len(dispersity)>1 for value, dispersity, weights in mesh):
         labels = [p.name for p in model_info.parameters.call_parameters]
-        pylab.interactive(True)
+        #pylab.interactive(True)
         pylab.figure()
-        for (v,w), s in zip(pairs, labels):
-            if len(v) > 1:
-                #print("weights for", s, v, w)
-                pylab.plot(v, w, '-o', label=s)
+        for (v,x,w), s in zip(mesh, labels):
+            if len(x) > 1:
+                pylab.plot(x, w, '-o', label=s)
         pylab.grid(True)
         pylab.legend()
