Using Manipulate to find best starting parameters to fit data

As I understand the question a curve fitting procedure that has the following properties is sought:

  1. Manually adjust the parameters to get an approximate fit.
  2. Use these parameters as the starting values for FindFit.
  3. Propagate the solution from FindFit back to the Manipulate parameters.
  4. Subsequently enable further editing of the Manipulate parameters and repeat the cycle.

The following code satisfies this criteria by wrapping Manipulate inside a DynamicModule and the use of a Button to indicate when FindFit should be run.

data = Table[{x, 8 x^3 - 7 x^2 - 10 x + 1 + RandomReal[{-5, 5}]}, {x, -2, 2, 0.1}];

DynamicModule[
 {
  sol
  },

 Manipulate[

  If[computeFlag == True,
   sol = FindFit[data, 
     aa x^3 + bb x^2 + cc x + 
      dd, {{aa, a}, {bb, b}, {cc, c}, {dd, d}}, x];
   {a, b, c, d} = {aa, bb, cc, dd} /. sol;
   computeFlag = False;
   ];

  Column[{
    Dynamic[
     Button["Compute",
      computeFlag = True
      ]
     ],
    Show[
     Plot[a x^3 + b x^2 + c x + d, {x, -2, 2},
      PlotStyle -> Black],
     ListPlot[data, PlotStyle -> Red],
     ImageSize -> 300,
     PlotRange -> {{-2.05, 2.05}, All}
     ]
    }],

  (*Manipulate variables*)
  {{computeFlag, False}, ControlType -> None},

  {{a, 1}, -10, 10, Appearance -> "Open"},
  {{b, 1}, -10, 10, Appearance -> "Open"},
  {{c, 1}, -10, 10, Appearance -> "Open"},
  {{d, 1}, -10, 10, Appearance -> "Open"}

  ] (* end of Manipulate *)
 ] (* end of DynamicModule *)

Below is a figure where the parameters have been manually adjusted.

Mathematica graphics

After clicking the Compute button FindFit propagates the solution back to the Manipulate parameters.

Mathematica graphics

The user is free to re-edit the Manipulate parameters and repeat the cycle.


dynamicFit[data_, expr_, pars_] :=
 With[{
   n = Length[pars],
   x1 = Min[First /@ data],
   x2 = Max[First /@ data]},
  DynamicModule[{pars2, fit, fitted = Null},
   pars2 = Table[Unique[], n];
   Do[pars2[[i]] = RandomReal[{-2, 2}], {i, n}];
   Column[{
     Sequence @@ Table[
       With[{i = i},
        Labeled[
         Slider[Dynamic[pars2[[i]]], {-10, 10}, 
          Appearance -> "Labeled",
          ImageSize -> 275], pars[[i]], Left]], {i, n}],
     Dynamic@Framed@Show[
        Plot[Evaluate[{expr[x] /. Thread[pars -> pars2], fitted}],
         {x, x1, x2}],
        ListPlot[data],
        ImageSize -> 300],
     Row[{
       Button["Fit",
        fit = FindFit[data, expr[x], Transpose[{pars, pars2}], x];
        fitted = expr[x] /. fit,
        ImageSize -> Automatic],
       Button["Export",
        exported = fitted,
        ImageSize -> Automatic]
       }]
     }]
   ]
  ]

Parameters are: data, model expr (as a Function) and model parameters pars (used in the model). Your arguments can be quite general as long as the data is 2D and model a function of one variable. Clear exported before invoking the routine, adjust parameters dynamically, try a fit, adjust some more ... eventually export the fit to exported.

test = Table[{x,
    x + Sin[3 x] + RandomReal[{-.5, .5}]}, {x, -3, 3, 0.1}];

exported = Null;
dynamicFit[test, Function[x, a x + Sin[b x]], {a, b}]

enter image description here

The fit resides in exported. This is a bit clumsy, I wish I knew how to do it better.

exported

0.995803 x + Sin[3.04859 x]