Apache GaussianCurveFitter заходит в тупик (?)

#java #apache-commons-math

#java #apache-commons-math

Вопрос:

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

Здесь код:

 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 fitResu<
    } 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…

Комментарии:

1. CSV действительно может помочь, предполагая, что тогда можно просто скопировать вставить код, запустить его в режиме отладки и нажать «пауза» в какой-то момент, чтобы увидеть, где он застрял. (Вы также могли бы это сделать, но … может быть, за этим стоит что-то еще …)

2. Привет, Марко, у тебя есть подсказка, куда поместить CSV?

3. Загруженный файл данных в Google drive:drive.google.com/file/d/1xojpk6Jbg8SysRtYywIhCeiCOzSiy8be /…

4. Не совсем ясно, на каком «уровне» следует ответить на вопрос. Прежде всего: строка theFitter.withMaxIterations(1); не имеет смысла — была ли это «попыткой отладки / обхода»? Метод возвращает нового монтажника, так что, вероятно, это должно быть theFitter = theFitter.withMaxIterations(1000); или около того. Затем подгонка выдаст исключение, потому что оно не сходится за 1000 итераций. Ответ на вопрос о том, почему он не сходится, может не быть «связанным с программированием» в самом строгом смысле, но, возможно, здесь все же можно было бы разобраться…

5. Привет, Марко, ваш комментарий верен, и ваше предположение относительно удаления ошибок тоже. Я просто забыл удалить его перед отправкой своего вопроса. Что касается вопроса как такового: мне не ясно, является ли тупиковая ситуация (/ бесконечный цикл) ошибкой в среде Apache или я делаю что-то не так. Поскольку я не нашел ошибки в своем коде, который работает правильно около 60 циклов, но перестает выходить из процедуры подгонки с циклом 61 (на основе понравившегося CSV-файла)