0

I've spend a few days trying to get this exact same code running in java: How do I fit a sine curve to my data with pylab and numpy?

Based on this answer: Sine Wave Curve Fitting in Java, I've started putting together this code:

public double sine_fit(double[] current_sample){
        double[] half_cycle = Arrays.copyOfRange(current_sample, 175, 225);
        double amp = 3*ArrayUtils.std(half_cycle)/Math.sqrt(2);
        double freq = 0;
        double phase = 0;
        double[] guess = new double[]{amp, freq, phase};
        HarmonicCurveFitter curveFit = new HarmonicCurveFitter(new LevenbergMarquardtOptimizer());
        //curveFit.withStartPoint(guess);
        for (int i=0; i < half_cycle.length; i++) {
            curveFit.addObservedPoint(i, half_cycle[i]);
        }
        double[] vals = curveFit.fit();
        System.out.println(vals);
    }

It doesn't compile, and it's not quite what I want (i.e., exactlty what's in the first link)

I'd really appreciate some help. Not being able to do in Java what I can do with only a few lines in Python is driving me nuts.

P.S.: Long time Python coder, newbee Java programmer.

Update

Based on @17slim's answer:

    double[] half_cycle = Arrays.copyOfRange(current_sample, 175, 225);
    double amp = 3*ArrayUtils.std(half_cycle)/Math.sqrt(2);
    double freq = 0;
    double phase = 0;
    double[] guess = new double[]{amp, freq, phase};
    HarmonicCurveFitter curveFit = HarmonicCurveFitter.create();
    curveFit.withStartPoint(guess);
    List<WeightedObservedPoint> points = new ArrayList<WeightedObservedPoint>();
    for (int i=0; i < half_cycle.length; i++) {
        points.add(new WeightedObservedPoint(1.0, i, half_cycle[i]));
    }
    double[] vals = curveFit.fit(points);
    for (double val: vals){
        System.out.println(val);
    }
  • 3
    What error do you get? – talex Jul 13 '17 at 17:51
  • - Cannot resolve method `addObservedPoint` - Constructor HarmonicCurveFitter in class org.apache.commons.math3.fitting.HarmonicCurveFitter cannot be applied to given types; required: double[],int found: org.apache.commons.math3.fitting.leastsquares.LevenbergMarquardtOptimizer - Method fit in class org.apache.commons.math3.fitting.AbstractCurveFitter cannot be applied to given types; required: java.util.Collection found: no arguments – Caroline Sofiatti Jul 13 '17 at 17:54
  • what is HarmonicCurveFitter? I can't seem to find a reference for that anywhere – Jamal H Jul 13 '17 at 17:58
  • `import org.apache.commons.math3.fitting.HarmonicCurveFitter;` – Caroline Sofiatti Jul 13 '17 at 17:59

2 Answers2

0

HarmonicCurveFitter does not extend CurveFitter; it extends AbstractCurveFitter, which does not have method addObservedPoint. GaussianFitter, HarmonicFitter, and PolynomialFitter are the known extenders of CurveFitter, which has the required method. Use HarmonicFitter.

See: CurveFitter and HarmonicCurveFitter

EDIT: Since HarmonicFitter is deprecated, you are correct to use HarmonicCurveFitter. Since it doesn't have the method you need, use fit(Collection<WeightedObservedPoint> points) instead of addObservedPoint.

Instead do:

HarmonicCurveFitter curveFit = new HarmonicCurveFitter.create();
List<WeightedObservedPoint> points = new ArrayList<WeightedObservedPoint>();
for (int i=0; i < half_cycle.length; i++) {
    points.add(new WeightedObservedPoint(1.0, i, half_cycle[i]));
}
double[] vals = curveFit.fit(points);

From the documentation:

The default implementation uses a Levenberg-Marquardt optimizer.

Make sure to import org.apache.commons.math3.fitting.WeightedObservedPoint, org.apache.commons.math3.fittingHarmonicCurveFitter, java.util.List and java.util.ArrayList.

Also, printing vals does not print each value like in Python, it prints a pointer to the array. Use for (double val: vals) and display each value individually.

17slim
  • 1,233
  • 1
  • 16
  • 21
  • `HarmonicFitter` seems to be deprecated. I'm supposed to use `HarmonicCurveFitter` and `WeightedObservedPoints`. I tried, and that also didn't go too far. – Caroline Sofiatti Jul 13 '17 at 18:02
  • You are correct, but it will work in exactly the same way. I'll try to find an undeprecated equivalent. – 17slim Jul 13 '17 at 18:03
  • Ok, from the documentation: `As of 3.3. Please use HarmonicCurveFitter and WeightedObservedPoints instead.` – 17slim Jul 13 '17 at 18:05
  • So, you are correct to use `HarmonicCurveFitter`, but since it doesn't have the required method, you should implement it instead with `fit(Collection points)` – 17slim Jul 13 '17 at 18:06
  • 1
    Awesome! That works!!! Last think I need to figure out is the least square step. What I was trying with the `LevenbergMarquardtOptimizer()`. And how to get back a sine array, instead of just the parameters. – Caroline Sofiatti Jul 13 '17 at 18:25
  • Edited to include info about the optimizer – 17slim Jul 13 '17 at 18:30
0

The problem is that you have to use HarmonicFitter class and the method of that class - addObservedPoint. Neither the class HarmonicCurveFitter nor his parent AbstractCurveFitter do not contain method addObservedPoint.