#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-файла)