Index: example/sesansfit.py
===================================================================
--- example/sesansfit.py	(revision 0ac3db5228ce012abd91225f8be83bb635c31a52)
+++ example/sesansfit.py	(revision 9c117a293e54d65d07bc4902eeab78dc58a6a8f8)
@@ -4,4 +4,5 @@
 from sasmodels import bumps_model as sas
 kernel = sas.load_model('sphere', dtype='single')
+#kernel = sas.load_model('triaxial_ellipsoid', dtype='single')
 
 
@@ -11,4 +12,5 @@
     loader=Loader()
     data=loader.load('testsasview1.ses')
+    data.x /=10
     
 #    data = load_sesans('mydatfile.pz')
@@ -20,26 +22,32 @@
     err_data = np.ones_like(SElength)*0.03
 
+    class Sample:
+        zacceptance = 0.1 # [A^-1]
+        thickness = 0.2 # [cm]
+        
     class SESANSData1D:
         #q_zmax = 0.23 # [A^-1]
-        zacceptance = 0.1 # [A^-1]
-        lam = 2e-10 # [m]
-        thickness = 0.2 # [cm]
+        lam = 0.2 # [nm]
         x = SElength
         y = data
         dy = err_data
-    data = SesansData()
-print dir(data)
+        sample = Sample()
+    data = SESANSData1D()
 
 radius = 1000
 data.Rmax = 3*radius # [A]
 
+##  Sphere parameters
+
 phi = Parameter(0.1, name="phi")
 model = sas.BumpsModel(data, kernel,
     scale=phi*(1-phi), sld=7.0, solvent_sld=1.0, radius=radius)
-phi.pmp(10)
-model.radius.pmp(40)
-model.sld.pm(2)
-model.background.range(0,5)
-
+phi.range(0.001,0.90)
+#model.radius.pmp(40)
+model.radius.range(100,10000)
+#model.sld.pmp(5)
+#model.background
+#model.radius_pd=0
+#model.radius_pd_n=0
 
 if False: # have sans data
@@ -49,2 +57,21 @@
     problem = FitProblem(model)
 
+
+### Tri-Axial Ellipsoid
+#
+#phi = Parameter(0.1, name='phi')
+#model = sas.BumpsModel(data, kernel,
+#    scale=phi*(1-phi), sld=7.0, solvent_sld=1.0, radius=radius)
+#phi.range(0.001,0.90)
+##model.radius.pmp(40)
+#model.radius.range(100,10000)
+##model.sld.pmp(5)
+##model.background
+##model.radius_pd=0
+##model.radius_pd_n=0
+#
+#if False: # have sans data
+#    sansmodel = sas.BumpsModel(sans_data, kernel, **model.parameters())
+#    problem = FitProblem([model, sansmodel])
+#else:
+#    problem = FitProblem(model)
Index: sasmodels/bumps_model.py
===================================================================
--- sasmodels/bumps_model.py	(revision 62b3cb21a2a19a773e020e8f7e70714e3440e5ad)
+++ sasmodels/bumps_model.py	(revision 9c117a293e54d65d07bc4902eeab78dc58a6a8f8)
@@ -354,5 +354,5 @@
             #self._theory[:] = self._fn.eval(pars, pd_pars)
             if self.data_type == 'sesans':
