Index: sansmodels/src/sans/models/CylinderModel.py
===================================================================
--- sansmodels/src/sans/models/CylinderModel.py	(revision ae3ce4eaa593202ebf49122e196897c0d45a25b6)
+++ sansmodels/src/sans/models/CylinderModel.py	(revision af03ddd0932915d6659404ab7824e4223ea2944f)
@@ -1,11 +1,23 @@
 #!/usr/bin/env python
+"""
+	This software was developed by the University of Tennessee as part of the
+	Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+	project funded by the US National Science Foundation.
+
+	If you use DANSE applications to do scientific research that leads to
+	publication, we ask that you acknowledge the use of the software with the
+	following sentence:
+
+	"This work benefited from DANSE software developed under NSF award DMR-0520547."
+
+	copyright 2008, University of Tennessee
+"""
+
 """ Provide functionality for a C extension model
 
 	WARNING: THIS FILE WAS GENERATED BY WRAPPERGENERATOR.PY
- 	         DO NOT MODIFY THIS FILE, MODIFY cylinder.h
+ 	         DO NOT MODIFY THIS FILE, MODIFY ../c_extensions/cylinder.h
  	         AND RE-RUN THE GENERATOR SCRIPT
 
-    @author: Mathieu Doucet / UTK
-    @contact: mathieu.doucet@nist.gov
 """
 
