Example Scripts

There are several ways to run XYmath

  1. Launch the GUI, enter and fit data and perhaps run some math operations
  2. Write a script to launch the GUI with data

  3. Run a script that outputs to the console

The examples that follow will show both GUI and console scripts (options 2 & 3 above).

Warning

It is dangerous to run a console curve fit and accept it without looking at a plot.

Curve fitting is mostly about what happens Between the points, not At the points.

Instrument Calibration

This example comes from: http://terpconnect.umd.edu/~toh/spectrum/CurveFitting.html

The author shows a linear fit of an instrument reading chemical concentrations

The author mentions that a quadratic fit w/o the data point at concentration=0.6 would be significantly better… that is also calculated.

With GUI

The script /xymath/examples/calibration_gui.py launches the XYmath GUI with the calibration data so that the GUI can perform the desired calculations.

from numpy import array
from xymath.dataset import DataSet
from xymath.linfit import LinCurveFit
from xymath.xy_job import XY_Job
from xymath.gui.xygui import main as run_gui

concL = [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1]
readingL = [1.54,2.03,3.17,3.67,4.89,6.73,6.74,7.87,8.86,10.35]
DS = DataSet(concL, readingL, xName='Concentration', yName='Instrument Reading')

XY = XY_Job()
XY.define_dataset(concL, readingL, wtArr=None, xName='Concentration',
                  yName='Instrument Reading', xUnits='', yUnits='')
run_gui( XY )

Once launched, the following steps can be taken inside the GUI:

1) Launch XYmath with code above
2) Go to "Simple Fit" Tab
3) Hit "Curve Fit"
    - XYmath will show "c0 + c1/x + c2/x**2 + c3*x" as best fit
4) Select "y = c0 + c1*x" to approximate the author's results
5) Go to "Data" Tab
6) Select "weight" of data point with concentration=0.6
    - Set that weight to 0.0
7) Go back to "Simple Fit" Tab and hit "Curve Fit"
    - Notice that the zero-weighted point is marked as such on the plot
    - As the author predicts, the fit is greatly improved
    - Surprisingly, XYmath shows the 3 term equation "y = c0 + c1*x + c2/x"
      to be superior to the 4 term equations as well as the quadratic.

Running the above code, launches the GUI, preloaded with the concentration data.

Using “Simple Fit” results in the GUI and plot shown below.

_images/ex_conc_simple_fit_gui.png _images/ex_conc_simple_fit_plot.png

Selecting the straight line “y = c0 + c1*x” gives the GUI and plot shown below.

_images/ex_conc_simple_fit_gui_v2.png _images/ex_conc_simple_fit_plot_v2.png

Use “Data” tab to set weight of data point at concentration=.6 to zero.

_images/ex_conc_simple_fit_gui_zerowt.png

Rerun “Simple Fit” and select author’s quadratic recommendation

Notice that the data point at concentration=0.6 is still on the plot, but it is labeled as “Weighted Low” and its weight value is indicated as “x0”.

_images/ex_conc_simple_fit_gui_zerowt_quad.png _images/ex_conc_simple_fit_gui_zerowt_quad_plot.png

With Console

As you might imagine, the console script is longer because it performs many of the steps done manually in the GUI example.

