Latest Version: 0.9.6.2
  Dashboard > Pylons Cookbook > ... > Pylons Curve and Surface Fitting Tutorial > Adding 3D surface fitting
  Pylons Cookbook Log In | Sign Up   View a printable version of the current page.  
  Adding 3D surface fitting
Added by James R. Phillips, last edited by James R. Phillips on Jan 16, 2008  (view change)
Labels: 
(None)

Now we'll extend the curve fitting into three dimensions, this is usually referred to as 'surface fitting'. From a programmatic point of view, there's hardly any difference in what we have already done earlier in the tutorial.

First, our 'user input' page will need a list of 3D equations to choose from, so this time we need the controller to provide them from the 3D equation set instead of the 2D set. Add the following to fitter.py:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# this comment forces the wiki to indent correctly, and is not needed

    def index3D(self):

        c.equationNameList = []

        # make a list of all 3D function names.  Do not include any functions that require user configuration, such as
        # the user-selectable polynomials or polyfunctionals. Code borrowed from the ListAllEquations.py example
        for submodule in inspect.getmembers(PythonEquations.Equations3D):
            if True == inspect.ismodule(submodule[1]):
                for equationClass in inspect.getmembers(submodule[1]):
                    if True == inspect.isclass(equationClass[1]):
                        equation = equationClass[1]() # need to make an instance so the offset forms can auto-generate themselves properly
                        if equation.polynomialFlag == 0 and equation.polyfunctionalFlag == 0:
                            c.equationNameList.append(equation.name)
                            
        c.equationNameList.sort()

        return render('/index3D.mako')

You can see at the end of the method we will render a template named index3D.mako. Make a file in the fittertutorial/templates directory named index3D.mako, and give it the following contents:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<PRE>
<form action="/fitter/FitAndReturnResults3D">

Simple 3D surface fitting example


<b>Step 1: </b>Text data entry

<TEXTAREA WRAP=OFF NAME="USERDATA" COLS="50" ROWS="7">
Example XYZ data.  All lines of text that do
not begin with three numbers are ignored.

 3.017  2.175   0.320
 2.822  2.624   0.629
 2.632  2.839   0.950
 2.287  3.030   1.574
 2.207  3.057   1.725
 2.048  3.098   2.035
 1.963  3.115   2.204
 1.784  3.144   2.570
 1.712  3.153   2.721
 2.972  2.106   0.313
 2.719  2.542   0.643
 2.495  2.721   0.956
 2.070  2.878   1.597
 1.969  2.899   1.758
 1.768  2.929   2.088
 1.677  2.939   2.240
 1.479  2.957   2.583
 1.387  2.963   2.744
 2.843  1.984   0.315
 2.485  2.320   0.639
 2.163  2.444   0.954
 1.687  2.525   1.459
 1.408  2.547   1.775
 1.279  2.554   1.927
 1.016  2.564   2.243
 0.742  2.568   2.581
 0.607  2.571   2.753
 </TEXTAREA>



<b>Step 2: </b>Select an equation

<select NAME="EQUATIONNAME">
% for equationName in c.equationNameList:
    <option>${equationName}
% endfor
</select>


<b>Step 3: </b>Push this button!

<input type="submit" name="submit" value="Submit">

</form>
</PRE>

The users again need to input their data, so the template again has a TEXTAREA for cut-n-paste ASCII text entry - however this time it has 3D data. The (now 3D) equation list was provided by the controller, and Mako once again turns this into our equation selector. At the top of the template it shows that the form will be sent to our controller's FitAndReturnResults3D() method - so paste this code into our controller file fitter.py:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# this comment forces the wiki to indent correctly, and is not needed

    def FitAndReturnResults3D(self):
        # since we only have the equation name, find and instantiate the appropriate equation - then fit
        for submodule in inspect.getmembers(PythonEquations.Equations3D):
            if True == inspect.ismodule(submodule[1]):
                for equationClass in inspect.getmembers(submodule[1]):
                    if True == inspect.isclass(equationClass[1]):
                        eq = equationClass[1]() # need to make an instance so the offset forms can auto-generate themselves properly
                        if eq.name == request.params['EQUATIONNAME']:
                            c.equation = eq

        c.equation.fittingTarget = 'SSQABS' # see the Equation base class for a list of fitting targets
        c.equation.ConvertTextToData(request.params['USERDATA']) # Equations have ASCII text data for testing and examples
        c.equation.Initialize() # now that the equation has data, set up the cache
        c.equation.GuessInitialCoefficients() # estimate initial parameters if needed
        c.equation.FitToCacheData() # perform the fit
        c.equation.CalculateErrors() # so we can output the errors
        return render('/results3D.mako')

The only difference here is that we iterate over the 3D equations instead of the 2D, and render the output with a file named results3D.mako. Make a file in the fittertutorial/templates directory named results3D.mako, and give it the following contents:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<PRE>

Result for ${c.equation.name}


${c.equation.HTML}


Coefficients:
% for i in range(len(c.equation.coefficientDesignatorTuple)):
     ${c.equation.coefficientDesignatorTuple[i]}: ${c.equation.coefficientArray[i]}
% endfor


<table border=1>
    <TR>
        <TD align=center>X</TD>
        <TD align=center>Y</TD>
        <TD align=center>Z</TD>
        <TD align=center>Equation Output</TD>
        <TD align=center>Absolute Error</TD>
        <TD align=center>Relative Error</TD>
        <TD align=center>Percent Error</TD>
    </TR>
% for i in range(len(c.equation.DependentDataArray)):
    <TR>
        <TD>${c.equation.IndependentDataArray[0][i]}</TD>
        <TD>${c.equation.IndependentDataArray[1][i]}</TD>
        <TD>${c.equation.DependentDataArray[i]}</TD>
        <TD>${c.equation.PredictedArray[i]}</TD>
        <TD>${c.equation.AbsoluteErrorArray[i]}</TD>
        <TD>${c.equation.RelativeErrorArray[i]}</TD>
        <TD>${c.equation.PercentErrorArray[i]}</TD>
    </TR>
% endfor
</table>

<code>
## uncomment your choice of computing languages here...
##${c.equation.CodeJAVA()}
##${c.equation.CodeCPP()}
${c.equation.CodePYTHON()}
##${c.equation.CodeCS()}
##${c.equation.CodeSCILAB()}
##${c.equation.CodeMATLAB()}
</code>

</PRE>

Try http://127.0.0.1:5000/fitter/index3D - you should now have a fully functional surface fitter. You are done, except for the next section on adding graphics. Again, this is not strictly required for a curve and surface fitting web site, but it greatly eases and speeds analysis of the fitting results.

Next: --> Adding graphical output

Site running on a free Atlassian Confluence Open Source Project License granted to Pylons. Evaluate Confluence today.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.3.3 Build:#645 Feb 13, 2007) - Bug/feature request - Contact Administrators
Top