In this section, we are going to create a minimally functional - working - curve fitting web site. This is the core of the tutorial.
At this site the users will:
- Input their data
- Select an equation to use
- Submit the form
- View results of the curve fitting
So, the Pylons site we are making will require:
- A simple input form
- Almost all of the work done by Pylons and Python Equations

- Some minimal output
This will not be very complicated, so let's get started. Create a new project named fittingtutorial with this command:
paster create -t pylons fittingtutorial
Paster has now created a skeleton site for you, including a place to now install Python Equations
, so that's next.
If you recall from the Getting Started page:
"The lib directory is where you can put code that is used between different controllers, third party code, or any other code..."
Since Python Equations
is third party code, we will install it in lib. Copy all files in the Python Equations
package into lib such that you have the following directory structure:
We can now verify that the Python Equations
package runs properly. Using the above directory structure, cd to the lib/PythonEquations/Examples/SimpleExamples directory and issue the following command:
If you get a lot of numbers and no exceptions, the installation is good and the software is functioning correctly.
While Python Equations
was just verified to run on your system, Pylons cannot import it as the lib directory is not in Python's import path. Fortunately, with Python that's easy to fix for this and all future third-party package installations. We will have Python find out if the absolute path to the lib directory is in the import path, and if not then add it for us. Edit the lib directory's _init_.py file to look like this:
1
2
3
4 | import sys, os
projectName = sys.path[0].split(os.sep)[-1]
if os.path.join(sys.path[0], projectName, 'lib') not in sys.path:
sys.path.append(os.path.join(sys.path[0], projectName, 'lib'))
|
With all of the preliminaries complete, we can at last proceed to build our Pylons site.
Start by making a controller. From the top-level fittingtutorial directory:
Set the custom routes in fittingtutorial/config/routing.py to be:
1
2
3
4 | # CUSTOM ROUTES HERE
map.connect('', controller='fitter', action='index')
map.connect(':controller/:action/:id')
map.connect('*url', controller='template', action='view')
|
Delete the fittingtutorial/public/index.html file.
From the top-level fittingtutorial directory, start the development server with:
paster serve --reload development.ini
Try the URL http://127.0.0.1:5000/
, and you should receive a "Hello World" response.
Now to create the user input section of the web site.
The users will need to choose which equation they want to use, and Python's introspection and reflection abilities make it a breeze to get this from the Python Equations
package itself. Replace the entire contents of fitter.py with:
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 | import logging, string, inspect, PythonEquations
from fittingtutorial.lib.base import *
log = logging.getLogger(__name__)
class FitterController(BaseController):
def index(self):
c.equationNameList = []
# make a list of all 2D 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.Equations2D):
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('/index.mako')
|
This will import the PythonEquations package, find the names of all 2D equations, and give the session global c a sorted list of all the equation names we will use. You can see at the end of the method we will render a template named index.mako. Make a file in the fittertutorial/templates directory named index.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 | <PRE>
<form action="/fitter/FitAndReturnResults">
Simple 2D curve fitting example
<b>Step 1: </b>Text data entry
<TEXTAREA WRAP=OFF NAME="USERDATA" COLS="50" ROWS="7">
Example XY data. All lines of text that do
not begin with two numbers are ignored.
5.357 0.376
5.457 0.489
5.797 0.874
5.936 1.049
6.161 1.327
6.697 2.054
6.731 2.077
6.775 2.138
8.442 4.744
9.769 7.068
9.861 7.104
</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 need to input their data, so the template has a TEXTAREA for cut-n-paste ASCII text entry. The equation list was provided by the controller, and Mako turns this into our equation selector. At the top of the template it shows that the form will be sent to our controller's FitAndReturnResults() 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 FitAndReturnResults(self):
# since we only have the equation name, find and instantiate the appropriate equation - then fit
for submodule in inspect.getmembers(PythonEquations.Equations2D):
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 can already convert ASCII text to data for us
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('/results.mako')
|
The controller's FitAndReturnResults() method uses the passed-in equation name to find and instantiate the appropriate equation, convert the user input text onto data arrays, perform a curve fit and then finally calculate errors for display and analysis. You can see at the end of the method that a Mako template named results.mako is needed. Make a file in the fittertutorial/templates directory named results.mako, and give it the following contents:
1
2
3
4
5
6
7
8
9
10
11
12
13 | <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
</PRE>
|
This will print out the equation's HTML representation and the fitted coefficients. If http://127.0.0.1:5000/
works as discussed above, you now have a Pylons curve fitting site!
In it's present form this web site - while it does curve fit - is not so useful. Let's add some fitting results for the users to review.
Next: --> Display fitting results