This example first duplicates the author’s equation (i.e. sets the straight line coefficients to the same values as the author (cArrInp=[0.199, 9.7926]) and calculates standard deviation and percent standard deviation as a reference.

Then runs XYmath to fit the points. It results in only a very slight improvment in the author’s answer (see output below python script).

And finally removes the point at concentration=0.6 and fits to a quadratic. This results in the big improvement that the author was looking for (see output below python script).

Here’s the code from /xymath/examples/calibration.py.

try:
    from matplotlib import pyplot as plt
    got_plt = True
except:
    got_plt = False

from xymath.dataset import DataSet
from xymath.linfit import LinCurveFit

concL = [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1]
readingL = [1.54,2.03,3.17,3.67,4.89,6.73,6.74,7.87,8.86,10.35]
DS = DataSet(concL, readingL, xName='Concentration', yName='Instrument Reading')

print('\n\n')
print('='*55)
print(".... First show author's answer ....")
Fit_ref = LinCurveFit(DS, xtranL=['const', 'x'] , ytran='y', cArrInp=[0.199, 9.7926],
                  fit_best_pcent=0)   # 0=fit best total error
print(Fit_ref.get_full_description())

print('='*55)
print('.... Then show XYmath answer ....')
Fit_linear = LinCurveFit(DS, xtranL=['const', 'x'] , ytran='y',
                  fit_best_pcent=0)   # 0=fit best total error
print(Fit_linear.get_full_description())

print('='*55)
print('.... Then show XYmath Quadratic answer ....')

v2_concL =    [0.1,  0.2, 0.3, 0.4, 0.5, 0.7, 0.8, 0.9, 1]
v2_readingL = [1.54,2.03,3.17,3.67,4.89,6.74,7.87,8.86,10.35]
DS = DataSet(v2_concL, v2_readingL, xName='Concentration', yName='Instrument Reading')

Fit_quad = LinCurveFit(DS, xtranL=['const', 'x', 'x**2'] , ytran='y',
                  fit_best_pcent=0)   # 0=fit best total error
print(Fit_quad.get_full_description())

if got_plt:
    plt.plot( concL, readingL, 'o', markersize=10  )
    xPlotArr, yPlotArr = Fit_ref.get_xy_plot_arrays( Npoints=100, logScale=False)
    plt.plot( xPlotArr, yPlotArr, '--', linewidth=4  )
    xPlotArr, yPlotArr = Fit_linear.get_xy_plot_arrays( Npoints=100, logScale=False)
    plt.plot( xPlotArr, yPlotArr, '-'  )
    xPlotArr, yPlotArr = Fit_quad.get_xy_plot_arrays( Npoints=100, logScale=False)
    plt.plot( xPlotArr, yPlotArr, '-'  )
    plt.title('Calibration Example')
    plt.show()

The console output is shown below:

=======================================================
.... First show author's answer ....
y = c0 + c1*x
    c0 = 0.199
    c1 = 9.7926
    x = Concentration
    y = Instrument Reading
    Correlation Coefficient = 0.993152645552
    Standard Deviation = 0.331007277412
    Percent Standard Deviation = 9.42865864393%
y = 0.199 + 9.7926*x
=======================================================
.... Then show XYmath answer ....
y = c0 + c1*x
    c0 = 0.196666666667
    c1 = 9.79696969697
    x = Concentration
    y = Instrument Reading
    Correlation Coefficient = 0.993152645552
    Standard Deviation = 0.331004897886
    Percent Standard Deviation = 9.45154746872%
y = 0.196666666667 + 9.79696969697*x
=======================================================
.... Then show XYmath Quadratic answer ....
y = c0 + c1*x + c2*x**2
    c0 = 0.8315625
    c1 = 6.22254971591
    c2 = 3.19353693182
    x = Concentration
    y = Instrument Reading
    Correlation Coefficient = 0.999039190283
    Standard Deviation = 0.129698349765
    Percent Standard Deviation = 4.11221905227%
y = 0.8315625 + 6.22254971591*x + 3.19353693182*x**2

If matplotlib is installed on your machine, then you should see the following plot

_images/ex_conc_console_fit_plot.png

Atmospheric Pressure

This example comes from: http://www.engineeringtoolbox.com/air-altitude-pressure-d_462.html

The author shows a non-linear fit of atmospheric pressure vs altitude.

The author derives a curve fit of air pressure above sea level as:

pressure(Pa)  = 101325 * (1 - 2.25577E-5 * h)**5.25588
where x=altitude(m)

With GUI

The script /xymath/examples/fit_Patmos_gui.py launches the XYmath GUI with the atmospheric data so that the GUI can perform the desired calculations.

from numpy import array, double
from xymath.xy_job import XY_Job
from xymath.gui.xygui import main as run_gui

XY = XY_Job()

alt_mArr = array([-1524,-1372,-1219,-1067,-914,-762,-610,-457,-305,-152,0,152,
           305,457,610,762,914,1067,1219,1372,1524,1829,2134,2438,2743,3048,4572,
           6096,7620,9144,10668,12192,13716,15240], dtype=double)

PaArr = 1000.0 * array([121,119,117,115,113,111,109,107,105,103,101,99.5,97.7,96,
        94.2,92.5,90.8,89.1,87.5,85.9,84.3,81.2,78.2,75.3,72.4,69.7,57.2,46.6,37.6,
        30.1,23.8,18.7,14.5,11.1], dtype=double)

XY.define_dataset(alt_mArr, PaArr, wtArr=None, xName='altitude', yName='Pressure',
                  xUnits='m', yUnits='Pa')


guessD = {'A':100000, 'c':1, 'd':0.00001, 'n':4  }

XY.fit_dataset_to_nonlinear_eqn(run_best_pcent=0, rhs_eqnStr='A*(c - d*x)**n',
                                constDinp=guessD)

run_gui( XY )

Once launched, the following steps can be taken inside the GUI:

1) Launch XYmath with code below
2) Go to "Non-Linear Fit" Tab
   - Should see "A*(c - d*x)**n" in eqn box
