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 Wed, 24 Nov 2010 17:29:03 -0800 + grace (1:5.1.22-5) unstable; urgency=low * Compile with -g0 on mips and mipsel, as a workaround for a FTBFS diff -u grace-5.1.22/debian/patches/series grace-5.1.22/debian/patches/series --- grace-5.1.22/debian/patches/series +++ grace-5.1.22/debian/patches/series @@ -8,0 +9 @@ +nonlinear_extended.diff only in patch2: unchanged: --- grace-5.1.22.orig/debian/patches/nonlinear_extended.diff +++ grace-5.1.22/debian/patches/nonlinear_extended.diff @@ -0,0 +1,756 @@ +Description: Add multiple non-linear data fitting functions + One of the most used features in software for scientific data analysis is + the ability to perform non linear peak fitting (specifically Lorentzian and + Gaussian fits). Xmgrace sorely lacks this capability, unless you consider + adding manually the required formula. + . + This implements a substantial library of such functions and documentation + for their use. +Author: Nicola Ferralis +Bug: http://plasma-gate.weizmann.ac.il/Grace/phpbb/w3todo.php?action=view_report&project_id=1&todo_id=2220 +Bug-Debian: http://bugs.debian.org/578435 +Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/grace/+bug/535459 +Last-Update: 2010-05-26 +Index: grace-5.1.22/doc/UsersGuide.html +=================================================================== +--- grace-5.1.22.orig/doc/UsersGuide.html 2008-05-21 13:52:14.000000000 -0700 ++++ grace-5.1.22/doc/UsersGuide.html 2010-07-27 11:01:29.000000000 -0700 +@@ -1516,6 +1516,103 @@ + sample range or to produce an evenly spaced set from an irregular + one.

+ ++

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)
++

++ +

Correlation/covariance

+ +

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