@@ -16,5 +28,5 @@
 class CylinderModel(CCylinderModel, BaseComponent):
     """ Class that evaluates a CylinderModel model. 
-    	This file was auto-generated from cylinder.h.
+    	This file was auto-generated from ../c_extensions/cylinder.h.
     	Refer to that file and the structure it contains
     	for details of the model.
@@ -72,4 +84,13 @@
         
         return CCylinderModel.runXY(self, x)
+        
+    def set_dispersion(self, parameter, dispersion):
+        """
+            Set the dispersion object for a model parameter
+            @param parameter: name of the parameter [string]
+            @dispersion: dispersion object of type DispersionModel
+        """
+        return CCylinderModel.set_dispersion(self, parameter, dispersion.cdisp)
+        
    
 # End of file
Index: sansmodels/src/sans/models/c_extensions/c_models.c
===================================================================
--- sansmodels/src/sans/models/c_extensions/c_models.c	(revision ae3ce4eaa593202ebf49122e196897c0d45a25b6)
+++ sansmodels/src/sans/models/c_extensions/c_models.c	(revision af03ddd0932915d6659404ab7824e4223ea2944f)
@@ -1,5 +1,5 @@
 /** c_models
  *
- * Module containing all SANS model extensions 
+ * Module containing all SANS model extensions
  *
  * @author   M.Doucet / UTK
@@ -11,5 +11,5 @@
  */
 static PyMethodDef module_methods[] = {
-    {NULL} 
+    {NULL}
 };
 
@@ -19,5 +19,5 @@
 #endif
 PyMODINIT_FUNC
-initc_models(void) 
+initc_models(void)
 {
     PyObject* m;
@@ -25,5 +25,5 @@
     m = Py_InitModule3("c_models", module_methods,
                        "C extension module for SANS scattering models.");
-                       
+
 	addCCylinderModel(m);
 	addCCoreShellCylinderModel(m);
Index: sansmodels/src/sans/models/c_extensions/c_models.cpp
===================================================================
--- sansmodels/src/sans/models/c_extensions/c_models.cpp	(revision af03ddd0932915d6659404ab7824e4223ea2944f)
+++ sansmodels/src/sans/models/c_extensions/c_models.cpp	(revision af03ddd0932915d6659404ab7824e4223ea2944f)
@@ -0,0 +1,148 @@
+/** c_models
+ *
+ * Module containing all SANS model extensions
+ *
+ * @author   M.Doucet / UTK
+ */
+#include <Python.h>
+#include <parameters.hh>
+
+void addCCylinderModel(PyObject *module);
+extern "C" {
+	void addCCoreShellCylinderModel(PyObject *module);
+	void addCCoreShellModel(PyObject *module);
+	void addCEllipsoidModel(PyObject *module);
+	void addCSphereModel(PyObject *module);
+	void addCEllipticalCylinderModel(PyObject *module);
+	void addDisperser(PyObject *module);
+	void addCGaussian(PyObject *module);
+	void addCLorentzian(PyObject *module);
+}
+
+/**
+ * Delete a dispersion model object
+ */
+void del_dispersion_model(void *ptr){
+	DispersionModel * disp = static_cast<DispersionModel *>(ptr);
+	delete disp;
+	return;
+}
+
+/**
+ * Create a dispersion model as a python object
+ */
+PyObject * new_dispersion_model(PyObject *, PyObject *args) {
+	DispersionModel *disp = new DispersionModel();
+	return PyCObject_FromVoidPtr(disp, del_dispersion_model);
+}
+
+
+/**
+ * Delete a gaussian dispersion model object
+ */
+void del_gaussian_dispersion(void *ptr){
+	GaussianDispersion * disp = static_cast<GaussianDispersion *>(ptr);
+	delete disp;
+	return;
+}
+
+/**
+ * Create a gaussian dispersion model as a python object
+ */
+PyObject * new_gaussian_dispersion(PyObject *, PyObject *args) {
+	GaussianDispersion *disp = new GaussianDispersion();
+	return PyCObject_FromVoidPtr(disp, del_gaussian_dispersion);
+}
+
+/**
+ * Delete an array dispersion model object
+ */
+void del_array_dispersion(void *ptr){
+	ArrayDispersion * disp = static_cast<ArrayDispersion *>(ptr);
+	delete disp;
+	return;
+}
+
+/**
+ * Create an array dispersion model as a python object
+ */
+PyObject * new_array_dispersion(PyObject *, PyObject *args) {
+	ArrayDispersion *disp = new ArrayDispersion();
+	return PyCObject_FromVoidPtr(disp, del_array_dispersion);
+}
+
+#define INVECTOR(obj,buf,len)										\
+    do { \
+        int err = PyObject_AsReadBuffer(obj, (const void **)(&buf), &len); \
+        if (err < 0) return NULL; \
+        len /= sizeof(*buf); \
+    } while (0)
+
+/**
+ * Sets weights from a numpy array
+ */
+PyObject * set_weights(PyObject *, PyObject *args) {
+	PyObject *val_obj;
+	PyObject *wei_obj;
+	PyObject *disp;
+	Py_ssize_t nval;
+	Py_ssize_t nwei;
+	double *values;
+	double *weights;
+    int i;
+
+	if (!PyArg_ParseTuple(args, "OOO", &disp, &val_obj, &wei_obj)) return NULL;
+	INVECTOR(val_obj, values, nval);
+	INVECTOR(wei_obj, weights, nwei);
+
+	// Sanity check
+	if(nval!=nwei) return NULL;
+
+	// Set the array pointers
+	void *temp = PyCObject_AsVoidPtr(disp);
+	DispersionModel * dispersion = static_cast<DispersionModel *>(temp);
+	dispersion->set_weights(nval, values, weights);
+
+	return Py_BuildValue("i",1);
+}
+
+
+
+/**
+ * Define empty module
+ */
+static PyMethodDef module_methods[] = {
+	{"new_dispersion_model", (PyCFunction)new_dispersion_model     , METH_VARARGS,
+		  "Create a new DispersionModel object"},
+	{"new_gaussian_model",   (PyCFunction)new_gaussian_dispersion, METH_VARARGS,
+		  "Create a new GaussianDispersion object"},
+	{"new_array_model",      (PyCFunction)new_array_dispersion  , METH_VARARGS,
+		  "Create a new ArrayDispersion object"},
+	{"set_dispersion_weights",(PyCFunction)set_weights  , METH_VARARGS,
+			"Create the dispersion weight arrays for an Array Dispersion object"},
+    {NULL}
+};
+
+
+#ifndef PyMODINIT_FUNC	/* declarations for DLL import/export */
+#define PyMODINIT_FUNC void
+#endif
+PyMODINIT_FUNC
+initc_models(void)
+{
+    PyObject* m;
+
+    m = Py_InitModule3("c_models", module_methods,
+                       "C extension module for SANS scattering models.");
+
+	addCCylinderModel(m);
+	addCCoreShellCylinderModel(m);
+	addCCoreShellModel(m);
+	addCEllipsoidModel(m);
+	addCSphereModel(m);
+	addCEllipticalCylinderModel(m);
+	addDisperser(m);
+	addCGaussian(m);
+	addCLorentzian(m);
+
+}
Index: sansmodels/src/sans/models/c_extensions/cylinder.h
===================================================================
--- sansmodels/src/sans/models/c_extensions/cylinder.h	(revision ae3ce4eaa593202ebf49122e196897c0d45a25b6)
+++ sansmodels/src/sans/models/c_extensions/cylinder.h	(revision af03ddd0932915d6659404ab7824e4223ea2944f)
@@ -2,13 +2,14 @@
 #define cylinder_h
 
-/** Structure definition for cylinder parameters 
+/** Structure definition for cylinder parameters
  * [PYTHONCLASS] = CylinderModel
+ * [DISP_PARAMS] = radius, length, cyl_theta, cyl_phi
  * */
 typedef struct {
-    /// Scale factor 
+    /// Scale factor
     //  [DEFAULT]=scale=1.0
     double scale;
     /// Radius of the cylinder [A]
-    //  [DEFAULT]=radius=20.0 A 
+    //  [DEFAULT]=radius=20.0 A
     double radius;
     /// Length of the cylinder [A]
@@ -20,5 +21,5 @@
 	/// Incoherent Background (cm-1) 0.000
 	//  [DEFAULT]=background=0 cm-1
-	double background;    
+	double background;
     /// Orientation of the cylinder axis w/respect incoming beam [rad]
     //  [DEFAULT]=cyl_theta=1.0 rad
@@ -26,5 +27,5 @@
     /// Orientation of the cylinder in the plane of the detector [rad]
     //  [DEFAULT]=cyl_phi=1.0 rad
-    double cyl_phi;    
+    double cyl_phi;
 } CylinderParameters;
 
Index: sansmodels/src/sans/models/c_extensions/models.cpp
===================================================================
--- sansmodels/src/sans/models/c_extensions/models.cpp	(revision a9dec92e2550e19a36ff107998eb8ff8c5b466a5)
+++ 	(revision )
@@ -1,50 +1,0 @@
-/**
- * Scattering model classes
- * The classes use the IGOR library found in
- *   sansmodels/src/libigor
- */
-#include "models.h"
-#include <stdio.h>
-using namespace std;
-
-extern "C" {
-	#include "libCylinder.h"
-	#include "cylinder.h"
-}
-
-Cylinder :: Cylinder() {
-	parameters.scale      = 1.0;
-	parameters.radius     = 10.0;
-	parameters.length     = 400.0;
-	parameters.contrast   = 1.0;
-	parameters.background = 0;
-	parameters.cyl_theta  = 0;
-	parameters.cyl_phi    = 0;
-}
-
-/**
- * Function to evaluate 1D scattering function
- * @param q: q-value
- * @return: function value
- */
-double Cylinder :: operator()(double q) {
-	return cylinder_analytical_1D(&parameters, q);
-}
-
-/**
- * Function to evaluate 2D scattering function
- * @param q_x: value of Q along x
- * @param q_y: value of Q along y
- * @return: function value
- */
-double Cylinder :: operator()(double qx, double qy) {
-	return cylinder_analytical_2DXY(&parameters, qx, qy);
-}
-
-int main(void)
-{
-	Cylinder c = Cylinder();
-	printf("I(Q=%g) = %g\n", 0.001, c(0.001));
-	printf("I(Qx=%g, Qy=%g) = %g\n", 0.001, 0.001, c(0.001, 0.001));
-	return 0;
-}
Index: sansmodels/src/sans/models/c_extensions/models.h
===================================================================
--- sansmodels/src/sans/models/c_extensions/models.h	(revision a9dec92e2550e19a36ff107998eb8ff8c5b466a5)
+++ 	(revision )
@@ -1,23 +1,0 @@
-#ifndef MODEL_CLASS_H
-#define MODEL_CLASS_H
-
-extern "C" {
-	#include "cylinder.h"
-}
-
-class Cylinder {
-
-public:
-	// Model parameters
-	CylinderParameters parameters;
-
-	// Constructor
-	Cylinder();
-
-	// Operators to get I(Q)
-	double operator()(double q);
-	double operator()(double qx, double qy);
-
-};
-
-#endif
Index: sansmodels/src/sans/models/c_models/CCylinder.cpp
===================================================================
--- sansmodels/src/sans/models/c_models/CCylinder.cpp	(revision fca6936ab3704433fa2327bcd55367e8ea28de72)
+++ 	(revision )
@@ -1,354 +1,0 @@
-/** CCylinder
- *
- * C extension
- *
- */
-extern "C" {
-#include <Python.h>
-#include "structmember.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <time.h>
-#include "cylinder.h"
-}
-
-
-#include "models.hh"
-#include "dispersion_visitor.hh"
-
-/// Error object for raised exceptions
-static PyObject * CCylinderModelError = NULL;
-
-
-// Class definition
-typedef struct {
-    PyObject_HEAD
-    /// Parameters
-    PyObject * params;
-    PyObject * dispersion;
-    Cylinder * model;
-    /// Log for unit testing
-    PyObject * log;
-    /// Model parameters
-	CylinderParameters model_pars;
-} CCylinderModel;
-
-
-static void
-CCylinderModel_dealloc(CCylinderModel* self)
-{
-    self->ob_type->tp_free((PyObject*)self);
-
-
-}
-
-static PyObject *
-CCylinderModel_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-    CCylinderModel *self;
-
-    self = (CCylinderModel *)type->tp_alloc(type, 0);
-
-    return (PyObject *)self;
-}
-
-static int
-CCylinderModel_init(CCylinderModel *self, PyObject *args, PyObject *kwds)
-{
-    if (self != NULL) {
-    	printf("Hello cylinder\n");
-    	// Create parameters
-        self->params = PyDict_New();
-        self->dispersion = PyDict_New();
-        self->model = new Cylinder();
-
-        // Initialize parameter dictionary
-        PyDict_SetItemString(self->params,"scale",     Py_BuildValue("d", self->model->scale()));
-        PyDict_SetItemString(self->params,"length",    Py_BuildValue("d", self->model->length()));
-        PyDict_SetItemString(self->params,"cyl_theta", Py_BuildValue("d", self->model->cyl_theta()));
-        PyDict_SetItemString(self->params,"background",Py_BuildValue("d", self->model->background()));
-        PyDict_SetItemString(self->params,"radius",    Py_BuildValue("d", self->model->radius()));
-        PyDict_SetItemString(self->params,"contrast",  Py_BuildValue("d", self->model->contrast()));
-        PyDict_SetItemString(self->params,"cyl_phi",   Py_BuildValue("d", self->model->cyl_phi()));
-
-        // Initialize dispersion / averaging parameter dict
-        DispersionVisitor* visitor = new DispersionVisitor();
-        PyObject * disp_dict = PyDict_New();
-        self->model->radius.dispersion->accept_as_source(visitor, self->model->radius.dispersion, disp_dict);
-        PyDict_SetItemString(self->dispersion, "disp_radius", disp_dict);
-
-        disp_dict = PyDict_New();
-        self->model->length.dispersion->accept_as_source(visitor, self->model->length.dispersion, disp_dict);
-        PyDict_SetItemString(self->dispersion, "disp_length", disp_dict);
-
-        disp_dict = PyDict_New();
-        self->model->cyl_phi.dispersion->accept_as_source(visitor, self->model->cyl_phi.dispersion, disp_dict);
-        PyDict_SetItemString(self->dispersion, "disp_cyl_phi", disp_dict);
-
-        disp_dict = PyDict_New();
-        self->model->cyl_theta.dispersion->accept_as_source(visitor, self->model->cyl_theta.dispersion, disp_dict);
-        PyDict_SetItemString(self->dispersion, "disp_cyl_theta", disp_dict);
-
-        // Create empty log
-        self->log = PyDict_New();
-
-    }
-    return 0;
-}
-
-static PyMemberDef CCylinderModel_members[] = {
-	{"params", T_OBJECT, offsetof(CCylinderModel, params), 0,
-	 "Parameters"},
-	{"dispersion", T_OBJECT, offsetof(CCylinderModel, dispersion), 0,
-	  "Dispersion parameters"},
-    {"log", T_OBJECT, offsetof(CCylinderModel, log), 0,
-     "Log"},
-    {NULL}  /* Sentinel */
-};
-
-/** Read double from PyObject
-    @param p PyObject
-    @return double
-*/
-double CCylinderModel_readDouble(PyObject *p) {
-    if (PyFloat_Check(p)==1) {
-        return (double)(((PyFloatObject *)(p))->ob_fval);
-    } else if (PyInt_Check(p)==1) {
-        return (double)(((PyIntObject *)(p))->ob_ival);
-    } else if (PyLong_Check(p)==1) {
-        return (double)PyLong_AsLong(p);
-    } else {
-        return 0.0;
-    }
-}
-
-/**
- * Method to set the dispersion model for a parameter.
- * We need to update the dispersion object of the parameter
- * on the C++ side and update the dispersion dictionary on the python side.
- *
- * TODO: define read-only integers that will be data members of this
- * class and allow the user to specify which model is needed with a code name.
- *
- * This method should take in a code name (FLAT, GAUSSIAN) and a string
- * that represent the parameter to attach the dispersion model to.
- *
- */
-static PyObject * set_dispersion_model(CCylinderModel *self, PyObject *args) {
-
-}
-
-
-/**
- * Function to call to evaluate model
- * @param args: input q or [q,phi]
- * @return: function value
- */
-static PyObject * run(CCylinderModel *self, PyObject *args) {
-	double q_value, phi_value;
-	PyObject* pars;
-	int npars;
-
-	// Get parameters
-
-	// Reader parameter dictionary
-    self->model->scale = PyFloat_AsDouble( PyDict_GetItemString(self->params, "scale") );
-    self->model->length = PyFloat_AsDouble( PyDict_GetItemString(self->params, "length") );
-    self->model->cyl_theta = PyFloat_AsDouble( PyDict_GetItemString(self->params, "cyl_theta") );
-    self->model->background = PyFloat_AsDouble( PyDict_GetItemString(self->params, "background") );
-    self->model->radius = PyFloat_AsDouble( PyDict_GetItemString(self->params, "radius") );
-    self->model->contrast = PyFloat_AsDouble( PyDict_GetItemString(self->params, "contrast") );
-    self->model->cyl_phi = PyFloat_AsDouble( PyDict_GetItemString(self->params, "cyl_phi") );
-
-    // Read in dispersion parameters
-    DispersionVisitor* visitor = new DispersionVisitor();
-    PyObject* disp_dict = PyDict_New();
-    disp_dict = PyDict_GetItemString(self->dispersion, "disp_radius");
-    self->model->radius.dispersion->accept_as_destination(visitor, self->model->radius.dispersion, disp_dict);
-    self->model->length.dispersion->accept_as_destination(visitor, self->model->length.dispersion, disp_dict);
-    self->model->cyl_theta.dispersion->accept_as_destination(visitor, self->model->cyl_theta.dispersion, disp_dict);
-    self->model->cyl_phi.dispersion->accept_as_destination(visitor, self->model->cyl_phi.dispersion, disp_dict);
-
-	// Get input and determine whether we have to supply a 1D or 2D return value.
-	if ( !PyArg_ParseTuple(args,"O",&pars) ) {
-	    PyErr_SetString(CCylinderModelError,
-	    	"CCylinderModel.run expects a q value.");
-		return NULL;
-	}
-
-	// Check params
-	if( PyList_Check(pars)==1) {
-
-		// Length of list should be 2 for I(q,phi)
-	    npars = PyList_GET_SIZE(pars);
-	    if(npars!=2) {
-	    	PyErr_SetString(CCylinderModelError,
-	    		"CCylinderModel.run expects a double or a list of dimension 2.");
-	    	return NULL;
-	    }
-	    // We have a vector q, get the q and phi values at which
-	    // to evaluate I(q,phi)
-	    q_value = CCylinderModel_readDouble(PyList_GET_ITEM(pars,0));
-	    phi_value = CCylinderModel_readDouble(PyList_GET_ITEM(pars,1));
-	    // Skip zero
-	    if (q_value==0) {
-	    	return Py_BuildValue("d",0.0);
-	    }
-		return Py_BuildValue("d",(*(self->model)).evaluate_rphi(q_value,phi_value));
-
-	} else {
-
-		// We have a scalar q, we will evaluate I(q)
-		q_value = CCylinderModel_readDouble(pars);
-
-		return Py_BuildValue("d",(*(self->model))(q_value));
-	}
-}
-
-/**
- * Function to call to evaluate model in cartesian coordinates
- * @param args: input q or [qx, qy]]
- * @return: function value
- */
-static PyObject * runXY(CCylinderModel *self, PyObject *args) {
-	double qx_value, qy_value;
-	PyObject* pars;
-	int npars;
-
-	// Get parameters
-
-	// Reader parameter dictionary
-    self->model->scale = PyFloat_AsDouble( PyDict_GetItemString(self->params, "scale") );
-    self->model->length = PyFloat_AsDouble( PyDict_GetItemString(self->params, "length") );
-    self->model->cyl_theta = PyFloat_AsDouble( PyDict_GetItemString(self->params, "cyl_theta") );
-    self->model->background = PyFloat_AsDouble( PyDict_GetItemString(self->params, "background") );
-    self->model->radius = PyFloat_AsDouble( PyDict_GetItemString(self->params, "radius") );
-    self->model->contrast = PyFloat_AsDouble( PyDict_GetItemString(self->params, "contrast") );
-    self->model->cyl_phi = PyFloat_AsDouble( PyDict_GetItemString(self->params, "cyl_phi") );
-
-    // Read in dispersion parameters
-    DispersionVisitor* visitor = new DispersionVisitor();
-    PyObject* disp_dict = PyDict_New();
-    disp_dict = PyDict_GetItemString(self->dispersion, "disp_radius");
-    self->model->radius.dispersion->accept_as_destination(visitor, self->model->radius.dispersion, disp_dict);
-    self->model->length.dispersion->accept_as_destination(visitor, self->model->length.dispersion, disp_dict);
-    self->model->cyl_theta.dispersion->accept_as_destination(visitor, self->model->cyl_theta.dispersion, disp_dict);
-    self->model->cyl_phi.dispersion->accept_as_destination(visitor, self->model->cyl_phi.dispersion, disp_dict);
-
-	// Get input and determine whether we have to supply a 1D or 2D return value.
-	if ( !PyArg_ParseTuple(args,"O",&pars) ) {
-	    PyErr_SetString(CCylinderModelError,
-	    	"CCylinderModel.run expects a q value.");
-		return NULL;
-	}
-
-	// Check params
-	if( PyList_Check(pars)==1) {
-
-		// Length of list should be 2 for I(qx, qy))
-	    npars = PyList_GET_SIZE(pars);
-	    if(npars!=2) {
-	    	PyErr_SetString(CCylinderModelError,
-	    		"CCylinderModel.run expects a double or a list of dimension 2.");
-	    	return NULL;
-	    }
-	    // We have a vector q, get the qx and qy values at which
-	    // to evaluate I(qx,qy)
-	    qx_value = CCylinderModel_readDouble(PyList_GET_ITEM(pars,0));
-	    qy_value = CCylinderModel_readDouble(PyList_GET_ITEM(pars,1));
-	    return Py_BuildValue("d",(*(self->model))(qx_value,qy_value));
-
-	} else {
-
-		// We have a scalar q, we will evaluate I(q)
-		qx_value = CCylinderModel_readDouble(pars);
-
-		return Py_BuildValue("d",(*(self->model))(qx_value));
-	}
-}
-
-static PyObject * reset(CCylinderModel *self, PyObject *args) {
-
-
-    return Py_BuildValue("d",0.0);
-}
-
-
-static PyMethodDef CCylinderModel_methods[] = {
-    {"run",      (PyCFunction)run     , METH_VARARGS,
-      "Evaluate the model at a given Q or Q, phi"},
-    {"runXY",      (PyCFunction)runXY     , METH_VARARGS,
-      "Evaluate the model at a given Q or Qx, Qy"},
-    {"reset",    (PyCFunction)reset   , METH_VARARGS,
-      "Reset pair correlation"},
-    //{"numerical_1D",      (PyCFunction)numerical_1D     , METH_VARARGS,
-    //  "Evaluate the 1D model at a given Q"},
-   {NULL}
-};
-
-static PyTypeObject CCylinderModelType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
-    "CCylinderModel",             /*tp_name*/
-    sizeof(CCylinderModel),             /*tp_basicsize*/
-    0,                         /*tp_itemsize*/
-    (destructor)CCylinderModel_dealloc, /*tp_dealloc*/
-    0,                         /*tp_print*/
-    0,                         /*tp_getattr*/
-    0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
-    0,                         /*tp_repr*/
-    0,                         /*tp_as_number*/
-    0,                         /*tp_as_sequence*/
-    0,                         /*tp_as_mapping*/
-    0,                         /*tp_hash */
-    0,                         /*tp_call*/
-    0,                         /*tp_str*/
-    0,                         /*tp_getattro*/
-    0,                         /*tp_setattro*/
-    0,                         /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
-    "CCylinderModel objects",           /* tp_doc */
-    0,		               /* tp_traverse */
-    0,		               /* tp_clear */
-    0,		               /* tp_richcompare */
-    0,		               /* tp_weaklistoffset */
-    0,		               /* tp_iter */
-    0,		               /* tp_iternext */
-    CCylinderModel_methods,             /* tp_methods */
-    CCylinderModel_members,             /* tp_members */
-    0,                         /* tp_getset */
-    0,                         /* tp_base */
-    0,                         /* tp_dict */
-    0,                         /* tp_descr_get */
-    0,                         /* tp_descr_set */
-    0,                         /* tp_dictoffset */
-    (initproc)CCylinderModel_init,      /* tp_init */
-    0,                         /* tp_alloc */
-    CCylinderModel_new,                 /* tp_new */
-};
-
-
-static PyMethodDef module_methods[] = {
-    {NULL}
-};
-
-/**
- * Function used to add the model class to a module
- * @param module: module to add the class to
- */
-void addCCylinderModel(PyObject *module) {
-	PyObject *d;
-
-    if (PyType_Ready(&CCylinderModelType) < 0)
-        return;
-
-    Py_INCREF(&CCylinderModelType);
-    PyModule_AddObject(module, "CCylinderModel", (PyObject *)&CCylinderModelType);
-
-    d = PyModule_GetDict(module);
-    CCylinderModelError = PyErr_NewException("CCylinderModel.error", NULL, NULL);
-    PyDict_SetItemString(d, "CCylinderModelError", CCylinderModelError);
-}
-
Index: sansmodels/src/sans/models/c_models/CCylinderModel.cpp
===================================================================
--- sansmodels/src/sans/models/c_models/CCylinderModel.cpp	(revision af03ddd0932915d6659404ab7824e4223ea2944f)
+++ sansmodels/src/sans/models/c_models/CCylinderModel.cpp	(revision af03ddd0932915d6659404ab7824e4223ea2944f)
@@ -0,0 +1,399 @@
+/**
+	This software was developed by the University of Tennessee as part of the
+	Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+	project funded by the US National Science Foundation.
+
+	If you use DANSE applications to do scientific research that leads to
+	publication, we ask that you acknowledge the use of the software with the
+	following sentence:
+
+	"This work benefited from DANSE software developed under NSF award DMR-0520547."
+
+	copyright 2008, University of Tennessee
+ */
+
+/** CCylinderModel
+ *
+ * C extension 
+ *
+ * WARNING: THIS FILE WAS GENERATED BY WRAPPERGENERATOR.PY
+ *          DO NOT MODIFY THIS FILE, MODIFY cylinder.h
+ *          AND RE-RUN THE GENERATOR SCRIPT
+ *
+ */
+ 
+extern "C" {
+#include <Python.h>
+#include "structmember.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <time.h>
+#include "cylinder.h"
+}
+
+#include "models.hh"
+#include "dispersion_visitor.hh"
+
+/// Error object for raised exceptions
+static PyObject * CCylinderModelError = NULL;
+
+
+// Class definition
+typedef struct {
+    PyObject_HEAD
+    /// Parameters
+    PyObject * params;
+    /// Dispersion parameters
+    PyObject * dispersion;
+    /// Underlying model object
+    CylinderModel * model;
+    /// Log for unit testing
+    PyObject * log;
+} CCylinderModel;
+
+
+static void
+CCylinderModel_dealloc(CCylinderModel* self)
+{
+    self->ob_type->tp_free((PyObject*)self);
+    
+
+}
+
+static PyObject *
+CCylinderModel_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    CCylinderModel *self;
+    
+    self = (CCylinderModel *)type->tp_alloc(type, 0);
+   
+    return (PyObject *)self;
+}
+
+static int
+CCylinderModel_init(CCylinderModel *self, PyObject *args, PyObject *kwds)
+{
+    if (self != NULL) {
+    	
+    	// Create parameters
+        self->params = PyDict_New();
+        self->dispersion = PyDict_New();
+        self->model = new CylinderModel();
+        
+        // Initialize parameter dictionary
+        PyDict_SetItemString(self->params,"scale",Py_BuildValue("d", self->model->scale()));
+        PyDict_SetItemString(self->params,"length",Py_BuildValue("d", self->model->length()));
+        PyDict_SetItemString(self->params,"cyl_theta",Py_BuildValue("d", self->model->cyl_theta()));
+        PyDict_SetItemString(self->params,"background",Py_BuildValue("d", self->model->background()));
+        PyDict_SetItemString(self->params,"radius",Py_BuildValue("d", self->model->radius()));
+        PyDict_SetItemString(self->params,"contrast",Py_BuildValue("d", self->model->contrast()));
+        PyDict_SetItemString(self->params,"cyl_phi",Py_BuildValue("d", self->model->cyl_phi()));
+        // Initialize dispersion / averaging parameter dict
+        DispersionVisitor* visitor = new DispersionVisitor();
+        PyObject * disp_dict;
+        disp_dict = PyDict_New();
+        self->model->radius.dispersion->accept_as_source(visitor, self->model->radius.dispersion, disp_dict);
+        PyDict_SetItemString(self->dispersion, "radius", disp_dict);
+        disp_dict = PyDict_New();
+        self->model->length.dispersion->accept_as_source(visitor, self->model->length.dispersion, disp_dict);
+        PyDict_SetItemString(self->dispersion, "length", disp_dict);
+        disp_dict = PyDict_New();
+        self->model->cyl_theta.dispersion->accept_as_source(visitor, self->model->cyl_theta.dispersion, disp_dict);
+        PyDict_SetItemString(self->dispersion, "cyl_theta", disp_dict);
+        disp_dict = PyDict_New();
+        self->model->cyl_phi.dispersion->accept_as_source(visitor, self->model->cyl_phi.dispersion, disp_dict);
+        PyDict_SetItemString(self->dispersion, "cyl_phi", disp_dict);
+
+
+         
+        // Create empty log
+        self->log = PyDict_New();
+        
+        
+
+    }
+    return 0;
+}
+
+static PyMemberDef CCylinderModel_members[] = {
+    {"params", T_OBJECT, offsetof(CCylinderModel, params), 0,
+     "Parameters"},
+	{"dispersion", T_OBJECT, offsetof(CCylinderModel, dispersion), 0,
+	  "Dispersion parameters"},     
+    {"log", T_OBJECT, offsetof(CCylinderModel, log), 0,
+     "Log"},
+    {NULL}  /* Sentinel */
+};
+
+/** Read double from PyObject
+    @param p PyObject
+    @return double
+*/
+double CCylinderModel_readDouble(PyObject *p) {
+    if (PyFloat_Check(p)==1) {
+        return (double)(((PyFloatObject *)(p))->ob_fval);
+    } else if (PyInt_Check(p)==1) {
+        return (double)(((PyIntObject *)(p))->ob_ival);
+    } else if (PyLong_Check(p)==1) {
+        return (double)PyLong_AsLong(p);
+    } else {
+        return 0.0;
+    }
+}
+
+
+/**
+ * Function to call to evaluate model
+ * @param args: input q or [q,phi]
+ * @return: function value
+ */
+static PyObject * run(CCylinderModel *self, PyObject *args) {
+	double q_value, phi_value;
+	PyObject* pars;
+	int npars;
+	
+	// Get parameters
+	
+	    // Reader parameter dictionary
+    self->model->scale = PyFloat_AsDouble( PyDict_GetItemString(self->params, "scale") );
+    self->model->length = PyFloat_AsDouble( PyDict_GetItemString(self->params, "length") );
+    self->model->cyl_theta = PyFloat_AsDouble( PyDict_GetItemString(self->params, "cyl_theta") );
+    self->model->background = PyFloat_AsDouble( PyDict_GetItemString(self->params, "background") );
+    self->model->radius = PyFloat_AsDouble( PyDict_GetItemString(self->params, "radius") );
+    self->model->contrast = PyFloat_AsDouble( PyDict_GetItemString(self->params, "contrast") );
+    self->model->cyl_phi = PyFloat_AsDouble( PyDict_GetItemString(self->params, "cyl_phi") );
+    // Read in dispersion parameters
+    PyObject* disp_dict;
+    DispersionVisitor* visitor = new DispersionVisitor();
+    disp_dict = PyDict_GetItemString(self->dispersion, "radius");
+    self->model->radius.dispersion->accept_as_destination(visitor, self->model->radius.dispersion, disp_dict);
+    disp_dict = PyDict_GetItemString(self->dispersion, "length");
+    self->model->length.dispersion->accept_as_destination(visitor, self->model->length.dispersion, disp_dict);
+    disp_dict = PyDict_GetItemString(self->dispersion, "cyl_theta");
+    self->model->cyl_theta.dispersion->accept_as_destination(visitor, self->model->cyl_theta.dispersion, disp_dict);
+    disp_dict = PyDict_GetItemString(self->dispersion, "cyl_phi");
+    self->model->cyl_phi.dispersion->accept_as_destination(visitor, self->model->cyl_phi.dispersion, disp_dict);
+
+	
+	// Get input and determine whether we have to supply a 1D or 2D return value.
+	if ( !PyArg_ParseTuple(args,"O",&pars) ) {
+	    PyErr_SetString(CCylinderModelError, 
+	    	"CCylinderModel.run expects a q value.");
+		return NULL;
+	}
+	  
+	// Check params
+	if( PyList_Check(pars)==1) {
+		
+		// Length of list should be 2 for I(q,phi)
+	    npars = PyList_GET_SIZE(pars); 
+	    if(npars!=2) {
+	    	PyErr_SetString(CCylinderModelError, 
+	    		"CCylinderModel.run expects a double or a list of dimension 2.");
+	    	return NULL;
+	    }
+	    // We have a vector q, get the q and phi values at which
+	    // to evaluate I(q,phi)
+	    q_value = CCylinderModel_readDouble(PyList_GET_ITEM(pars,0));
+	    phi_value = CCylinderModel_readDouble(PyList_GET_ITEM(pars,1));
+	    // Skip zero
+	    if (q_value==0) {
+	    	return Py_BuildValue("d",0.0);
+	    }
+		return Py_BuildValue("d",(*(self->model)).evaluate_rphi(q_value,phi_value));
+
+	} else {
+
+		// We have a scalar q, we will evaluate I(q)
+		q_value = CCylinderModel_readDouble(pars);		
+		
+		return Py_BuildValue("d",(*(self->model))(q_value));
+	}	
+}
+
+/**
+ * Function to call to evaluate model in cartesian coordinates
+ * @param args: input q or [qx, qy]]
+ * @return: function value
+ */
+static PyObject * runXY(CCylinderModel *self, PyObject *args) {
+	double qx_value, qy_value;
+	PyObject* pars;
+	int npars;
+	
+	// Get parameters
+	
+	    // Reader parameter dictionary
+    self->model->scale = PyFloat_AsDouble( PyDict_GetItemString(self->params, "scale") );
+    self->model->length = PyFloat_AsDouble( PyDict_GetItemString(self->params, "length") );
+    self->model->cyl_theta = PyFloat_AsDouble( PyDict_GetItemString(self->params, "cyl_theta") );
+    self->model->background = PyFloat_AsDouble( PyDict_GetItemString(self->params, "background") );
+    self->model->radius = PyFloat_AsDouble( PyDict_GetItemString(self->params, "radius") );
+    self->model->contrast = PyFloat_AsDouble( PyDict_GetItemString(self->params, "contrast") );
+    self->model->cyl_phi = PyFloat_AsDouble( PyDict_GetItemString(self->params, "cyl_phi") );
+    // Read in dispersion parameters
+    PyObject* disp_dict;
+    DispersionVisitor* visitor = new DispersionVisitor();
+    disp_dict = PyDict_GetItemString(self->dispersion, "radius");
+    self->model->radius.dispersion->accept_as_destination(visitor, self->model->radius.dispersion, disp_dict);
+    disp_dict = PyDict_GetItemString(self->dispersion, "length");
+    self->model->length.dispersion->accept_as_destination(visitor, self->model->length.dispersion, disp_dict);
+    disp_dict = PyDict_GetItemString(self->dispersion, "cyl_theta");
+    self->model->cyl_theta.dispersion->accept_as_destination(visitor, self->model->cyl_theta.dispersion, disp_dict);
+    disp_dict = PyDict_GetItemString(self->dispersion, "cyl_phi");
+    self->model->cyl_phi.dispersion->accept_as_destination(visitor, self->model->cyl_phi.dispersion, disp_dict);
+
+	
+	// Get input and determine whether we have to supply a 1D or 2D return value.
+	if ( !PyArg_ParseTuple(args,"O",&pars) ) {
+	    PyErr_SetString(CCylinderModelError, 
+	    	"CCylinderModel.run expects a q value.");
+		return NULL;
+	}
+	  
+	// Check params
+	if( PyList_Check(pars)==1) {
+		
+		// Length of list should be 2 for I(qx, qy))
+	    npars = PyList_GET_SIZE(pars); 
+	    if(npars!=2) {
+	    	PyErr_SetString(CCylinderModelError, 
+	    		"CCylinderModel.run expects a double or a list of dimension 2.");
+	    	return NULL;
+	    }
+	    // We have a vector q, get the qx and qy values at which
+	    // to evaluate I(qx,qy)
+	    qx_value = CCylinderModel_readDouble(PyList_GET_ITEM(pars,0));
+	    qy_value = CCylinderModel_readDouble(PyList_GET_ITEM(pars,1));
+	    return Py_BuildValue("d",(*(self->model))(qx_value,qy_value));
+
+	} else {
+
+		// We have a scalar q, we will evaluate I(q)
+		qx_value = CCylinderModel_readDouble(pars);		
+		
+		return Py_BuildValue("d",(*(self->model))(qx_value));
+	}	
+}
+
+static PyObject * reset(CCylinderModel *self, PyObject *args) {
+    
+
+    return Py_BuildValue("d",0.0);
+}
+
+static PyObject * set_dispersion(CCylinderModel *self, PyObject *args) {
+	PyObject * disp;
+	const char * par_name;
+
+	if ( !PyArg_ParseTuple(args,"sO", &par_name, &disp) ) {
+	    PyErr_SetString(CCylinderModelError,
+	    	"CCylinderModel.set_dispersion expects a DispersionModel object.");
+		return NULL;
+	}
+	void *temp = PyCObject_AsVoidPtr(disp);
+	DispersionModel * dispersion = static_cast<DispersionModel *>(temp);
+
+
+	// Ugliness necessary to go from python to C
+	    // TODO: refactor this
+    if (!strcmp(par_name, "radius")) {
+        self->model->radius.dispersion = dispersion;
+    } else    if (!strcmp(par_name, "length")) {
+        self->model->length.dispersion = dispersion;
+    } else    if (!strcmp(par_name, "cyl_theta")) {
+        self->model->cyl_theta.dispersion = dispersion;
+    } else    if (!strcmp(par_name, "cyl_phi")) {
+        self->model->cyl_phi.dispersion = dispersion;
+    } else {
+	    PyErr_SetString(CCylinderModelError,
+	    	"CCylinderModel.set_dispersion expects a valid parameter name.");
+		return NULL;
+	}
+
+	DispersionVisitor* visitor = new DispersionVisitor();
+	PyObject * disp_dict = PyDict_New();
+	dispersion->accept_as_source(visitor, dispersion, disp_dict);
+	PyDict_SetItemString(self->dispersion, par_name, disp_dict);
+    return Py_BuildValue("i",1);
+}
+
+
+static PyMethodDef CCylinderModel_methods[] = {
+    {"run",      (PyCFunction)run     , METH_VARARGS,
+      "Evaluate the model at a given Q or Q, phi"},
+    {"runXY",      (PyCFunction)runXY     , METH_VARARGS,
+      "Evaluate the model at a given Q or Qx, Qy"},
+    {"reset",    (PyCFunction)reset   , METH_VARARGS,
+      "Reset pair correlation"},
+    {"set_dispersion",      (PyCFunction)set_dispersion     , METH_VARARGS,
+      "Set the dispersion model for a given parameter"},
+   {NULL}
+};
+
+static PyTypeObject CCylinderModelType = {
+    PyObject_HEAD_INIT(NULL)
+    0,                         /*ob_size*/
+    "CCylinderModel",             /*tp_name*/
+    sizeof(CCylinderModel),             /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)CCylinderModel_dealloc, /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_compare*/
+    0,                         /*tp_repr*/
+    0,                         /*tp_as_number*/
+    0,                         /*tp_as_sequence*/
+    0,                         /*tp_as_mapping*/
+    0,                         /*tp_hash */
+    0,                         /*tp_call*/
+    0,                         /*tp_str*/
+    0,                         /*tp_getattro*/
+    0,                         /*tp_setattro*/
+    0,                         /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+    "CCylinderModel objects",           /* tp_doc */
+    0,		               /* tp_traverse */
+    0,		               /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    CCylinderModel_methods,             /* tp_methods */
+    CCylinderModel_members,             /* tp_members */
+    0,                         /* tp_getset */
+    0,                         /* tp_base */
+    0,                         /* tp_dict */
+    0,                         /* tp_descr_get */
+    0,                         /* tp_descr_set */
+    0,                         /* tp_dictoffset */
+    (initproc)CCylinderModel_init,      /* tp_init */
+    0,                         /* tp_alloc */
+    CCylinderModel_new,                 /* tp_new */
+};
+
+
+static PyMethodDef module_methods[] = {
+    {NULL} 
+};
+
+/**
+ * Function used to add the model class to a module
+ * @param module: module to add the class to
+ */ 
+void addCCylinderModel(PyObject *module) {
+	PyObject *d;
+	
+    if (PyType_Ready(&CCylinderModelType) < 0)
+        return;
+
+    Py_INCREF(&CCylinderModelType);
+    PyModule_AddObject(module, "CCylinderModel", (PyObject *)&CCylinderModelType);
+    
+    d = PyModule_GetDict(module);
+    CCylinderModelError = PyErr_NewException("CCylinderModel.error", NULL, NULL);
+    PyDict_SetItemString(d, "CCylinderModelError", CCylinderModelError);
+}
+
Index: sansmodels/src/sans/models/c_models/WrapperGenerator.py
===================================================================
--- sansmodels/src/sans/models/c_models/WrapperGenerator.py	(revision af03ddd0932915d6659404ab7824e4223ea2944f)
+++ sansmodels/src/sans/models/c_models/WrapperGenerator.py	(revision af03ddd0932915d6659404ab7824e4223ea2944f)
@@ -0,0 +1,366 @@
+#!/usr/bin/env python
+""" WrapperGenerator class to generate model code automatically.
+"""
+
+import os, sys
+
+class WrapperGenerator:
+    """ Python wrapper generator for C models
+    
+        The developer must provide a header file describing 
+        the new model.
+        
+        To provide the name of the Python class to be
+        generated, the .h file must contain the following 
+        string in the comments:
+        
+        // [PYTHONCLASS] = my_model
+        
+        where my_model must be replaced by the name of the
+        class that you want to import from sans.models.
+        (example: [PYTHONCLASS] = MyModel
+          will create a class MyModel in sans.models.MyModel.
+          It will also create a class CMyModel in 
+          sans_extension.c_models.)
+          
+        Also in comments, each parameter of the params 
+        dictionary must be declared with a default value
+        in the following way:
+        
+        // [DEFAULT]=param_name=default_value
+        
+        (example:
+            //  [DEFAULT]=radius=20.0
+        )
+          
+        See cylinder.h for an example.
+        
+        
+        A .c file corresponding to the .h file should also
+        be provided (example: my_model.h, my_model.c).
+    
+        The .h file should define two function definitions. For example,
+        cylinder.h defines the following:
+        
+            /// 1D scattering function
+            double cylinder_analytical_1D(CylinderParameters *pars, double q);
+            
+            /// 2D scattering function
+            double cylinder_analytical_2D(CylinderParameters *pars, double q, double phi);
+            
+        The .c file implements those functions.
+        
+        @author: Mathieu Doucet / UTK
+        @contact: mathieu.doucet@nist.gov
+    """
+    
+    def __init__(self, filename):
+        """ Initialization """
+        
+        ## Name of .h file to generate wrapper from
+        self.file = filename
+        
+        # Info read from file
+        
+        ## Name of python class to write
+        self.pythonClass = None
+        ## Parser in struct section
+        self.inStruct = False
+        ## Name of struct for the c object
+        self.structName = None
+        ## Dictionary of parameters
+        self.params = {}
+        ## ModelCalculation module flag
+        self.modelCalcFlag = False
+        ## List of default parameters (text)
+        self.default_list = ""
+        ## Dictionary of units
+        self.details = ""
+        ## List of dispersed parameters
+        self.disp_params = []
+        
+    def __repr__(self):
+        """ Simple output for printing """
+        
+        rep  = "Python class: %s\n" % self.pythonClass
+        rep += "  struc name: %s\n" % self.structName
+        rep += "  params:     %s\n" % self.params
+        return rep
+        
+    def read(self):
+        """ Reads in the .h file to catch parameters of the wrapper """
+        
+        # Check if the file is there
+        if not os.path.isfile(self.file):
+            raise ValueError, "File %s is not a regular file" % self.file
+        
+        # Read file
+        f = open(self.file,'r')
+        buf = f.read()
+        
+        self.default_list = "List of default parameters:\n"
+        #lines = string.split(buf,'\n')
+        lines = buf.split('\n')
+        self.details  = "## Parameter details [units, min, max]\n"
+        self.details += "        self.details = {}\n"
+        for line in lines:
+            
+            # Catch class name
+            key = "[PYTHONCLASS]"
+            if line.count(key)>0:
+                try:
+                    index = line.index(key)
+                    #toks = string.split( line[index:], "=" )
+                    toks = line[index:].split("=" )
+                    self.pythonClass = toks[1].lstrip().rstrip()
+                except:
+                    raise ValueError, "Could not parse file %s" % self.file
+                
+            # Catch struct name
+            if line.count("typedef struct")>0:
+                # We are entering a struct block
+                self.inStruct = True
+            
+            if self.inStruct and line.count("}")>0:
+                # We are exiting a struct block
+                self.inStruct = False
+    
+                # Catch the name of the struct
+                index = line.index("}")
+                #toks = string.split(line[index+1:],";")
+                toks = line[index+1:].split(";")
+                # Catch pointer definition
+                #toks2 = string.split(toks[0],',')
+                toks2 = toks[0].split(',')
+                self.structName = toks2[0].lstrip().rstrip()
+                
+            # Catch struct content
+            key = "[DEFAULT]"
+            if self.inStruct and line.count(key)>0:
+                # Found a new parameter
+                try:
+                    index = line.index(key)
+                    toks = line[index:].split("=")
+                    toks2 = toks[2].split()
+                    val = float(toks2[0])
+                    self.params[toks[1]] = val
+                    #self.pythonClass = toks[1].lstrip().rstrip()
+                    units = ""
+                    if len(toks2) >= 2:
+                        units = toks2[1]
+                    self.default_list += "         %-15s = %s %s\n" % \
+                        (toks[1], val, units)
+                    
+                    # Check for min and max
+                    min = "None"
+                    max = "None"
+                    if len(toks2) == 4:
+                        min = toks2[2]
+                        max = toks2[3]
+                    
+                    self.details += "        self.details['%s'] = ['%s', %s, %s]\n" % \
+                        (toks[1].lstrip().rstrip(), units.lstrip().rstrip(), min, max)
+                except:
+                    raise ValueError, "Could not parse input file %s \n  %s" % \
+                        (self.file, sys.exc_value)
+                
+                
+            # Catch need for numerical calculations
+            key = "CalcParameters calcPars"
+            if line.count(key)>0:
+                self.modelCalcFlag = True
+                
+            # Catch list of dispersed parameters 
+            key = "[DISP_PARAMS]"
+            if line.count(key)>0:
+                try:
+                    index = line.index(key)
+                    toks = line[index:].split("=")
+                    list_str = toks[1].lstrip().rstrip()
+                    self.disp_params = list_str.split(',')
+                except:
+                    raise ValueError, "Could not parse file %s" % self.file
+               
+                
+                
+    def write_c_wrapper(self):
+        """ Writes the C file to create the python extension class 
+            The file is written in C[PYTHONCLASS].c
+        """
+        
+        file = open("C"+self.pythonClass+'.cpp', 'w')
+        template = open("classTemplate.txt", 'r')
+        
+        tmp_buf = template.read()
+        #tmp_lines = string.split(tmp_buf,'\n')
+        tmp_lines = tmp_buf.split('\n')
+        
+        for tmp_line in tmp_lines:
+            
+            # Catch class name
+            newline = self.replaceToken(tmp_line, 
+                                        "[PYTHONCLASS]", 'C'+self.pythonClass)
+            
+            # Catch C model name
+            newline = self.replaceToken(newline, 
+                                        "[CMODEL]", self.pythonClass)
+            
+            # Catch class name
+            newline = self.replaceToken(newline, 
+                                        "[MODELSTRUCT]", self.structName)
+            
+            # Dictionary initialization
+            param_str = "// Initialize parameter dictionary\n"            
+            for par in self.params:
+                param_str += "        PyDict_SetItemString(self->params,\"%s\",Py_BuildValue(\"d\", self->model->%s()));\n" % \
+                    (par, par)
+
+            param_str += "        // Initialize dispersion / averaging parameter dict\n"
+            param_str += "        DispersionVisitor* visitor = new DispersionVisitor();\n"
+            param_str += "        PyObject * disp_dict;\n"
+            for par in self.disp_params:
+                par = par.strip()
+                param_str += "        disp_dict = PyDict_New();\n"
+                param_str += "        self->model->%s.dispersion->accept_as_source(visitor, self->model->%s.dispersion, disp_dict);\n" % (par, par)
+                param_str += "        PyDict_SetItemString(self->dispersion, \"%s\", disp_dict);\n" % par
+                
+            # Initialize dispersion object dictionnary
+            param_str += "\n"
+            
+                
+            newline = self.replaceToken(newline,
+                                        "[INITDICTIONARY]", param_str)
+            
+            # Read dictionary
+            param_str = "    // Reader parameter dictionary\n"
+            for par in self.params:
+                param_str += "    self->model->%s = PyFloat_AsDouble( PyDict_GetItemString(self->params, \"%s\") );\n" % \
+                    (par, par)
+                    
+            param_str += "    // Read in dispersion parameters\n"
+            param_str += "    PyObject* disp_dict;\n"
+            param_str += "    DispersionVisitor* visitor = new DispersionVisitor();\n"
+            for par in self.disp_params:
+                par = par.strip()
+                param_str += "    disp_dict = PyDict_GetItemString(self->dispersion, \"%s\");\n" % par
+                param_str += "    self->model->%s.dispersion->accept_as_destination(visitor, self->model->%s.dispersion, disp_dict);\n" % (par, par)
+                
+            newline = self.replaceToken(newline, "[READDICTIONARY]", param_str)
+                
+            # Name of .c file
+            #toks = string.split(self.file,'.')
+            basename = os.path.basename(self.file)
+            toks = basename.split('.')
+            newline = self.replaceToken(newline, "[C_FILENAME]", toks[0])
+            
+            # Include file
+            basename = os.path.basename(self.file)
+            newline = self.replaceToken(newline, 
+                                        "[INCLUDE_FILE]", basename)           
+                
+            # Numerical calcs dealloc
+            dealloc_str = "\n"
+            if self.modelCalcFlag:
+                dealloc_str = "    modelcalculations_dealloc(&(self->model_pars.calcPars));\n"
+            newline = self.replaceToken(newline, 
+                                        "[NUMERICAL_DEALLOC]", dealloc_str)     
+                
+            # Numerical calcs init
+            init_str = "\n"
+            if self.modelCalcFlag:
+                init_str = "        modelcalculations_init(&(self->model_pars.calcPars));\n"
+            newline = self.replaceToken(newline, 
+                                        "[NUMERICAL_INIT]", init_str)     
+                
+            # Numerical calcs reset
+            reset_str = "\n"
+            if self.modelCalcFlag:
+                reset_str = "modelcalculations_reset(&(self->model_pars.calcPars));\n"
+            newline = self.replaceToken(newline, 
+                                        "[NUMERICAL_RESET]", reset_str)     
+                
+            # Setting dispsertion weights
+            set_weights = "    // Ugliness necessary to go from python to C\n"
+            set_weights = "    // TODO: refactor this\n"
+            for par in self.disp_params:
+                par = par.strip()
+                set_weights += "    if (!strcmp(par_name, \"%s\")) {\n" % par
+                set_weights += "        self->model->%s.dispersion = dispersion;\n" % par
+                set_weights += "    } else"
+            newline = self.replaceToken(newline, 
+                                        "[SET_DISPERSION]", set_weights)     
+            
+            
+            # Write new line to the wrapper .c file
+            file.write(newline+'\n')
+            
+            
+        file.close()
+        
+    def write_python_wrapper(self):
+        """ Writes the python file to create the python extension class 
+            The file is written in ../[PYTHONCLASS].py
+        """
+        
+        file = open("../"+self.pythonClass+'.py', 'w')
+        template = open("modelTemplate.txt", 'r')
+        
+        tmp_buf = template.read()
+        tmp_lines = tmp_buf.split('\n')
+        
+        for tmp_line in tmp_lines:
+            
+            # Catch class name
+            newline = self.replaceToken(tmp_line, 
+                                        "[CPYTHONCLASS]", 'C'+self.pythonClass)
+            
+            # Catch class name
+            newline = self.replaceToken(newline, 
+                                        "[PYTHONCLASS]", self.pythonClass)
+            
+            # Include file
+            newline = self.replaceToken(newline, 
+                                        "[INCLUDE_FILE]", self.file)    
+                   
+            # Include file
+            newline = self.replaceToken(newline, 
+                                        "[DEFAULT_LIST]", self.default_list)
+
+            # Parameter details
+            newline = self.replaceToken(newline, 
+                                        "[PAR_DETAILS]", self.details)
+
+            # Write new line to the wrapper .c file
+            file.write(newline+'\n')
+               
+        file.close()
+        
+        
+    def replaceToken(self, line, key, value): #pylint: disable-msg=R0201
+        """ Replace a token in the template file 
+            @param line: line of text to inspect
+            @param key: token to look for
+            @param value: string value to replace the token with
+            @return: new string value
+        """
+        lenkey = len(key)
+        newline = line
+        while newline.count(key)>0:
+            index = newline.index(key)
+            newline = newline[:index]+value+newline[index+lenkey:]
+        return newline
+        
+        
+# main
+if __name__ == '__main__':
+    if len(sys.argv)>1:
+        print "Will look for file %s" % sys.argv[1]
+        app = WrapperGenerator(sys.argv[1])
+    else:
+        app = WrapperGenerator("test.h")
+    app.read()
+    app.write_c_wrapper()
+    app.write_python_wrapper()
+    print app
+   
+# End of file        
Index: sansmodels/src/sans/models/c_models/classTemplate.txt
===================================================================
--- sansmodels/src/sans/models/c_models/classTemplate.txt	(revision af03ddd0932915d6659404ab7824e4223ea2944f)
+++ sansmodels/src/sans/models/c_models/classTemplate.txt	(revision af03ddd0932915d6659404ab7824e4223ea2944f)
@@ -0,0 +1,324 @@
+/**
+	This software was developed by the University of Tennessee as part of the
+	Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+	project funded by the US National Science Foundation.
+
+	If you use DANSE applications to do scientific research that leads to
+	publication, we ask that you acknowledge the use of the software with the
+	following sentence:
+
+	"This work benefited from DANSE software developed under NSF award DMR-0520547."
+
+	copyright 2008, University of Tennessee
+ */
+
+/** [PYTHONCLASS]
+ *
+ * C extension 
+ *
+ * WARNING: THIS FILE WAS GENERATED BY WRAPPERGENERATOR.PY
+ *          DO NOT MODIFY THIS FILE, MODIFY [INCLUDE_FILE]
+ *          AND RE-RUN THE GENERATOR SCRIPT
+ *
+ */
+ 
+extern "C" {
+#include <Python.h>
+#include "structmember.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <time.h>
+#include "[INCLUDE_FILE]"
+}
+
+#include "models.hh"
+#include "dispersion_visitor.hh"
+
+/// Error object for raised exceptions
+static PyObject * [PYTHONCLASS]Error = NULL;
+
+
+// Class definition
+typedef struct {
+    PyObject_HEAD
+    /// Parameters
+    PyObject * params;
+    /// Dispersion parameters
+    PyObject * dispersion;
+    /// Underlying model object
+    [CMODEL] * model;
+    /// Log for unit testing
+    PyObject * log;
+} [PYTHONCLASS];
+
+
+static void
+[PYTHONCLASS]_dealloc([PYTHONCLASS]* self)
+{
+    self->ob_type->tp_free((PyObject*)self);
+    [NUMERICAL_DEALLOC]
+}
+
+static PyObject *
+[PYTHONCLASS]_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    [PYTHONCLASS] *self;
+    
+    self = ([PYTHONCLASS] *)type->tp_alloc(type, 0);
+   
+    return (PyObject *)self;
+}
+
+static int
+[PYTHONCLASS]_init([PYTHONCLASS] *self, PyObject *args, PyObject *kwds)
+{
+    if (self != NULL) {
+    	
+    	// Create parameters
+        self->params = PyDict_New();
+        self->dispersion = PyDict_New();
+        self->model = new [CMODEL]();
+        
+        [INITDICTIONARY]
+         
+        // Create empty log
+        self->log = PyDict_New();
+        
+        [NUMERICAL_INIT]
+    }
+    return 0;
+}
+
+static PyMemberDef [PYTHONCLASS]_members[] = {
+    {"params", T_OBJECT, offsetof([PYTHONCLASS], params), 0,
+     "Parameters"},
+	{"dispersion", T_OBJECT, offsetof([PYTHONCLASS], dispersion), 0,
+	  "Dispersion parameters"},     
+    {"log", T_OBJECT, offsetof([PYTHONCLASS], log), 0,
+     "Log"},
+    {NULL}  /* Sentinel */
+};
+
+/** Read double from PyObject
+    @param p PyObject
+    @return double
+*/
+double [PYTHONCLASS]_readDouble(PyObject *p) {
+    if (PyFloat_Check(p)==1) {
+        return (double)(((PyFloatObject *)(p))->ob_fval);
+    } else if (PyInt_Check(p)==1) {
+        return (double)(((PyIntObject *)(p))->ob_ival);
+    } else if (PyLong_Check(p)==1) {
+        return (double)PyLong_AsLong(p);
+    } else {
+        return 0.0;
+    }
+}
+
+
+/**
+ * Function to call to evaluate model
+ * @param args: input q or [q,phi]
+ * @return: function value
+ */
+static PyObject * run([PYTHONCLASS] *self, PyObject *args) {
+	double q_value, phi_value;
+	PyObject* pars;
+	int npars;
+	
+	// Get parameters
+	
+	[READDICTIONARY]
+	
+	// Get input and determine whether we have to supply a 1D or 2D return value.
+	if ( !PyArg_ParseTuple(args,"O",&pars) ) {
+	    PyErr_SetString([PYTHONCLASS]Error, 
+	    	"[PYTHONCLASS].run expects a q value.");
+		return NULL;
+	}
+	  
+	// Check params
+	if( PyList_Check(pars)==1) {
+		
+		// Length of list should be 2 for I(q,phi)
+	    npars = PyList_GET_SIZE(pars); 
+	    if(npars!=2) {
+	    	PyErr_SetString([PYTHONCLASS]Error, 
+	    		"[PYTHONCLASS].run expects a double or a list of dimension 2.");
+	    	return NULL;
+	    }
+	    // We have a vector q, get the q and phi values at which
+	    // to evaluate I(q,phi)
+	    q_value = [PYTHONCLASS]_readDouble(PyList_GET_ITEM(pars,0));
+	    phi_value = [PYTHONCLASS]_readDouble(PyList_GET_ITEM(pars,1));
+	    // Skip zero
+	    if (q_value==0) {
+	    	return Py_BuildValue("d",0.0);
+	    }
+		return Py_BuildValue("d",(*(self->model)).evaluate_rphi(q_value,phi_value));
+
+	} else {
+
+		// We have a scalar q, we will evaluate I(q)
+		q_value = [PYTHONCLASS]_readDouble(pars);		
+		
+		return Py_BuildValue("d",(*(self->model))(q_value));
+	}	
+}
+
+/**
+ * Function to call to evaluate model in cartesian coordinates
+ * @param args: input q or [qx, qy]]
+ * @return: function value
+ */
+static PyObject * runXY([PYTHONCLASS] *self, PyObject *args) {
+	double qx_value, qy_value;
+	PyObject* pars;
+	int npars;
+	
+	// Get parameters
+	
+	[READDICTIONARY]
+	
+	// Get input and determine whether we have to supply a 1D or 2D return value.
+	if ( !PyArg_ParseTuple(args,"O",&pars) ) {
+	    PyErr_SetString([PYTHONCLASS]Error, 
+	    	"[PYTHONCLASS].run expects a q value.");
+		return NULL;
+	}
+	  
+	// Check params
+	if( PyList_Check(pars)==1) {
+		
+		// Length of list should be 2 for I(qx, qy))
+	    npars = PyList_GET_SIZE(pars); 
+	    if(npars!=2) {
+	    	PyErr_SetString([PYTHONCLASS]Error, 
+	    		"[PYTHONCLASS].run expects a double or a list of dimension 2.");
+	    	return NULL;
+	    }
+	    // We have a vector q, get the qx and qy values at which
+	    // to evaluate I(qx,qy)
+	    qx_value = [PYTHONCLASS]_readDouble(PyList_GET_ITEM(pars,0));
+	    qy_value = [PYTHONCLASS]_readDouble(PyList_GET_ITEM(pars,1));
+	    return Py_BuildValue("d",(*(self->model))(qx_value,qy_value));
+
+	} else {
+
+		// We have a scalar q, we will evaluate I(q)
+		qx_value = [PYTHONCLASS]_readDouble(pars);		
+		
+		return Py_BuildValue("d",(*(self->model))(qx_value));
+	}	
+}
+
+static PyObject * reset([PYTHONCLASS] *self, PyObject *args) {
+    [NUMERICAL_RESET]
+    return Py_BuildValue("d",0.0);
+}
+
+static PyObject * set_dispersion([PYTHONCLASS] *self, PyObject *args) {
+	PyObject * disp;
+	const char * par_name;
+
+	if ( !PyArg_ParseTuple(args,"sO", &par_name, &disp) ) {
+	    PyErr_SetString([PYTHONCLASS]Error,
+	    	"[PYTHONCLASS].set_dispersion expects a DispersionModel object.");
+		return NULL;
+	}
+	void *temp = PyCObject_AsVoidPtr(disp);
+	DispersionModel * dispersion = static_cast<DispersionModel *>(temp);
+
+
+	// Ugliness necessary to go from python to C
+	[SET_DISPERSION] {
+	    PyErr_SetString([PYTHONCLASS]Error,
+	    	"[PYTHONCLASS].set_dispersion expects a valid parameter name.");
+		return NULL;
+	}
+
+	DispersionVisitor* visitor = new DispersionVisitor();
+	PyObject * disp_dict = PyDict_New();
+	dispersion->accept_as_source(visitor, dispersion, disp_dict);
+	PyDict_SetItemString(self->dispersion, par_name, disp_dict);
+    return Py_BuildValue("i",1);
+}
+
+
+static PyMethodDef [PYTHONCLASS]_methods[] = {
+    {"run",      (PyCFunction)run     , METH_VARARGS,
+      "Evaluate the model at a given Q or Q, phi"},
+    {"runXY",      (PyCFunction)runXY     , METH_VARARGS,
+      "Evaluate the model at a given Q or Qx, Qy"},
+    {"reset",    (PyCFunction)reset   , METH_VARARGS,
+      "Reset pair correlation"},
+    {"set_dispersion",      (PyCFunction)set_dispersion     , METH_VARARGS,
+      "Set the dispersion model for a given parameter"},
+   {NULL}
+};
+
+static PyTypeObject [PYTHONCLASS]Type = {
+    PyObject_HEAD_INIT(NULL)
+    0,                         /*ob_size*/
+    "[PYTHONCLASS]",             /*tp_name*/
+    sizeof([PYTHONCLASS]),             /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)[PYTHONCLASS]_dealloc, /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_compare*/
+    0,                         /*tp_repr*/
+    0,                         /*tp_as_number*/
+    0,                         /*tp_as_sequence*/
+    0,                         /*tp_as_mapping*/
+    0,                         /*tp_hash */
+    0,                         /*tp_call*/
+    0,                         /*tp_str*/
+    0,                         /*tp_getattro*/
+    0,                         /*tp_setattro*/
+    0,                         /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+    "[PYTHONCLASS] objects",           /* tp_doc */
+    0,		               /* tp_traverse */
+    0,		               /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    [PYTHONCLASS]_methods,             /* tp_methods */
+    [PYTHONCLASS]_members,             /* tp_members */
+    0,                         /* tp_getset */
+    0,                         /* tp_base */
+    0,                         /* tp_dict */
+    0,                         /* tp_descr_get */
+    0,                         /* tp_descr_set */
+    0,                         /* tp_dictoffset */
+    (initproc)[PYTHONCLASS]_init,      /* tp_init */
+    0,                         /* tp_alloc */
+    [PYTHONCLASS]_new,                 /* tp_new */
+};
+
+
+static PyMethodDef module_methods[] = {
+    {NULL} 
+};
+
+/**
+ * Function used to add the model class to a module
+ * @param module: module to add the class to
+ */ 
+void add[PYTHONCLASS](PyObject *module) {
+	PyObject *d;
+	
+    if (PyType_Ready(&[PYTHONCLASS]Type) < 0)
+        return;
+
+    Py_INCREF(&[PYTHONCLASS]Type);
+    PyModule_AddObject(module, "[PYTHONCLASS]", (PyObject *)&[PYTHONCLASS]Type);
+    
+    d = PyModule_GetDict(module);
+    [PYTHONCLASS]Error = PyErr_NewException("[PYTHONCLASS].error", NULL, NULL);
+    PyDict_SetItemString(d, "[PYTHONCLASS]Error", [PYTHONCLASS]Error);
+}
Index: sansmodels/src/sans/models/c_models/cylinder.cpp
===================================================================
--- sansmodels/src/sans/models/c_models/cylinder.cpp	(revision fca6936ab3704433fa2327bcd55367e8ea28de72)
+++ sansmodels/src/sans/models/c_models/cylinder.cpp	(revision af03ddd0932915d6659404ab7824e4223ea2944f)
@@ -32,5 +32,5 @@
 }
 
-Cylinder :: Cylinder() {
+CylinderModel :: CylinderModel() {
 	scale      = Parameter(1.0);
 	radius     = Parameter(20.0, true);
@@ -50,5 +50,5 @@
  * @return: function value
  */
-double Cylinder :: operator()(double q) {
+double CylinderModel :: operator()(double q) {
 	double dp[5];
 
@@ -96,5 +96,5 @@
  * @return: function value
  */
-double Cylinder :: operator()(double qx, double qy) {
+double CylinderModel :: operator()(double qx, double qy) {
 	CylinderParameters dp;
 	// Fill parameter array
@@ -177,5 +177,5 @@
  * @return: function value
  */
-double Cylinder :: evaluate_rphi(double q, double phi) {
+double CylinderModel :: evaluate_rphi(double q, double phi) {
 	double qx = q*cos(phi);
 	double qy = q*sin(phi);
@@ -186,5 +186,5 @@
 int main(void)
 {
-	Cylinder c = Cylinder();
+	CylinderModel c = CylinderModel();
 
 	printf("Length = %g\n", c.length());
Index: sansmodels/src/sans/models/c_models/dispersion_models.py
===================================================================
--- sansmodels/src/sans/models/c_models/dispersion_models.py	(revision af03ddd0932915d6659404ab7824e4223ea2944f)
+++ sansmodels/src/sans/models/c_models/dispersion_models.py	(revision af03ddd0932915d6659404ab7824e4223ea2944f)
@@ -0,0 +1,100 @@
+"""
+    This software was developed by the University of Tennessee as part of the
+    Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+    project funded by the US National Science Foundation.
+
+    If you use DANSE applications to do scientific research that leads to
+    publication, we ask that you acknowledge the use of the software with the
+    following sentence:
+
+    "This work benefited from DANSE software developed under NSF award DMR-0520547."
+
+    copyright 2008, University of Tennessee
+"""
+
+"""
+    Class definitions for python dispersion model for 
+    model parameters. These classes are bridges to the C++
+    dispersion object.
+    
+    The ArrayDispersion class takes in numpy arrays only.
+    
+    Usage:
+    These classes can be used to set the dispersion model of a SANS model
+    parameter:
+    
+        cyl = CylinderModel()
+        cyl.set_dispersion('radius', GaussianDispersion())
+    
+    
+    After the dispersion model is set, you can access it's
+    parameter through the dispersion dictionary:
+    
+        cyl.dispersion['radius']['width'] = 5.0
+    
+    TODO: For backward compatibility, the model parameters are still kept in
+    a dictionary. The next iteration of refactoring work should involve moving
+    away from value-based parameters to object-based parameter. We want to
+    store parameters as objects so that we can unify the 'params' and 'dispersion'
+    dictionaries into a single dictionary of parameter objects that hold the
+    complete information about the parameter (units, limits, dispersion model, etc...).  
+    
+    
+"""
+import sans_extension.c_models as c_models 
+
+class DispersionModel:
+    """
+        Python bridge class for a basic dispersion model 
+        class with a constant parameter value distribution
+    """
+    def __init__(self):
+        self.cdisp = c_models.new_dispersion_model()
+        
+    def set_weights(self, values, weights):
+        """
+            Set the weights of an array dispersion
+        """
+        message = "set_weights is not available for DispersionModel.\n"
+        message += "  Solution: Use an ArrayDispersion object"
+        raise "RuntimeError", message
+        
+class GaussianDispersion(DispersionModel):
+    """
+        Python bridge class for a dispersion model based 
+        on a Gaussian distribution.
+    """
+    def __init__(self):
+        self.cdisp = c_models.new_gaussian_model()
+        
+    def set_weights(self, values, weights):
+        """
+            Set the weights of an array dispersion
+        """
+        message = "set_weights is not available for GaussiantDispersion.\n"
+        message += "  Solution: Use an ArrayDispersion object"
+        raise "RuntimeError", message
+        
+class ArrayDispersion(DispersionModel):
+    """
+        Python bridge class for a dispersion model based on arrays.
+        The user has to set a weight distribution that
+        will be used in the averaging the model parameter
+        it is applied to. 
+    """
+    def __init__(self):
+        self.cdisp = c_models.new_array_model()
+        
+    def set_weights(self, values, weights):
+        """
+            Set the weights of an array dispersion
+            Only accept numpy arrays.
+            @param values: numpy array of values
+            @param weights: numpy array of weights for each value entry
+        """
+        if len(values) != len(weights):
+            raise ValueError, "ArrayDispersion.set_weights: given arrays are of different lengths"
+        
+        c_models.set_dispersion_weights(self.cdisp, values, weights)
+        
+        
Index: sansmodels/src/sans/models/c_models/modelTemplate.txt
===================================================================
--- sansmodels/src/sans/models/c_models/modelTemplate.txt	(revision af03ddd0932915d6659404ab7824e4223ea2944f)
+++ sansmodels/src/sans/models/c_models/modelTemplate.txt	(revision af03ddd0932915d6659404ab7824e4223ea2944f)
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+"""
+	This software was developed by the University of Tennessee as part of the
+	Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+	project funded by the US National Science Foundation.
+
+	If you use DANSE applications to do scientific research that leads to
+	publication, we ask that you acknowledge the use of the software with the
+	following sentence:
+
+	"This work benefited from DANSE software developed under NSF award DMR-0520547."
+
+	copyright 2008, University of Tennessee
+"""
+
+""" Provide functionality for a C extension model
+
+	WARNING: THIS FILE WAS GENERATED BY WRAPPERGENERATOR.PY
+ 	         DO NOT MODIFY THIS FILE, MODIFY [INCLUDE_FILE]
+ 	         AND RE-RUN THE GENERATOR SCRIPT
+
+"""
+
+from sans.models.BaseComponent import BaseComponent
+from sans_extension.c_models import [CPYTHONCLASS]
+import copy    
+    
+class [PYTHONCLASS]([CPYTHONCLASS], BaseComponent):
+    """ Class that evaluates a [PYTHONCLASS] model. 
+    	This file was auto-generated from [INCLUDE_FILE].
+    	Refer to that file and the structure it contains
+    	for details of the model.
+    	[DEFAULT_LIST]
+    """
+        
+    def __init__(self):
+        """ Initialization """
+        
+        # Initialize BaseComponent first, then sphere
+        BaseComponent.__init__(self)
+        [CPYTHONCLASS].__init__(self)
+        
+        ## Name of the model
+        self.name = "[PYTHONCLASS]"
+
+		[PAR_DETAILS]
+   
+    def clone(self):
+        """ Return a identical copy of self """
+        obj = [PYTHONCLASS]()
+        obj.params = copy.deepcopy(self.params)
+        return obj   
+   
+    def run(self, x = 0.0):
+        """ Evaluate the model
+            @param x: input q, or [q,phi]
+            @return: scattering function P(q)
+        """
+        
+        return [CPYTHONCLASS].run(self, x)
+   
+    def runXY(self, x = 0.0):
+        """ Evaluate the model in cartesian coordinates
+            @param x: input q, or [qx, qy]
+            @return: scattering function P(q)
+        """
+        
+        return [CPYTHONCLASS].runXY(self, x)
+        
+    def set_dispersion(self, parameter, dispersion):
+        """
+            Set the dispersion object for a model parameter
+            @param parameter: name of the parameter [string]
+            @dispersion: dispersion object of type DispersionModel
+        """
+        return [CPYTHONCLASS].set_dispersion(self, parameter, dispersion.cdisp)
+        
+   
+# End of file
Index: sansmodels/src/sans/models/c_models/models.hh
===================================================================
--- sansmodels/src/sans/models/c_models/models.hh	(revision fca6936ab3704433fa2327bcd55367e8ea28de72)
+++ sansmodels/src/sans/models/c_models/models.hh	(revision af03ddd0932915d6659404ab7824e4223ea2944f)
@@ -23,5 +23,5 @@
 using namespace std;
 
-class Cylinder{
+class CylinderModel{
 
 public:
@@ -37,5 +37,5 @@
 
 	// Constructor
-	Cylinder();
+	CylinderModel();
 
 	// Operators to get I(Q)
Index: sansmodels/src/sans/models/test/utest_models.py
===================================================================
--- sansmodels/src/sans/models/test/utest_models.py	(revision ae3ce4eaa593202ebf49122e196897c0d45a25b6)
+++ sansmodels/src/sans/models/test/utest_models.py	(revision af03ddd0932915d6659404ab7824e4223ea2944f)
@@ -50,4 +50,6 @@
     def test2D(self):
         """ Test 2D model of a cylinder """ 
+        self.comp.setParam('cyl_theta', 1.0)
+        self.comp.setParam('cyl_phi', 1.0)
         self.assertAlmostEqual(self.comp.run([0.2, 2.5]), 
                                0.038176446608393366, 4)
Index: sansmodels/src/setup.py
===================================================================
--- sansmodels/src/setup.py	(revision ae3ce4eaa593202ebf49122e196897c0d45a25b6)
+++ sansmodels/src/setup.py	(revision af03ddd0932915d6659404ab7824e4223ea2944f)
@@ -92,8 +92,12 @@
     ext_modules = [ Extension("sans_extension.c_models",
      sources = [
-        srcdir+"/c_models.c",
+        srcdir+"/c_models.cpp",
         srcdir+"/CSphereModel.c",
         srcdir+"/sphere.c",
-        srcdir+"/CCylinderModel.c",
+        #srcdir+"/CCylinderModel.c",
+        "sans/models/c_models/CCylinderModel.cpp",
+        "sans/models/c_models/cylinder.cpp",
+        "sans/models/c_models/parameters.cpp",
+        "sans/models/c_models/dispersion_visitor.cpp",
         srcdir+"/cylinder.c",
         srcdir+"/CCoreShellCylinderModel.c",
@@ -113,4 +117,4 @@
         srcdir+"/CLorentzian.c"
             ],
-         include_dirs=[igordir])])
+         include_dirs=[igordir,srcdir,"sans/models/c_models"])])
         