3) Hit "Curve Fit"

    y = A*(c - d*x)**n
        A = 101351.958792
        c = 0.999991347618
        d = 2.22155669208e-05
        n = 5.34803660866
        x = altitude (m)
        y = Pressure (Pa)
        Correlation Coefficient = 0.999996164903
        Standard Deviation = 88.4289410055
        Percent Standard Deviation = 0.0992974873982%

4) Change the "Fit By" flag to "Percent Error".
   Notice the XYmath improves Percent StdDev fit very slightly

    y = A*(c - d*x)**n
        A = 101124.977819
        c = 1.00041249485
        d = 2.23356723474e-05
        n = 5.31856523127
        x = altitude (m)
        y = Pressure (Pa)
        Correlation Coefficient = 0.999996135864
        Standard Deviation = 88.761441745
        Percent Standard Deviation = 0.094401748723%

Running the above code, launches the GUI, preloaded with the atmospheric data.

Using “Non-Linear Fit” results in the GUI and plot shown below.

_images/ex_patmos_gui.png _images/ex_patmos_gui_plot.png

With Console

Here’s the code from /xymath/examples/fit_Patmos.py. The code generates two curve fits, one with minimum total error and one with minimum percent error. The reference curve from www.engineeringtoolbox.com is also placed into a NonLinCurveFit object.

try:
    from matplotlib import pyplot as plt
    got_plt = True
except:
    got_plt = False

from numpy import array, double
from xymath.dataset import DataSet
from xymath.nonlinfit import NonLinCurveFit

alt_mArr = array([-1524,-1372,-1219,-1067,-914,-762,-610,-457,-305,-152,0,152,305,457,
          610,762,914,1067,1219,1372,1524,1829,2134,2438,2743,3048,4572,6096,7620,
          9144,10668,12192,13716,15240], dtype=double)

PaArr = 1000.0 * array([121,119,117,115,113,111,109,107,105,103,101,99.5,97.7,96,94.2,92.5,90.8,
        89.1,87.5,85.9,84.3,81.2,78.2,75.3,72.4,69.7,57.2,46.6,37.6,30.1,23.8,
        18.7,14.5,11.1], dtype=double)

DS = DataSet(alt_mArr, PaArr, xName='altitude', yName='pressure', xUnits='m', yUnits='Pa')


