Apache GaussianCurveFitter заходит в тупик (?) - PullRequest
0 голосов
/ 11 апреля 2019

Я работаю над кодом, анализирующим периодический шумовой сигнал. Сигнал подается в моем примере в виде файла CSV, содержащего около 382 периодов сигнала в 25000 бинов, которые загружаются в мой класс. Я разбил данные на подмножества, представляющие по одному пику каждый, и применил GaussianCurveFitter к каждому из наборов данных. В определенных случаях - я думаю, если данные, переданные Fitter, являются дрянными и очень негауссовыми - CurveFitter просто заходит в тупик или бесконечный цикл и никогда не возвращается к жизни. Я не понимаю, почему.

Вот код:

package de.gsi.sdbe.playground.wgeithner.BpmFitTest.main;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
import org.apache.commons.math3.fitting.GaussianCurveFitter;
import org.apache.commons.math3.fitting.WeightedObservedPoints;
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
import de.gsi.chart.data.spi.DefaultDataSet;

public class TemplateAppModel {

final private WeightedObservedPoints _fitDataSet = new WeightedObservedPoints(); // datasets for curve fitting
private final ArrayList<Double>      _rawDataY   = new ArrayList<>();

public DefaultDataSet loadCsvFile() {

    Scanner fileScanner = null;
    try {
        fileScanner = new Scanner(new File("src/main/resources/YR06DX1HSignal.csv"));
    } catch (final FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    final DefaultDataSet dataSet = new DefaultDataSet("Signal"); // dataset for visualization

    while (fileScanner.hasNextLine()) {
        final String lineText = fileScanner.nextLine();
        final String[] xyItems = lineText.split(",");
        try {
            dataSet.add(Double.valueOf(xyItems[0]), Double.valueOf(xyItems[1]));
            _rawDataY.add(Double.valueOf(xyItems[1]));
        } catch (final NumberFormatException ex) {
            // DO NOTHING
        }

    }

    fileScanner.close();

    return dataSet;
}

public ArrayList<Double> doBoxedPeakFitting(final Double binLengthIn, final Double rfFrequencyIn) {

    final ArrayList<Double> fitSummary = new ArrayList<>();
    final Double binLength = 8e-9; // in nanoseconds
    final Double rfFrequency = 1907440.2; // in Hz

    final Double dataSetTimeLength = _rawDataY.size() * binLength;
    final int peakCount = (int) Math.round(dataSetTimeLength * rfFrequency);

    // move a box over the data set an perform a fit for each boxed peak
    final int peakBoxSize = _rawDataY.size() / peakCount;

    for (int peakBoxCounter = 0; peakBoxCounter < peakCount; peakBoxCounter++) {

        final int maxRawIndex = peakBoxCounter * peakBoxSize + peakBoxSize;

        final List<Double> fitWindow = _rawDataY.subList(peakBoxCounter * peakBoxSize, maxRawIndex);

        final Double minimum = Collections.min(fitWindow);

        System.out.println("Minimum: " + minimum);

        final List<Double> fitWindowNormalized = new ArrayList<>();
        // add an offset to data to get everything into positive
        for (final Double item : fitWindow) {
            fitWindowNormalized.add(item - minimum);
        }

        // perform the actual fit
        final double[] fitResult = doFit(fitWindowNormalized, peakBoxCounter);

        if (fitResult.length == 3) {
            fitSummary.add(fitResult[2]);
        }
    }

    return fitSummary;
}

private double[] doFit(final List<Double> dataSet, final int fitIndex) {

    final WeightedObservedPoints fitData = new WeightedObservedPoints();
    double xValue = 0.0;

    // map the input to a format Apache GaussianCurveFitter expects
    for (final double yValue : dataSet) {
        fitData.add(xValue, yValue);
        xValue++;

    }

    GaussianCurveFitter theFitter = GaussianCurveFitter.create();
    theFitter.withMaxIterations(1);

    try {
        final double[] fitResult = theFitter.fit(fitData.toList());
        theFitter = null;
        return fitResult;
    } catch (final Exception ex) {
        System.out.println(fitIndex);
        ex.printStackTrace();

        for (final Double value : dataSet) {
            System.out.println(value);
        }

    }

    return new double[1];
}

public static double getMinValue(final double[] numbers) {
    double minValue = numbers[0];
    for (int i = 1; i < numbers.length; i++) {
        if (numbers[i] < minValue) {
            minValue = numbers[i];
        }
    }
    return minValue;
}

public static void main(final String[] args) {
    final TemplateAppModel model = new TemplateAppModel();
    model.loadCsvFile();
    final ArrayList<Double> result = model.doBoxedPeakFitting(null, null);

    final DescriptiveStatistics stats = new DescriptiveStatistics();
    result.stream().forEach(item -> {
        stats.addValue(item.doubleValue());
    });

    System.out.println("Mean: " + stats.getMean());

}

}

Это ошибка в библиотеке Apache или я что-то не так делаю? При необходимости я могу также предоставить файл данных CSV ...

...