Index: src/sas/models/c_extension/python_wrapper/WrapperGenerator.py
===================================================================
--- src/sas/models/c_extension/python_wrapper/WrapperGenerator.py	(revision 794922220f2fb3b23dd08c648aabf87b4850596c)
+++ src/sas/models/c_extension/python_wrapper/WrapperGenerator.py	(revision 794922220f2fb3b23dd08c648aabf87b4850596c)
@@ -0,0 +1,596 @@
+#!/usr/bin/env python
+""" WrapperGenerator class to generate model code automatically.
+"""
+
+import os, sys,re
+import lineparser
+
+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, output_dir='.', c_wrapper_dir='.'):
+        """ 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
+        self.foundCPP = False
+        self.inParDefs = 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 = []
+        #model description
+        self.description=''
+        # paramaters for fittable
+        self.fixed= []
+        # paramaters for non-fittable
+        self.non_fittable= []
+        ## parameters with orientation
+        self.orientation_params =[]
+        ## parameter with magnetism
+        self.magentic_params = []
+        # Model category
+        self.category = None
+        # Whether model belongs to multifunc
+        self.is_multifunc = False
+        ## output directory for wrappers
+        self.output_dir = output_dir
+        self.c_wrapper_dir = c_wrapper_dir
+
+        
+        
+    def __repr__(self):
+        """ Simple output for printing """
+        
+        rep  = "\n Python class: %s\n\n" % self.pythonClass
+        rep += "  struc name: %s\n\n" % self.structName
+        rep += "  params:     %s\n\n" % self.params
+        rep += "  description:    %s\n\n" % self.description
+        rep += "  Fittable parameters:     %s\n\n"% self.fixed
+        rep += "  Non-Fittable parameters:     %s\n\n"% self.non_fittable
+        rep += "  Orientation parameters:  %s\n\n"% self.orientation_params
+        rep += "  Magnetic parameters:  %s\n\n"% self.magnetic_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 = "\n    List of default parameters:\n\n"
+        #lines = string.split(buf,'\n')
+        lines = buf.split('\n')
+        self.details  = "## Parameter details [units, min, max]\n"
+        self.details += "        self.details = {}\n"
+        
+        #open item in this case Fixed
+        text='text'
+        key2="<%s>"%text.lower()
+        # close an item in this case fixed
+        text='TexT'
+        key3="</%s>"%text.lower()
+        
+        ## Catch fixed parameters
+        key = "[FIXED]"
+        try:
+            self.fixed= lineparser.readhelper(lines, key, 
+                                              key2, key3, file=self.file)
+        except:
+           raise   
+        ## Catch non-fittable parameters parameters
+        key = "[NON_FITTABLE_PARAMS]"
+        try:
+            self.non_fittable= lineparser.readhelper(lines, key, key2,
+                                                     key3, file=self.file)
+        except:
+           raise   
+
+        ## Catch parameters with orientation
+        key = "[ORIENTATION_PARAMS]"    
+        try:
+            self.orientation_params = lineparser.readhelper(lines, key, 
+                                                    key2, key3, file=self.file)
+        except:
+           raise 
+       
+        ## Catch parameters with orientation
+        key = "[MAGNETIC_PARAMS]"    
+        try:
+            self.magnetic_params = lineparser.readhelper( lines,key, 
+                                                    key2,key3, file= self.file)
+        except:
+           raise 
+       
+        ## Catch Description
+        key = "[DESCRIPTION]"
+        
+        find_description = False
+        temp=""
+        for line in lines:
+            if line.count(key)>0 :
+                
+                try:
+                    find_description= True
+                    index = line.index(key)
+                    toks = line[index:].split("=",1 )
+                    temp=toks[1].lstrip().rstrip()
+                    text='text'
+                    key2="<%s>"%text.lower()
+                    if re.match(key2,temp)!=None:
+    
+                        toks2=temp.split(key2,1)
+                        self.description=toks2[1]
+                        text='text'
+                        key2="</%s>"%text.lower()
+                        if re.search(key2,toks2[1])!=None:
+                            temp=toks2[1].split(key2,1)
+                            self.description=temp[0]
+                            break
+                      
+                    else:
+                        self.description=temp
+                        break
+                except:
+                     raise ValueError, "Could not parse file %s" % self.file
+            elif find_description:
+                text='text'
+                key2="</%s>"%text.lower()
+                if re.search(key2,line)!=None:
+                    tok=line.split(key2,1)
+                    temp=tok[0].split("//",1)
+                    self.description+=tok[1].lstrip().rstrip()
+                    break
+                else:
+                    if re.search("//",line)!=None:
+                        temp=line.split("//",1)
+                        self.description+='\n\t\t'+temp[1].lstrip().rstrip()
+                        
+                    else:
+                        self.description+='\n\t\t'+line.lstrip().rstrip()
+                    
+                
+     
+        for line in lines:
+            
+            # Catch class name
+            key = "[PYTHONCLASS]"
+            if line.count(key)>0:
+                try:
+                    index = line.index(key)
+                    toks = line[index:].split("=" )
+                    self.pythonClass = toks[1].lstrip().rstrip()
+
+                except:
+                    raise ValueError, "Could not parse file %s" % self.file
+                
+            key = "[CATEGORY]"
+            if line.count(key)>0:
+                try:
+                    index = line.index(key)
+                    toks = line[index:].split("=")
+                    self.category = toks[1].lstrip().rstrip()
+
+                except:
+                    raise ValueError, "Could not parse file %s" % self.file
+
+            # is_multifunc
+            key = "[MULTIPLICITY_INFO]"
+            if line.count(key) > 0:
+                self.is_multifunc = True
+                try:
+                    index = line.index(key)
+                    toks = line[index:].split("=")
+                    self.multiplicity_info = toks[1].lstrip().rstrip()
+                except:
+                    raise ValueError, "Could not parse file %s" % self.file
+
+            # Catch struct name
+            # C++ class definition
+            if line.count("class")>0:
+                # We are entering a class definition
+                self.inParDefs = True
+                self.foundCPP = True
+                
+            # Old-Style C struct definition
+            if line.count("typedef struct")>0:
+                # We are entering a struct block
+                self.inParDefs = True
+                self.inStruct = True
+            
+            if self.inParDefs and line.count("}")>0:
+                # We are exiting a struct block
+                self.inParDefs = False
+                
+                if self.inStruct:
+                    self.inStruct = False
+                    # Catch the name of the struct
+                    index = line.index("}")
+                    toks = line[index+1:].split(";")
+                    # Catch pointer definition
+                    toks2 = toks[0].split(',')
+                    self.structName = toks2[0].lstrip().rstrip()
+           
+            # Catch struct content
+            key = "[DEFAULT]"
+            if self.inParDefs 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_path = os.path.join(self.c_wrapper_dir, 
+                                 "C"+self.pythonClass+'.cpp')
+        file = open(file_path, 'w')
+        
+        template = open(os.path.join(os.path.dirname(__file__), 
+                                     "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 model description
+            #newline = self.replaceToken(tmp_line, 
+            #                            "[DESCRIPTION]", self.description)
+            # Catch C model name
+            newline = self.replaceToken(newline, 
+                                        "[CMODEL]", self.pythonClass)
+            
+            # Catch class name
+            newline = self.replaceToken(newline, 
+                                        "[MODELSTRUCT]", self.structName)
+
+            # Sort model initialization based on multifunc
+            if(self.is_multifunc):
+                line = "int level = 1;\nPyArg_ParseTuple(args,\"i\",&level);\n"
+                line += "self->model = new " + self.pythonClass + "(level);"
+            else:
+                line = "self->model = new " + self.pythonClass + "();"
+    
+            newline = self.replaceToken(newline,"[INITIALIZE_MODEL]",
+                                            line)
+            
+            # Dictionary initialization
+            param_str = "// Initialize parameter dictionary\n"            
+            for par in self.params:
+                param_str += "        PyDict_SetItemString(self->params,\"%s\",Py_BuildValue(\"d\",%10.12f));\n" % \
+                    (par, self.params[par])
+
+            if len(self.disp_params)>0:
+                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()
+                    if par == '':
+                        continue
+                    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)
+                    
+            if len(self.disp_params)>0:
+                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()
+                    if par == '':
+                        continue
+                    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]", self.file)  
+            if self.foundCPP:
+                newline = self.replaceToken(newline, 
+                            "[C_INCLUDE_FILE]", "")  
+                newline = self.replaceToken(newline, 
+                            "[CPP_INCLUDE_FILE]", "#include \"%s\"" % basename)  
+            else:  
+                newline = self.replaceToken(newline, 
+                            "[C_INCLUDE_FILE]", "#include \"%s\"" % basename)   
+                newline = self.replaceToken(newline, 
+                            "[CPP_INCLUDE_FILE]", "#include \"models.hh\"")  
+                
+            # 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()
+                if par == '':
+                        continue
+                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_path = os.path.join(self.output_dir, self.pythonClass+'.py')
+        file = open(file_path, 'w')
+        template = open(os.path.join(os.path.dirname(__file__), 
+                                     "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)
+            # model description
+            newline = self.replaceToken(newline, 
+                                        "[DESCRIPTION]", self.description)
+            # Parameter details
+            newline = self.replaceToken(newline, 
+                                        "[PAR_DETAILS]", self.details)
+            
+            # Call base constructor
+            if self.is_multifunc:
+                newline = self.replaceToken(newline,"[CALL_CPYTHON_INIT]",
+                    'C' + self.pythonClass + \
+                    ".__init__(self,multfactor)\n\tself.is_multifunc = True")
+                newline = self.replaceToken(newline,"[MULTIPLICITY_INFO]", 
+                                            self.multiplicity_info)
+            else:
+                newline = self.replaceToken(newline,"[CALL_CPYTHON_INIT]",
+                    'C' + self.pythonClass + \
+                    ".__init__(self)\n        self.is_multifunc = False")
+                newline = self.replaceToken(newline, 
+                                            "[MULTIPLICITY_INFO]", "None")
+
+           
+            # fixed list  details
+            fixed_str = str(self.fixed)
+            fixed_str = fixed_str.replace(', ', ',\n                      ')
+            newline = self.replaceToken(newline, "[FIXED]", fixed_str)
+            
+            # non-fittable list details
+            pars_str = str(self.non_fittable)
+            pars_str = pars_str.replace(', ', 
+                                        ',\n                             ')
+            newline = self.replaceToken(newline, 
+                                        "[NON_FITTABLE_PARAMS]", pars_str)
+            
+            ## parameters with orientation
+            oriented_str = str(self.orientation_params)
+            formatted_endl = ',\n                                   '
+            oriented_str = oriented_str.replace(', ', formatted_endl)
+            newline = self.replaceToken(newline, 
+                               "[ORIENTATION_PARAMS]", oriented_str)
+           ## parameters with magnetism
+            newline = self.replaceToken(newline, 
+                               "[MAGNETIC_PARAMS]", str(self.magnetic_params))
+
+            if self.category:
+                newline = self.replaceToken(newline, "[CATEGORY]", 
+                                            '"' + self.category + '"')
+            else:
+                newline = self.replaceToken(newline, "[CATEGORY]",
+                                            "None")
+            
+
+
+            # 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
+        
+    def getModelName(self):
+        return self.pythonClass
+        
+
+
+# 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: src/sas/models/c_extension/python_wrapper/classTemplate.txt
===================================================================
--- src/sas/models/c_extension/python_wrapper/classTemplate.txt	(revision 794922220f2fb3b23dd08c648aabf87b4850596c)
+++ src/sas/models/c_extension/python_wrapper/classTemplate.txt	(revision 794922220f2fb3b23dd08c648aabf87b4850596c)
@@ -0,0 +1,507 @@
+/**
+	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
+ *
+ */
+#define NO_IMPORT_ARRAY
+#define PY_ARRAY_UNIQUE_SYMBOL PyArray_API_sans
+ 
+extern "C" {
+#include <Python.h>
+#include <arrayobject.h>
+#include "structmember.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <time.h>
+[C_INCLUDE_FILE]
+}
+
+[CPP_INCLUDE_FILE]
+#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)
+{
+    Py_DECREF(self->params);
+    Py_DECREF(self->dispersion);
+    Py_DECREF(self->log);
+    delete self->model;
+    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();
+
+	[INITIALIZE_MODEL]
+
+        [INITDICTIONARY]
+         
+        // Create empty log
+        self->log = PyDict_New();
+        
+        [NUMERICAL_INIT]
+    }
+    return 0;
+}
+
+static char name_params[] = "params";
+static char def_params[] = "Parameters";
+static char name_dispersion[] = "dispersion";
+static char def_dispersion[] = "Dispersion parameters";
+static char name_log[] = "log";
+static char def_log[] = "Log";
+
+static PyMemberDef [PYTHONCLASS]_members[] = {
+    {name_params, T_OBJECT, offsetof([PYTHONCLASS], params), 0, def_params},
+	{name_dispersion, T_OBJECT, offsetof([PYTHONCLASS], dispersion), 0, def_dispersion},     
+    {name_log, T_OBJECT, offsetof([PYTHONCLASS], log), 0, def_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 numpy array q[] 
+ * @return: numpy array object 
+ */
+ 
+static PyObject *evaluateOneDim([CMODEL]* model, PyArrayObject *q){
+    PyArrayObject *result;
+   
+    // Check validity of array q , q must be of dimension 1, an array of double
+    if (q->nd != 1 || q->descr->type_num != PyArray_DOUBLE)
+    {
+        //const char * message= "Invalid array: q->nd=%d,type_num=%d\n",q->nd,q->descr->type_num;
+        //PyErr_SetString(PyExc_ValueError , message);
+        return NULL;
+    }
+    result = (PyArrayObject *)PyArray_FromDims(q->nd, (int *)(q->dimensions), PyArray_DOUBLE);
+	if (result == NULL) {
+        const char * message= "Could not create result ";
+        PyErr_SetString(PyExc_RuntimeError , message);
+		return NULL;
+	}
+#pragma omp parallel for
+	 for (int i = 0; i < q->dimensions[0]; i++){
+      double q_value  = *(double *)(q->data + i*q->strides[0]);
+      double *result_value = (double *)(result->data + i*result->strides[0]);
+      *result_value =(*model)(q_value);
+	}
+    return PyArray_Return(result); 
+ }
+
+ /**
+ * Function to call to evaluate model
+ * @param args: input numpy array  [x[],y[]]
+ * @return: numpy array object 
+ */
+ static PyObject * evaluateTwoDimXY( [CMODEL]* model, 
+                              PyArrayObject *x, PyArrayObject *y)
+ {
+    PyArrayObject *result;
+    int x_len, y_len, dims[1];
+    //check validity of input vectors
+    if (x->nd != 1 || x->descr->type_num != PyArray_DOUBLE
+        || y->nd != 1 || y->descr->type_num != PyArray_DOUBLE
+        || y->dimensions[0] != x->dimensions[0]){
+        const char * message= "evaluateTwoDimXY  expect 2 numpy arrays";
+        PyErr_SetString(PyExc_ValueError , message); 
+        return NULL;
+    }
+   
+	if (PyArray_Check(x) && PyArray_Check(y)) {
+		
+	    x_len = dims[0]= x->dimensions[0];
+        y_len = dims[0]= y->dimensions[0];
+	    
+	    // Make a new double matrix of same dims
+        result=(PyArrayObject *) PyArray_FromDims(1,dims,NPY_DOUBLE);
+        if (result == NULL){
+	    const char * message= "Could not create result ";
+        PyErr_SetString(PyExc_RuntimeError , message);
+	    return NULL;
+	    }
+       
+        /* Do the calculation. */
+#pragma omp parallel for
+        for (int i=0; i< x_len; i++) {
+            double x_value = *(double *)(x->data + i*x->strides[0]);
+  		    double y_value = *(double *)(y->data + i*y->strides[0]);
+  			double *result_value = (double *)(result->data +
+  			      i*result->strides[0]);
+  			*result_value = (*model)(x_value, y_value);
+        }           
+        return PyArray_Return(result); 
+        
+        }else{
+		    PyErr_SetString([PYTHONCLASS]Error, 
+                   "[PYTHONCLASS].evaluateTwoDimXY couldn't run.");
+	        return NULL;
+		}      	
+}
+/**
+ *  evalDistribution function evaluate a model function with input vector
+ *  @param args: input q as vector or [qx, qy] where qx, qy are vectors
+ *
+ */ 
+static PyObject * evalDistribution([PYTHONCLASS] *self, PyObject *args){
+	PyObject *qx, *qy;
+	PyArrayObject * pars;
+	int npars ,mpars;
+	
+	// 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].evalDistribution expects a q value.");
+		return NULL;
+	}
+    // Check params
+	
+    if(PyArray_Check(pars)==1) {
+		
+	    // Length of list should 1 or 2
+	    npars = pars->nd; 
+	    if(npars==1) {
+	        // input is a numpy array
+	        if (PyArray_Check(pars)) {
+		        return evaluateOneDim(self->model, (PyArrayObject*)pars); 
+		    }
+		}else{
+		    PyErr_SetString([PYTHONCLASS]Error, 
+                   "[PYTHONCLASS].evalDistribution expect numpy array of one dimension.");
+	        return NULL;
+		}
+    }else if( PyList_Check(pars)==1) {
+    	// Length of list should be 2 for I(qx,qy)
+	    mpars = PyList_GET_SIZE(pars); 
+	    if(mpars!=2) {
+	    	PyErr_SetString([PYTHONCLASS]Error, 
+	    		"[PYTHONCLASS].evalDistribution expects a list of dimension 2.");
+	    	return NULL;
+	    }
+	     qx = PyList_GET_ITEM(pars,0);
+	     qy = PyList_GET_ITEM(pars,1);
+	     if (PyArray_Check(qx) && PyArray_Check(qy)) {
+	         return evaluateTwoDimXY(self->model, (PyArrayObject*)qx,
+		           (PyArrayObject*)qy);
+		 }else{
+		    PyErr_SetString([PYTHONCLASS]Error, 
+                   "[PYTHONCLASS].evalDistribution expect 2 numpy arrays in list.");
+	        return NULL;
+	     }
+	}
+	PyErr_SetString([PYTHONCLASS]Error, 
+                   "[PYTHONCLASS].evalDistribution couln't be run.");
+	return NULL;
+	
+}
+
+/**
+ * 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 calculate_ER
+ * @return: effective radius value 
+ */
+static PyObject * calculate_ER([PYTHONCLASS] *self) {
+
+	// Get parameters
+	
+	[READDICTIONARY]
+		
+	return Py_BuildValue("d",(*(self->model)).calculate_ER());
+
+}
+/**
+ * Function to call to cal the ratio shell volume/ total volume
+ * @return: the ratio shell volume/ total volume 
+ */
+static PyObject * calculate_VR([PYTHONCLASS] *self) {
+
+	// Get parameters
+	
+	[READDICTIONARY]
+		
+	return Py_BuildValue("d",(*(self->model)).calculate_VR());
+
+}
+/**
+ * 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"},
+    {"calculate_ER",      (PyCFunction)calculate_ER     , METH_VARARGS,
+      "Evaluate the model at a given Q or Q, phi"},
+    {"calculate_VR",      (PyCFunction)calculate_VR     , METH_VARARGS,
+      "Evaluate VR"},    
+    {"evalDistribution",  (PyCFunction)evalDistribution , METH_VARARGS,
+      "Evaluate the model at a given Q or Qx, Qy vector "},
+    {"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);
+    static char error_name[] = "[PYTHONCLASS].error";
+    [PYTHONCLASS]Error = PyErr_NewException(error_name, NULL, NULL);
+    PyDict_SetItemString(d, "[PYTHONCLASS]Error", [PYTHONCLASS]Error);
+}
Index: src/sas/models/c_extension/python_wrapper/lineparser.py
===================================================================
--- src/sas/models/c_extension/python_wrapper/lineparser.py	(revision 794922220f2fb3b23dd08c648aabf87b4850596c)
+++ src/sas/models/c_extension/python_wrapper/lineparser.py	(revision 794922220f2fb3b23dd08c648aabf87b4850596c)
@@ -0,0 +1,215 @@
+#!/usr/bin/env python
+""" WrapperGenerator class to generate model code automatically.
+"""
+
+import os, sys,re
+def split_list(separator, mylist, n=0):
+    """
+        @return a list of string without white space of separator
+        @param separator: the string to remove
+    """
+    list=[]
+    for item in mylist:
+        if re.search( separator,item)!=None:
+            if n >0:
+                word =re.split(separator,item,int(n))
+            else:
+                word =re.split( separator,item)
+            for new_item in word: 
+                if new_item.lstrip().rstrip() !='':
+                    list.append(new_item.lstrip().rstrip())
+    return list
+def split_text(separator, string1, n=0):
+    """
+        @return a list of string without white space of separator
+        @param separator: the string to remove
+    """
+    list=[]
+    if re.search( separator,string1)!=None:
+        if n >0:
+            word =re.split(separator,string1,int(n))
+        else:
+            word =re.split(separator,string1)
+        for item in word: 
+            if item.lstrip().rstrip() !='':
+                list.append(item.lstrip().rstrip())
+    return list
+def look_for_tag( string1,begin, end=None ):
+    """
+        @note: this method  remove the begin and end tags given by the user
+        from the string .
+        @param begin: the initial tag
+        @param end: the final tag
+        @param string: the string to check
+        @return: begin_flag==True if begin was found,
+         end_flag==if end was found else return false, false
+         
+    """
+    begin_flag= False
+    end_flag= False
+    if  re.search( begin,string1)!=None:
+        begin_flag= True
+    if end !=None:
+        if  re.search(end,string1)!=None:
+            end_flag= True
+    return begin_flag, end_flag
+
+
+  
+def readhelper(lines, key, key2, key3 , file):
+  
+    temp=""
+    # flag to found key
+    find_fixed= False
+    find_key2=False
+    find_key3=False
+    listtofill=[]
+    for line in lines:
+        if line.count(key.lstrip().rstrip())>0 :#[FIXED]= .....
+            try:
+                find_fixed= True
+                index = line.index(key)
+                toks  = line[index:].split("=",1 )
+                temp  = toks[1].lstrip().rstrip()
+                find_key2, find_key3=look_for_tag( string1=temp,
+                                                   begin=key2, end=key3 )
+                if find_key2 and find_key3:
+                    temp1=[]
+                    temp2=[]
+                    temp3=[]
+                    temp4=[]
+                    temp1=split_text(separator=key2, string1=temp)
+                    temp2=split_list(separator=key3, mylist=temp1)
+                    temp3=split_list(separator=';', mylist=temp2)
+                    temp4=split_list(separator=',', mylist=temp3)
+                    listtofill= temp3 + temp4
+                    return listtofill
+                    
+                    
+                elif find_key2 and not find_key3:
+                    ## [key]= key2(<text>)
+                    ##        ....
+                    ##        key3(<text>)
+                    temp1=[]
+                    temp2=[]
+                    temp3=[]
+                    temp4=[]
+                    ## remove key2= <text>
+                    temp1=split_text(separator=key2, string1=temp)
+                    
+                    ## split ";" first
+                    temp3=split_list(separator=';', mylist=temp1)
+                    temp4=split_list(separator=',', mylist=temp3)
+            
+                    if len(temp3 + temp4)==0:
+                        # [FIXED]=  only one param
+                        listtofill+= temp1
+                    listtofill += temp3+temp4 
+               
+                elif not find_key2 and not find_key3 :
+                    ## [key]= param done looking
+                    temp3=[]
+                    temp4=[]
+                    if look_for_tag( string1=temp,begin=";")[0]:
+                        ## split ";" first
+                        temp3=split_text(separator=';',string1=temp)
+                        temp4=split_list(separator=',', mylist=temp3)
+                    else:
+                        ## slip "," first
+                        temp3=split_text(separator=',',string1=temp)
+                        temp4=split_list(separator=';', mylist=temp3)
+                    if len(temp3+ temp4)==0:
+                        ## [FIXED]=  only one param
+                        if temp.lstrip().rstrip()!="":
+                            listtofill= [temp.lstrip().rstrip()]
+                        
+                    listtofill += temp3+temp4
+                    return listtofill
+            except:
+                raise ValueError, "Could not parse file %s" % file
+        
+        elif find_fixed :
+            if not find_key2:
+                raise ValueError, "Could not parse file %s" % file
+            if find_key3:
+                temp1=[]
+                temp2=[]
+                temp3=[]
+                temp4=[]
+                temp5=[]
+               
+                temp1=split_text(separator=key3, string1=line)
+                temp2=split_list(separator='//',mylist=temp1)
+                temp5=split_list(separator="\*",mylist=temp1)
+                
+                if len(temp5)>0:
+                    temp3=split_list(separator=';',mylist=temp5)
+                    temp4=split_list(separator=',', mylist=temp5)
+                elif len(temp2)>0:
+                    temp3=split_list(separator=';',mylist=temp2)
+                    temp4=split_list(separator=',', mylist=temp2)
+                else:
+                    temp3=split_list(separator=';',mylist=temp1)
+                    temp4=split_list(separator=',', mylist=temp1)
+                
+                if len(temp3 + temp4)==0:# [FIXED]=  only one param
+                    listtofill += temp1
+                listtofill+=temp3+temp4 #   
+                break
+            
+            else:
+                temp2=split_text(separator='//', string1=line)
+                temp5=split_text(separator="\*", string1=line)
+                if len(temp5)>0:
+                    temp3=split_list(separator=';', mylist=temp5)
+                    temp4=split_list(separator=',', mylist=temp5)
+                elif len(temp2)>0:
+                    temp3=split_list(separator=';', mylist=temp2)
+                    temp4=split_list(separator=',', mylist=temp2)
+                else:
+                    if look_for_tag( string1=line,begin=";")[0]:# split ";" first
+                        temp3=split_text(separator=';', string1=line)
+                        temp4=split_list(separator=',', mylist=temp3)
+                    else:
+                        temp3=split_text(separator=',', string1=line)# slip "," first
+                        temp4=split_list(separator=';', mylist=temp3)
+                if len(temp3+ temp4)==0:# [FIXED]=  only one param
+                    if line.lstrip().rstrip()!="":
+                        listtofill=[line.lstrip().rstrip()]
+                listtofill+=temp3+temp4 #
+                break
+    return listtofill
+   
+# main
+if __name__ == '__main__':
+    
+    # Read file
+    name= "sphere.h"
+    f = open("..\include\core_shell.h",'r')
+    buf = f.read()
+  
+    lines = buf.split('\n')
+  
+    ## Catch Fixed parameters
+    key = "[FIXED]"
+    #open item in this case Fixed
+    text='text'
+    key2="<%s>"%text.lower()
+    # close an item in this case fixed
+    text='TexT'
+    key3="</%s>"%text.lower()
+    listto=[]
+   
+    listto= readhelper(lines, key, key2,key3, file=name)
+    print "fixed parameters\n ",listto
+    print 
+    
+   
+    key0="[ORIENTATION_PARAMS]"
+   
+    listto=[]
+    listto= readhelper(lines,key0, key2,key3, file=name)
+    print "orientation parameters\n ",listto
+    print 
+    f.close()
+# End of file        
Index: src/sas/models/c_extension/python_wrapper/modelTemplate.txt
===================================================================
--- src/sas/models/c_extension/python_wrapper/modelTemplate.txt	(revision 794922220f2fb3b23dd08c648aabf87b4850596c)
+++ src/sas/models/c_extension/python_wrapper/modelTemplate.txt	(revision 794922220f2fb3b23dd08c648aabf87b4850596c)
@@ -0,0 +1,161 @@
+##############################################################################
+# 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-2011, 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.models.sans_extension.c_models import [CPYTHONCLASS]
+
+def create_[PYTHONCLASS]():
+    """
+       Create a model instance
+    """
+    obj = [PYTHONCLASS]()
+    # [CPYTHONCLASS].__init__(obj) is called by
+    # the [PYTHONCLASS] constructor
+    return obj
+
+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, multfactor=1):
+        """ Initialization """
+        self.__dict__ = {}
+        
+        # Initialize BaseComponent first, then sphere
+        BaseComponent.__init__(self)
+        #apply([CPYTHONCLASS].__init__, (self,)) 
+
+        [CALL_CPYTHON_INIT]
+		        
+        ## Name of the model
+        self.name = "[PYTHONCLASS]"
+        ## Model description
+        self.description = """
+        [DESCRIPTION]
+        """
+       
+        [PAR_DETAILS]
+        ## fittable parameters
+        self.fixed = [FIXED]
+        
+        ## non-fittable parameters
+        self.non_fittable = [NON_FITTABLE_PARAMS]
+        
+        ## parameters with orientation
+        self.orientation_params = [ORIENTATION_PARAMS]
+
+        ## parameters with magnetism
+        self.magnetic_params = [MAGNETIC_PARAMS]
+
+        self.category = [CATEGORY]
+        self.multiplicity_info = [MULTIPLICITY_INFO]
+        
+    def __setstate__(self, state):
+        """
+        restore the state of a model from pickle
+        """
+        self.__dict__, self.params, self.dispersion = state
+        
+    def __reduce_ex__(self, proto):
+        """
+        Overwrite the __reduce_ex__ of PyTypeObject *type call in the init of 
+        c model.
+        """
+        state = (self.__dict__, self.params, self.dispersion)
+        return (create_[PYTHONCLASS], tuple(), state, None, None)
+        
+    def clone(self):
+        """ Return a identical copy of self """
+        return self._clone([PYTHONCLASS]())   
+       	
+    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 evalDistribution(self, x):
+        """ 
+        Evaluate the model in cartesian coordinates
+        
+        :param x: input q[], or [qx[], qy[]]
+        
+        :return: scattering function P(q[])
+        
+        """
+        return [CPYTHONCLASS].evalDistribution(self, x)
+        
+    def calculate_ER(self):
+        """ 
+        Calculate the effective radius for P(q)*S(q)
+        
+        :return: the value of the effective radius
+        
+        """       
+        return [CPYTHONCLASS].calculate_ER(self)
+        
+    def calculate_VR(self):
+        """ 
+        Calculate the volf ratio for P(q)*S(q)
+        
+        :return: the value of the volf ratio
+        
+        """       
+        return [CPYTHONCLASS].calculate_VR(self)
+              
+    def set_dispersion(self, parameter, dispersion):
+        """
+        Set the dispersion object for a model parameter
+        
+        :param parameter: name of the parameter [string]
+        :param dispersion: dispersion object of type DispersionModel
+        
+        """
+        return [CPYTHONCLASS].set_dispersion(self,
+               parameter, dispersion.cdisp)
+        
+   
+# End of file
Index: src/sas/models/c_extension/python_wrapper/wrapping.py
===================================================================
--- src/sas/models/c_extension/python_wrapper/wrapping.py	(revision 794922220f2fb3b23dd08c648aabf87b4850596c)
+++ src/sas/models/c_extension/python_wrapper/wrapping.py	(revision 794922220f2fb3b23dd08c648aabf87b4850596c)
@@ -0,0 +1,69 @@
+import sys
+import os
+import os.path
+from WrapperGenerator import WrapperGenerator
+
+def generate_wrappers(header_dir, output_dir='.', c_wrapper_dir='.'):
+    nModels=0
+    model_list = list()
+
+    for item in os.listdir(header_dir):
+        toks = os.path.splitext(os.path.basename(item))
+        if toks[1]=='.h':
+            nModels += 1
+            name = toks[0]
+            app = WrapperGenerator(os.path.join(header_dir, name+".h"), 
+                                   output_dir=output_dir,
+                                   c_wrapper_dir=c_wrapper_dir)
+            app.read()
+            app.write_c_wrapper()
+            app.write_python_wrapper()
+            model_list.append(app.getModelName())
+    write_c_models(model_list)
+    print "Total number of model  wrappers created is %s" % nModels
+
+def write_c_models(model_list):
+    # simultaneously generates 'sansmodels/installed_models.txt'
+    # and 'sansmodels/src/c_models/c_models.cpp'
+    
+
+    template_file = open(os.path.join("src", "sans", "models","c_extension","c_models","c_models.cpp.template"),"r")
+    write_file = open(os.path.join("src", "sans",  "models","c_extension","c_models","c_models.cpp"),"w")
+    buf = template_file.read()
+    lines = buf.split('\n')
+    
+    tag1 = "[TAG_1]"
+    tag2 = "[TAG_2]"
+    
+    for line in lines:
+        
+        if line.count(tag1) > 0:
+            write_file.write("\n // adding generated code \n")
+            for pyclass in model_list:
+                write_file.write("void addC" + pyclass
+                                 + "(PyObject *module); \n")
+            write_file.write(" // end generated code \n")
+                
+
+        elif line.count(tag2) > 0:
+            write_file.write("\n // adding generated code \n")
+
+            for pyclass in model_list:
+                write_file.write("addC" + pyclass + "(m); \n")
+
+            write_file.write("addDisperser(m); \n")
+            write_file.write("\n // end generated code \n")
+                
+                
+        else:
+            write_file.write(line + "\n")
+
+
+
+if __name__ == '__main__':
+    header_dir = os.path.join('..', 'include')
+    generate_wrappers(header_dir, output_dir="../sans/models/", c_wrapper_dir='.')
+
+
+
+