guessD = {'A':101325, 'c':1, 'd':2.25577E-5, 'n':5.25588  }
print( 'guessD Before',guessD )
CFit_toterr = NonLinCurveFit(DS, rhs_eqnStr='A*(c - d*x)**n',
                                constDinp=guessD, fit_best_pcent=0)   # 0=fit best total error
print( 'guessD After',guessD )

print('='*55)
print('..........Total Error............')
print(CFit_toterr.get_full_description())
print('='*55)
print('..........Percent Error............')
CFit_pcterr = NonLinCurveFit(DS, rhs_eqnStr='A*(c - d*x)**n',
                                constDinp=guessD, fit_best_pcent=1)   # 1=fit best percent error
print(CFit_pcterr.get_full_description())
print('='*55)

# To set parameters to reference values from www.engineeringtoolbox.com do this:
print('..........Reference Curve Fit............')
CFit_ref = NonLinCurveFit(DS, rhs_eqnStr='A*(c - d*x)**n', constDinp=guessD)
CFit_ref.constD.update( {'A':101325, 'c':1, 'd':2.25577E-5, 'n':5.25588  } )
CFit_ref.calc_std_values()
print(CFit_ref.get_full_description())

if got_plt:
    plt.plot( alt_mArr, PaArr, 'o', markersize=10  )
    xPlotArr, yPlotArr = CFit_ref.get_xy_plot_arrays( Npoints=100, logScale=False)
    plt.plot( xPlotArr, yPlotArr, '--', linewidth=5, label='Reference'  )
    xPlotArr, yPlotArr = CFit_toterr.get_xy_plot_arrays( Npoints=100, logScale=False)
    plt.plot( xPlotArr, yPlotArr, '-', label='Total Error' , linewidth=3 )
    xPlotArr, yPlotArr = CFit_pcterr.get_xy_plot_arrays( Npoints=100, logScale=False)
    plt.plot( xPlotArr, yPlotArr, '-', label='Percent Error'  )
    plt.title('Atmospheric Pressure')
    plt.legend()
    plt.show()

The console output is shown below

Note

After the curve fit, guessD holds the fitted values of the parameters.

('guessD Before', {'A': 101325, 'c': 1, 'd': 2.25577e-05, 'n': 5.25588})
('guessD After', {'A': 101071.99507528808, 'c': 1.0005086965155954, 'd': 2.2227059781416107e-05, 'n': 5.3480367230661061})
=======================================================
..........Total Error............
y = A*(c - d*x)**n
    A = 101071.995075
    c = 1.00050869652
    d = 2.22270597814e-05
    n = 5.34803672307
    x = altitude (m)
    y = pressure (Pa)
    Correlation Coefficient = 0.999996164903
    Standard Deviation = 88.4289426009
    Percent Standard Deviation = 0.0992975318388%
y = 101071.995075*(1.00050869652 - 2.22270597814e-05*x)**5.34803672307
=======================================================
..........Percent Error............
y = A*(c - d*x)**n
    A = 101749.173838
    c = 0.999255692815
    d = 2.2309845172e-05
    n = 5.31856519674
    x = altitude (m)
    y = pressure (Pa)
    Correlation Coefficient = 0.999996135864
    Standard Deviation = 88.7614426959
    Percent Standard Deviation = 0.0944017487367%
y = 101749.173838*(0.999255692815 - 2.2309845172e-05*x)**5.31856519674
=======================================================
..........Reference Curve Fit............
y = A*(c - d*x)**n
    A = 101325
    c = 1
    d = 2.25577e-05
    n = 5.25588
    x = altitude (m)
    y = pressure (Pa)
    Correlation Coefficient = 0.999995821319
    Standard Deviation = 93.2374437135
    Percent Standard Deviation = 0.106440180482%
y = 101325*(1 - 2.25577e-05*x)**5.25588

If matplotlib is installed on your machine, then you should see the following plot

_images/ex_patmos_console_plot.png

Trigonometric Function

This example comes from: http://www.walkingrandomly.com/?p=5215

The author (Mike Croucher) wants to fit the equation:

