diff -u grace-5.1.22/debian/changelog grace-5.1.22/debian/changelog
--- grace-5.1.22/debian/changelog
+++ grace-5.1.22/debian/changelog
@@ -1,3 +1,10 @@
+grace (1:5.1.22-5ubuntu1) lucid-proposed; urgency=low
+
+ * Add support for non-linear fitting.
+ - Written and contributed by Nicola Ferralis. (LP: #535459)
+
+ -- Nicola Ferralis
Under the "Library" menu, several functions are available under the ++categories: "Gaussian Functions", "Lorentzian Functions", "Peak Functions", ++ "Periodic Peak Functions" and "Baseline Functions".
++ ++Gaussian
  y = A0 + (A3*2*sqrt(ln(2)/pi)/A2)*exp(-4*ln(2)*((x-A1)/A2)^2)
++  where: A0: Baseline offset; A1: Center of the peak; A2: Full width at half
++maximum; A3: Peak area.
The center and initial amplitude of the peak can be set from
++ user input (via mouse coordinates).
Gaussian (Chromatography):
++  y = A0 + (1/sqrt(2*pi))*(A3/A2)*exp(-(x-A1)^2/2*A2^2)
++ A0: Baseline offset; A1: Center of the peak (retention time); A2:
++ Standard deviation of the peak; A3: Peak area.
The center and initial amplitude of the peak can be set from
++ user input (via mouse coordinates).
Lorentzian
  y = A0 + (2*A2*A3/pi)/(4*(x-A1)^2 + A2^2)
++  where: A0: Baseline offset; A1: Center of the peak; A2: Full width at half
++maximum; A3: Peak area.
The center and initial amplitude of the peak can be set from
++ user input (via mouse coordinates).
Peak Functions
++Pseudo Voigt 1
++  y = A0 + A3 * (A4*(2/pi)*A2/(4*(x-A1)^2+A2^2) +
(1-A4)*exp(-4*ln(2)*(x-A1)^2/A2^2)*(sqrt(4*ln(2))/(A2*sqrt(pi))))
++  where: Gaussian and Lorentzian have the same width; A0: Baseline offset;
++ A1: Center of the peak; A2: Full width at half maximum; A3: Amplitude;
++ A4: Profile shape factor.
++Pseudo Voigt 2
++  y = A0 + A3 * (A5*(2/pi)*A2/(4*(x-A1)^2+A2^2) + (1-A5)*exp(-4*ln(2)*(x-A1)^2/A4^2)*(sqrt(4*ln(2))/(A2*sqrt(pi))))
++  where: Gaussian and Lorentzian have different width; A0: Baseline offset;
++ A1: Center of the peak; A2: Full width at half maximum; A3: Amplitude;
++ A4: Profile shape factor.
++Doniach-Sunjic
++  y = A0 + A3*cos((pi*A4/2)+(1-A4)*atan((x-A1)/A2))/(A2^2+(x-A1)^2)^((1-A4)/2)
++  where:A0: Baseline offset; A1: Center of the peak; A2: Full width at half maximum;
++ A3: Peak area; A4: Asymmetry parameter.
++Asymmetric double Sigmoidal
++  y = A0 + A3*(1/(1+exp(-(x-A1+A2/2)/A4)))*(1-(1/(1+exp(-(x-A1-A2/2)/A5))))
++  where: A0: Baseline offset; A1: Center of the peak; A2: Width 1;
++ A3: Amplitude; A4: Width 2; A5: Width 5.
++Logarithm Normal:
++  y = A0 + A3*exp(-((ln(x)-ln(A1))^2)/(2*A2))
++  where: A0: Baseline offset; A1: Center of the peak; A2: Width
++Gram-Charlier A-Series (GCAS)
++  y = A0 + A3/(A2*sqrt(2*pi))*exp(-0.5*((x-A1)/A2)^2)*(1+(A4/6)*
++ (((x-A1)/A2)^3-3*(x-A1)/A2)+(A5/24)*(((x-A1)/A2)^4-6*((x-A1)/A2)^3+3))
++  where: A0: Baseline offset; A1: Center of the peak; A2: Standard deviation;
++ A3: Peak Area; A4: Skew; A5: Excess.
++Edgeworth-Cramer Series
++  y = A0 + A3/(A2*sqrt(2*pi))*exp(-0.5*((x-A1)/A2)^2)*(1+(A4/6)*
++ (((x-A1)/A2)^3-3*(x-A1)/A2)+(A5/24)*(((x-A1)/A2)^4-6 *((x-A1)/A2)^3+3)
++ +(A5^2/720)*(((x-A1)/A2)^6-15*((x-A1)/A2)^4+45*((x-A1)/A2)^2-15))
++  where: A0: Baseline offset; A1: Center of the peak; A2: Standard deviation;
++ A3: Peak Area; A4: Skew; A5: Excess.
++Inverse Polynomial
++  y=A0+A3/(1+ A4*(2*(x-A1)/A2)^2 + A5*(2*(x-A1)/A2)^4 + A6*(2*(x-A1)/A2)^6)
++  where: A0: Baseline offset; A1: Center of the peak; A2: Standard deviation;
++ A3: Peak Area; A4, A5, A6: Parameters.
++
Periodic Peak Functions
++Sine:
++ y=A0+A3*sin(pi*(x-A1)/A2)
++ where: A0: Baseline offset; A1: Center; A2: Width; A3: Amplitude.
++Sine Square:
++ y=A0+A3*sin(pi*(x-A1)/A2)^2
++ where: A0: Baseline offset; A1: Center; A2: Width; A3: Amplitude.
++Sine damp:
++ y=A0+A3*exp(-x/A4)*sin(pi*(x-A1)/A2)
++ where: A0: Baseline offset; A1: Center; A2: Width; A3: Amplitude; A4: Decay time.
++
Baseline Functions
++Exponential Decay 1:
++ y=A0+A3*exp(-(x-A1)/A2)
++Exponential Decay 2:
++ y=A0+A3*exp(-(x-A1)/A2)+A6*exp(-(x-A4)/A5);
++Exponential Growth 1:
++ y=A0+A3*exp((x-A1)/A2)
++Exponential Growth 2:
++ y=A0+A3*exp(-(x-A1)/A2)+A6*exp((x-A4)/A5);
++Hyperbolic:
++ y=A0+(A1*x)/(A2+x)
++Bradley:
++ y=A0*ln(-A1*ln(x))
++Logarithm 3 Parameters:
++ y=A0-A1*ln(x+A2)
++Weibull Probability Density 2 Parameters:
++ y=(A0/A1)*((x/A1)^(A0-1))*exp(-(x/A1)^A0)
++Weibull Cumulative Distribution 2 Parameters:
++ y=1-exp(-(x/A1)^A0)
++
This popup can be used to compute autocorrelation
+Index: grace-5.1.22/src/draw.c
+===================================================================
+--- grace-5.1.22.orig/src/draw.c 2005-11-19 13:53:24.000000000 -0800
++++ grace-5.1.22/src/draw.c 2010-07-27 10:50:30.000000000 -0700
+@@ -258,6 +258,12 @@
+ return (vp);
+ }
+
++WPoint Vpoint2Wpoint(VPoint vp)
++{
++ WPoint wp;
++ view2world(vp.x, vp.y, &wp.x, &wp.y);
++ return (wp);
++}
+
+ void symplus(VPoint vp, double s)
+ {
+Index: grace-5.1.22/src/draw.h
+===================================================================
+--- grace-5.1.22.orig/src/draw.h 2004-07-03 13:47:45.000000000 -0700
++++ grace-5.1.22/src/draw.h 2010-07-27 10:50:30.000000000 -0700
+@@ -236,6 +236,7 @@
+ double xy_xconv(double wx);
+ double xy_yconv(double wy);
+ VPoint Wpoint2Vpoint(WPoint wp);
++WPoint Vpoint2Wpoint(VPoint vp);
+ int world2view(double x, double y, double *xv, double *yv);
+ void view2world(double xv, double yv, double *xw, double *yw);
+
+Index: grace-5.1.22/src/events.c
+===================================================================
+--- grace-5.1.22.orig/src/events.c 2008-04-26 12:12:11.000000000 -0700
++++ grace-5.1.22/src/events.c 2010-07-27 10:50:30.000000000 -0700
+@@ -111,6 +111,7 @@
+ int axisno;
+ Datapoint dpoint;
+ GLocator locator;
++ static char buf[256];
+
+ cg = get_cg();
+ get_tracking_props(&track_setno, &move_dir, &add_at);
+@@ -487,6 +488,60 @@
+ }
+ select_line(anchor_x, anchor_y, x, y, 0);
+ break;
++ case PEAK_POS:
++ anchor_point(x, y, vp);
++ sprintf(buf, "Initial peak position, intensity: %f, %f \n", Vpoint2Wpoint(vp).x, Vpoint2Wpoint(vp).y);
++ stufftext(buf);
++ nonl_parms[1].value = Vpoint2Wpoint(vp).x;
++ nonl_parms[3].value = Vpoint2Wpoint(vp).y;
++ set_actioncb(NULL);
++ update_nonl_frame();
++ break;
++ case PEAK_POS1:
++ anchor_point(x, y, vp);
++ sprintf(buf, "Initial position, intensity peak #1: %f, %f \n", Vpoint2Wpoint(vp).x, Vpoint2Wpoint(vp).y);
++ stufftext(buf);
++ nonl_parms[1].value = Vpoint2Wpoint(vp).x;
++ nonl_parms[3].value = Vpoint2Wpoint(vp).y;
++ set_actioncb((void*) PEAK_POS2);
++ update_nonl_frame();
++ break;
++ case PEAK_POS2:
++ anchor_point(x, y, vp);
++ sprintf(buf, "Initial position, intensity peak #2: %f, %f \n", Vpoint2Wpoint(vp).x, Vpoint2Wpoint(vp).y);
++ stufftext(buf);
++ nonl_parms[4].value = Vpoint2Wpoint(vp).x;
++ nonl_parms[6].value = Vpoint2Wpoint(vp).y;
++ set_actioncb(NULL);
++ update_nonl_frame();
++ break;
++ case PEAK_POS1B:
++ anchor_point(x, y, vp);
++ sprintf(buf, "Initial position, intensity peak #1: %f, %f \n", Vpoint2Wpoint(vp).x, Vpoint2Wpoint(vp).y);
++ stufftext(buf);
++ nonl_parms[1].value = Vpoint2Wpoint(vp).x;
++ nonl_parms[3].value = Vpoint2Wpoint(vp).y;
++ set_actioncb((void*) PEAK_POS2B);
++ update_nonl_frame();
++ break;
++ case PEAK_POS2B:
++ anchor_point(x, y, vp);
++ sprintf(buf, "Initial position, intensity peak #2: %f, %f \n", Vpoint2Wpoint(vp).x, Vpoint2Wpoint(vp).y);
++ stufftext(buf);
++ nonl_parms[4].value = Vpoint2Wpoint(vp).x;
++ nonl_parms[6].value = Vpoint2Wpoint(vp).y;
++ set_actioncb((void*) PEAK_POS3B);
++ update_nonl_frame();
++ break;
++ case PEAK_POS3B:
++ anchor_point(x, y, vp);
++ sprintf(buf, "Initial position, intensity peak #3: %f, %f \n", Vpoint2Wpoint(vp).x, Vpoint2Wpoint(vp).y);
++ stufftext(buf);
++ nonl_parms[7].value = Vpoint2Wpoint(vp).x;
++ nonl_parms[9].value = Vpoint2Wpoint(vp).y;
++ set_actioncb(NULL);
++ update_nonl_frame();
++ break;
+ default:
+ break;
+ }
+@@ -567,6 +622,7 @@
+ void set_action(CanvasAction act)
+ {
+ int i;
++ static char buf[256];
+ /*
+ * indicate what's happening with a message in the left footer
+ */
+@@ -760,6 +816,42 @@
+ set_cursor(0);
+ set_left_footer("Pick ending point");
+ break;
++ case PEAK_POS:
++ set_cursor(0);
++ set_left_footer("Click on the approximate position of the maximum of the peak");
++ sprintf(buf, "Click on the approximate position of the maximum of the peak.\n");
++ stufftext(buf);
++ break;
++ case PEAK_POS1:
++ set_cursor(0);
++ set_left_footer("Click on the approximate position of the maximum of the peak #1");
++ sprintf(buf, "Click on the approximate position of the maximum of the peak #1.\n");
++ stufftext(buf);
++ break;
++ case PEAK_POS2:
++ set_cursor(0);
++ set_left_footer("Click on the approximate position of the maximum of the peak #2");
++ sprintf(buf, "Click on the approximate position of the maximum of the peak #2.\n");
++ stufftext(buf);
++ break;
++ case PEAK_POS1B:
++ set_cursor(0);
++ set_left_footer("Click on the approximate position of the maximum of the peak #1");
++ sprintf(buf, "Click on the approximate position of the maximum of the peak #1.\n");
++ stufftext(buf);
++ break;
++ case PEAK_POS2B:
++ set_cursor(0);
++ set_left_footer("Click on the approximate position of the maximum of the peak #2");
++ sprintf(buf, "Click on the approximate position of the maximum of the peak #2.\n");
++ stufftext(buf);
++ break;
++ case PEAK_POS3B:
++ set_cursor(0);
++ set_left_footer("Click on the approximate position of the maximum of the peak #3");
++ sprintf(buf, "Click on the approximate position of the maximum of the peak #3.\n");
++ stufftext(buf);
++ break;
+ }
+
+ action_flag = act;
+Index: grace-5.1.22/src/events.h
+===================================================================
+--- grace-5.1.22.orig/src/events.h 2004-07-03 13:47:45.000000000 -0700
++++ grace-5.1.22/src/events.h 2010-07-27 10:50:30.000000000 -0700
+@@ -81,7 +81,13 @@
+ ZOOMY_1ST,
+ ZOOMY_2ND,
+ DISLINE1ST,
+- DISLINE2ND
++ DISLINE2ND,
++ PEAK_POS,
++ PEAK_POS1,
++ PEAK_POS2,
++ PEAK_POS1B,
++ PEAK_POS2B,
++ PEAK_POS3B
+ } CanvasAction;
+
+ /* add points at */
+Index: grace-5.1.22/src/nonlwin.c
+===================================================================
+--- grace-5.1.22.orig/src/nonlwin.c 2010-07-27 10:50:30.000000000 -0700
++++ grace-5.1.22/src/nonlwin.c 2010-07-27 11:01:29.000000000 -0700
+@@ -7,6 +7,7 @@
+ * Copyright (c) 1996-2000 Grace Development Team
+ *
+ * Maintained by Evgeny Stambulchik
++ * Additional non linear fitting functions by Nicola Ferralis
+ *
+ *
+ * All Rights Reserved
+@@ -47,6 +48,7 @@
+ #include "parser.h"
+ #include "motifinc.h"
+ #include "protos.h"
++#include "events.h"
+
+ /* nonlprefs.load possible values */
+ #define LOAD_VALUES 0
+@@ -98,6 +100,34 @@
+ static void nonl_wf_cb(int value, void *data);
+ static void do_constr_toggle(int onoff, void *data);
+
++static void nonl_Lorentzian_cb(void *data);
++static void nonl_doubleLorentzian_cb(void *data);
++static void nonl_tripleLorentzian_cb(void *data);
++static void nonl_Gaussian_cb(void *data);
++static void nonl_doubleGaussian_cb(void *data);
++static void nonl_tripleGaussian_cb(void *data);
++static void nonl_Gaussian2_cb(void *data);
++static void nonl_PsVoight1_cb(void *data);
++static void nonl_PsVoight2_cb(void *data);
++static void nonl_DS_cb(void *data);
++static void nonl_Asym2Sig_cb(void *data);
++static void nonl_LogNormal_cb(void *data);
++static void nonl_GCAS_cb(void *data);
++static void nonl_ECS_cb(void *data);
++static void nonl_InvPoly_cb(void *data);
++static void nonl_Sine_cb(void *data);
++static void nonl_Sinesq_cb(void *data);
++static void nonl_Sinedamp_cb(void *data);
++static void nonl_ExpDec1_cb(void *data);
++static void nonl_ExpDec2_cb(void *data);
++static void nonl_ExpGrow1_cb(void *data);
++static void nonl_ExpGrow2_cb(void *data);
++static void nonl_Hyperbol_cb(void *data);
++static void nonl_Bradley_cb(void *data);
++static void nonl_Log3_cb(void *data);
++static void nonl_WeibullPD_cb(void *data);
++static void nonl_WeibullCD_cb(void *data);
++
+ static void update_nonl_frame_cb(void *data);
+ static void reset_nonl_frame_cb(void *data);
+
+@@ -118,7 +148,7 @@
+ if (nonl_frame == NULL) {
+ int i;
+ OptionItem np_option_items[MAXPARM + 1], option_items[5];
+- Widget menubar, menupane;
++ Widget menubar, menupane, submenugauss, submenulorentz, submenupeak, submenubaseline, submenuperiodic;
+ Widget nonl_tab, nonl_main, nonl_advanced;
+ Widget sw, title_fr, fr3, rc1, rc2, rc3, lab;
+
+@@ -145,6 +175,54 @@
+ CreateMenuSeparator(menupane);
+ CreateMenuButton(menupane, "Update", 'U', update_nonl_frame_cb, NULL);
+
++ menupane = CreateMenu(menubar, "Library", 'L', FALSE);
++
++ submenugauss = CreateMenu(menupane, "Gaussian Functions", 'G', FALSE);
++ CreateMenuButton(submenugauss, "Single", 'g', nonl_Gaussian_cb, NULL);
++ CreateMenuButton(submenugauss, "Double", 'D', nonl_doubleGaussian_cb, NULL);
++ CreateMenuButton(submenugauss, "Triple", 'T', nonl_tripleGaussian_cb, NULL);
++ CreateMenuSeparator(submenugauss);
++ CreateMenuButton(submenugauss, "Single (chromatography)", 'c', nonl_Gaussian2_cb, NULL);
++ CreateMenuSeparator(menupane);
++
++ submenulorentz = CreateMenu(menupane, "Lorentzian Functions", 'L', FALSE);
++ CreateMenuButton(submenulorentz, "Single", 'S', nonl_Lorentzian_cb, NULL);
++ CreateMenuButton(submenulorentz, "Double", 'D', nonl_doubleLorentzian_cb, NULL);
++ CreateMenuButton(submenulorentz, "Triple", 'T', nonl_tripleLorentzian_cb, NULL);
++ CreateMenuSeparator(menupane);
++
++ submenupeak = CreateMenu(menupane, "Peak Functions", 'P', FALSE);
++ CreateMenuButton(submenupeak, "Pseudo Voigt 1", 'V', nonl_PsVoight1_cb, NULL);
++ CreateMenuButton(submenupeak, "Pseudo Voigt 2", 'o', nonl_PsVoight2_cb, NULL);
++ CreateMenuButton(submenupeak, "Doniach-Sunjic", 'D', nonl_DS_cb, NULL);
++ CreateMenuButton(submenupeak, "Asymmetric Double Sigmoidal", 'S', nonl_Asym2Sig_cb, NULL);
++ CreateMenuButton(submenupeak, "LogNormal", 'L', nonl_LogNormal_cb, NULL);
++ CreateMenuButton(submenupeak, "Gram-Charlier A-Series", 'C', nonl_GCAS_cb, NULL);
++ CreateMenuButton(submenupeak, "Edgeworth-Cramer Series", 'E', nonl_ECS_cb, NULL);
++ CreateMenuButton(submenupeak, "Inverse Polynomial", 'I', nonl_InvPoly_cb, NULL);
++ CreateMenuSeparator(menupane);
++
++ submenuperiodic = CreateMenu(menupane, "Periodic Peak Functions", 'e', FALSE);
++ CreateMenuButton(submenuperiodic, "Sine", 'S', nonl_Sine_cb, NULL);
++ CreateMenuButton(submenuperiodic, "Sine Square", 'q', nonl_Sinesq_cb, NULL);
++ CreateMenuButton(submenuperiodic, "Sine Damp", 'D', nonl_Sinedamp_cb, NULL);
++ CreateMenuSeparator(menupane);
++
++ submenubaseline = CreateMenu(menupane, "Baseline Functions", 'B', FALSE);
++ CreateMenuButton(submenubaseline, "Exponential Decay 1", 'D', nonl_ExpDec1_cb, NULL);
++ CreateMenuButton(submenubaseline, "Exponential Decay 2", 'e', nonl_ExpDec2_cb, NULL);
++ CreateMenuButton(submenubaseline, "Exponential Growth 1", 'G', nonl_ExpGrow1_cb, NULL);
++ CreateMenuButton(submenubaseline, "Exponential Growth 2", 'r', nonl_ExpGrow2_cb, NULL);
++ CreateMenuButton(submenubaseline, "Hyperbolic Function", 'H', nonl_Hyperbol_cb, NULL);
++ CreateMenuSeparator(submenubaseline);
++ CreateMenuButton(submenubaseline, "Bradley", 'B', nonl_Bradley_cb, NULL);
++ CreateMenuButton(submenubaseline, "Logarithm 3", 'L', nonl_Log3_cb, NULL);
++ CreateMenuSeparator(submenubaseline);
++ CreateMenuButton(submenubaseline, "Weibull Probability Density", 'W', nonl_WeibullPD_cb, NULL);
++ CreateMenuButton(submenubaseline, "Weibull Cumulative", 'w', nonl_WeibullCD_cb, NULL);
++ CreateMenuSeparator(menupane);
++
++ CreateMenuButton(menupane, "Reset fit parameters", 'R', reset_nonl_frame_cb, NULL);
+ menupane = CreateMenu(menubar, "Help", 'H', TRUE);
+
+ CreateMenuHelpButton(menupane, "On fit", 'f',
+@@ -712,3 +790,343 @@
+ }
+ return TRUE;
+ }
++
++
++static void nonl_Lorentzian_cb(void *data)
++{ int i;
++ nonl_opts.title = copy_string(nonl_opts.title, "Lorentzian function");
++ nonl_opts.formula = copy_string(nonl_opts.formula, "y = A0 + (2*A2*A3/pi)/(4*(x-A1)^2 + A2^2)");
++ nonl_opts.parnum = 4;
++
++ for (i=0; i