-                P = sesans.hankel(self.data.x, self.data.lam,
+                P = sesans.hankel(self.data.x, self.data.lam*1e-9,
                                   self.data.sample.thickness/10, self._fn_inputs[0],
                                   self._theory)
Index: sasmodels/convert.py
===================================================================
--- sasmodels/convert.py	(revision a503bfddd742ec35fe2b801f1d75a0a5f11eccfa)
+++ sasmodels/convert.py	(revision fd1c79268efa7be421f93c4a7c9e5cca2132d6c0)
@@ -13,10 +13,12 @@
         for variant in ("", "_pd", "_pd_n", "_pd_nsigma", "_pd_type"):
             if old+variant in newpars:
-                newpars[new+variant] = pars[old+variant]
+                if new is not None:
+                    newpars[new+variant] = pars[old+variant]
                 del newpars[old+variant]
         # Sasview style parameter names
         for variant in (".width", ".nsigmas", ".type", ".npts"):
             if old+variant in newpars:
-                newpars[new+variant] = pars[old+variant]
+                if new is not None:
+                    newpars[new+variant] = pars[old+variant]
                 del newpars[old+variant]
     return newpars
Index: sasmodels/direct_model.py
===================================================================
--- sasmodels/direct_model.py	(revision 16bc3fc9198028a6dd2dc68927e9590dff53ae09)
+++ sasmodels/direct_model.py	(revision 16bc3fc9198028a6dd2dc68927e9590dff53ae09)
@@ -0,0 +1,96 @@
+import warnings
+
+import numpy as np
+
+from . import models
+from . import weights
+
+try:
+    from .kernelcl import load_model
+except ImportError,exc:
+    warnings.warn(str(exc))
+    warnings.warn("using ctypes instead")
+    from .kerneldll import load_model
+
+def load_model_definition(model_name):
+    __import__('sasmodels.models.'+model_name)
+    model_definition = getattr(models, model_name, None)
+    return model_definition
+
+# load_model is imported above.  It looks like the following
+#def load_model(model_definition, dtype='single):
+#    if kerneldll:
+#        if source is newer than compiled: compile
+#        load dll
+#        return kernel
+#    elif kernelcl:
+#        compile source on context
+#        return kernel
+
+
+def make_kernel(model, q_vectors):
+    """
+    Return a computation kernel from the model definition and the q input.
+    """
+    input = model.make_input(q_vectors)
+    return model(input)
+
+def get_weights(kernel, pars, name):
+    """
+    Generate the distribution for parameter *name* given the parameter values
+    in *pars*.
+
+    Searches for "name", "name_pd", "name_pd_type", "name_pd_n", "name_pd_sigma"
+    """
+    relative = name in kernel.info['partype']['pd-rel']
+    limits = kernel.info['limits']
+    disperser = pars.get(name+'_pd_type', 'gaussian')
+    value = pars.get(name, kernel.info['defaults'][name])
+    npts = pars.get(name+'_pd_n', 0)
+    width = pars.get(name+'_pd', 0.0)
+    nsigma = pars.get(name+'_pd_nsigma', 3.0)
+    v,w = weights.get_weights(
+        disperser, npts, width, nsigma,
+        value, limits[name], relative)
+    return v,w/np.sum(w)
+
+def call_kernel(kernel, pars):
+    fixed_pars = [pars.get(name, kernel.info['defaults'][name])
+                  for name in kernel.fixed_pars]
+    pd_pars = [get_weights(kernel, pars, name) for name in kernel.pd_pars]
+    return kernel(fixed_pars, pd_pars)
+
+class DirectModel:
+    def __init__(self, name, q_vectors, dtype='single'):
+        self.model_definition = load_model_definition(name)
+        self.model = load_model(self.model_definition, dtype=dtype)
+        q_vectors = [np.ascontiguousarray(q,dtype=dtype) for q in q_vectors]
+        self.kernel = make_kernel(self.model, q_vectors)
+    def __call__(self, **pars):
+        return call_kernel(self.kernel, pars)
+
+def demo():
+    import sys
+    if len(sys.argv) < 3:
+        print "usage: python -m sasmodels.direct_model modelname (q|qx,qy) par=val ..."
+        sys.exit(1)
+    model_name = sys.argv[1]
+    values = [float(v) for v in sys.argv[2].split(',')]
+    if len(values) == 1:
+        q = values[0]
+        q_vectors = [[q]]
+    elif len(values) == 2:
+        qx,qy = values
+        q_vectors = [[qx],[qy]]
+    else:
+        print "use q or qx,qy"
+        sys.exit(1)
+    model = DirectModel(model_name, q_vectors)
+    pars = dict((k,float(v))
+                for pair in sys.argv[3:]
+                for k,v in [pair.split('=')])
+    Iq = model(**pars)
+    print Iq[0]
+
+if __name__ == "__main__":
+    demo()
Index: sasmodels/generate.py
===================================================================
--- sasmodels/generate.py	(revision ff58110a27b9d0715ee0cfdb726a7186a2bab733)
+++ sasmodels/generate.py	(revision ae7b97b7619696aff6e6f1d4549b539e6ecf8a1d)
@@ -731,4 +731,5 @@
     info['limits'] = dict((p[0],p[3]) for p in info['parameters'])
     info['partype'] = categorize_parameters(info['parameters'])
+    info['defaults'] = dict((p[0],p[2]) for p in info['parameters'])
 
     source = make_model(info)
Index: sasmodels/kernelpy.py
===================================================================
--- sasmodels/kernelpy.py	(revision f786ff3daee63fedbada60cec1eb19964c370615)
+++ sasmodels/kernelpy.py	(revision 6edb74ad0e29130e51cebe28cb7dafc6d82aebbf)
@@ -87,5 +87,5 @@
         self.pd_pars = pd_pars
 
-    def __call__(self, fixed, pd, cutoff):
+    def __call__(self, fixed, pd, cutoff=1e-5):
         #print "fixed",fixed
         #print "pd", pd
@@ -144,20 +144,24 @@
     ##########################################################
 
-    # weight vector, to be populated by polydispersity loops
     weight = np.empty(len(pd), 'd')
-
-    # identify which pd parameters are volume parameters
-    vol_weight_index = np.array([(index in vol_index) for index in pd_index])
-
-    # Sort parameters in decreasing order of pd length
-    Npd = np.array([len(pdi[0]) for pdi in pd], 'i')
-    order = np.argsort(Npd)[::-1]
-    stride = np.cumprod(Npd[order])
-    pd = [pd[index] for index in order]
-    pd_index = pd_index[order]
-    vol_weight_index = vol_weight_index[order]
-
-    fast_value = pd[0][0]
-    fast_weight = pd[0][1]
+    if weight.size > 0:
+        # weight vector, to be populated by polydispersity loops
+
+        # identify which pd parameters are volume parameters
+        vol_weight_index = np.array([(index in vol_index) for index in pd_index])
+
+        # Sort parameters in decreasing order of pd length
+        Npd = np.array([len(pdi[0]) for pdi in pd], 'i')
+        order = np.argsort(Npd)[::-1]
+        stride = np.cumprod(Npd[order])
+        pd = [pd[index] for index in order]
+        pd_index = pd_index[order]
+        vol_weight_index = vol_weight_index[order]
+
+        fast_value = pd[0][0]
+        fast_weight = pd[0][1]
+    else:
+        stride = np.array([1])
+        vol_weight_index = slice(None, None)
 
     ret = np.zeros_like(args[0])
@@ -169,7 +173,8 @@
         fast_index = k%stride[0]
         if fast_index == 0:  # bottom loop complete ... check all other loops
-            for i,index, in enumerate(k%stride):
-                args[pd_index[i]] = pd[i][0][index]
-                weight[i] = pd[i][1][index]
+            if weight.size > 0:
+                for i,index, in enumerate(k%stride):
+                    args[pd_index[i]] = pd[i][0][index]
+                    weight[i] = pd[i][1][index]
         else:
             args[pd_index[0]] = fast_value[fast_index]
Index: sasmodels/models/broad_peak.py
===================================================================
--- sasmodels/models/broad_peak.py	(revision 636adb6f79af5036379849690e91a2cfdf1b5c02)
+++ sasmodels/models/broad_peak.py	(revision fd1c79268efa7be421f93c4a7c9e5cca2132d6c0)
@@ -51,5 +51,5 @@
 
 import numpy as np
-from numpy import pi, inf, sin, cos, sqrt, exp, log
+from numpy import pi, inf, sin, cos, sqrt, exp, log, fabs
 
 name = "broad_peak"
@@ -92,5 +92,5 @@
 def Iq(q, porod_scale, porod_exp, lorentz_scale, lorentz_length, peak_pos, lorentz_exp):
     inten = porod_scale/pow(q,porod_exp) + lorentz_scale/(1.0 \
-        + pow((math.fabs(q-peak_pos)*lorentz_length),lorentz_exp))
+        + pow((fabs(q-peak_pos)*lorentz_length),lorentz_exp))
     return inten  
 
@@ -113,3 +113,3 @@
 oldpars = dict(porod_scale='scale_p', porod_exp='exponent_p', 
         lorentz_scale='scale_l', lorentz_length='length_l', peak_pos='q_peak', 
-        lorentz_exp='exponent_l')
+        lorentz_exp='exponent_l', scale=None)