y = p1*cos(p2*x) + p2*sin(p1*x)

to some (x,y) data.

He makes an initial guess of p1=1 and p2=0.2 and gets an answer of:

p1 = 1.88184732
p2 = 0.70022901

With no initial guess, XYmath gets very nearly the same answer:

p1 = 1.88185084847
p2 = 0.70022981688

With GUI

The script /xymath/examples/walking_randomly_gui.py launches the XYmath GUI with the trig function data so that the GUI can perform the desired calculations.

from xymath.xy_job import XY_Job
from xymath.gui.xygui import main as run_gui

XY = XY_Job()

xdata = [-2,-1.64,-1.33,-0.7,0,0.45,1.2,1.64,2.32,2.9]
ydata = [0.699369,0.700462,0.695354,1.03905,1.97389,2.41143,1.91091,0.919576,-0.730975,-1.42001]

XY.define_dataset(xdata, ydata, wtArr=None, xName='x', yName='y', xUnits='', yUnits='')

XY.fit_dataset_to_nonlinear_eqn(run_best_pcent=0, rhs_eqnStr='p1*cos(p2*x) + p2*sin(p1*x)')

run_gui( XY )

Once launched, the following steps can be taken inside the GUI:

1) Launch XYmath with code above
2) Go to "Non-Linear Fit" Tab
   - should see "p1*cos(p2*x) + p2*sin(p1*x)" in eqn box
3) Hit "Curve Fit"
4) See what happens when you hit "Improve Fit" a few times
5) Change to "Percent Error" and notice changes

Running the above code, launches the GUI, preloaded with the trig function data.

Using “Non-Linear Fit” results in the GUI and plot shown below.

_images/ex_trig_gui.png _images/ex_trig_gui_plot.png

With Console

Here’s the code from /xymath/examples/walking_randomly.py. The code generates a curve fit of the equation ( y = p1*cos(p2*x) + p2*sin(p1*x) ).

try:
    from matplotlib import pyplot as plt
    got_plt = True
except:
    got_plt = False

from numpy import array
from xymath.dataset import DataSet
from xymath.nonlinfit import NonLinCurveFit

xdata = array([-2,-1.64,-1.33,-0.7,0,0.45,1.2,1.64,2.32,2.9])
ydata = array([0.699369,0.700462,0.695354,1.03905,1.97389,2.41143,
               1.91091,0.919576,-0.730975,-1.42001])
DS = DataSet(xdata, ydata, xName='x', yName='y')

guessD = {'p1':1.0, 'p2':0.2}
CFit = NonLinCurveFit(DS, rhs_eqnStr='p1*cos(p2*x) + p2*sin(p1*x)',
                      constDinp=guessD, fit_best_pcent=0)   # 0=fit best total error

print( 'residuals from XYmath = %g'%sum( (CFit.eval_xrange( xdata ) - ydata)**2 ) )
print( 'residuals from author = 0.053812696547933969' )
print('')
print(CFit.get_full_description())

if got_plt:
    plt.plot( xdata, ydata, 'o', markersize=10  )
    xPlotArr, yPlotArr = CFit.get_xy_plot_arrays( Npoints=100, logScale=False)
    plt.plot( xPlotArr, yPlotArr )
    plt.title('Trig Function: p1*cos(p2*x) + p2*sin(p1*x)')
    plt.show()

The console output is shown below:

residuals from XYmath = 0.0538127
residuals from author = 0.053812696547933969

y = p1*cos(p2*x) + p2*sin(p1*x)
    p1 = 1.881850994
    p2 = 0.700229857403
    x = x
    y = y
    Correlation Coefficient = 0.99919315158
    Standard Deviation = 0.0640227178858
    Percent Standard Deviation = 5.2045450232%
y = 1.881850994*cos(0.700229857403*x) + 0.700229857403*sin(1.881850994*x)

If matplotlib is installed on your machine, then you should see the following plot

_images/ex_trig_console_plot.png