io.fair_acc.sample.dataset.legacy.DoubleDataSet Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of samples Show documentation
Show all versions of samples Show documentation
Small sample applications to showcase the features of the chart-fx library.
The newest version!
package io.fair_acc.sample.dataset.legacy;
import java.util.Arrays;
import io.fair_acc.dataset.AxisDescription;
import io.fair_acc.dataset.DataSet;
import io.fair_acc.dataset.DataSet2D;
import io.fair_acc.dataset.EditableDataSet;
import io.fair_acc.dataset.events.ChartBits;
import io.fair_acc.dataset.spi.AbstractDataSet;
import io.fair_acc.dataset.spi.DoubleErrorDataSet;
import io.fair_acc.dataset.utils.AssertUtils;
/**
* Implementation of the DataSet
interface which stores x,y values in two separate arrays. It provides
* methods allowing easily manipulate of data points.
* User provides X and Y coordinates or only Y coordinates. In the former case X coordinates have value of data point
* index. This version being optimised for native double arrays.
*
* @see DoubleErrorDataSet for an equivalent implementation with asymmetric errors in Y
* @author rstein
* @deprecated this is kept for reference/performance comparisons only
*/
@SuppressWarnings("PMD")
public class DoubleDataSet extends AbstractDataSet implements EditableDataSet, DataSet2D {
private static final long serialVersionUID = 467969092912080826L;
protected double[] xValues;
protected double[] yValues;
protected int dataMaxIndex; // <= xValues.length, stores the actually used
// data array size
/**
* Creates a new instance of DoubleDataSet
as copy of another (deep-copy).
*
* @param another name of this DataSet.
*/
public DoubleDataSet(final DataSet2D another) {
this("");
lock().writeLockGuard(() -> another.lock().writeLockGuard(() -> {
this.setName(another.getName());
this.set(another); // NOPMD by rstein on 25/06/19 07:42
}));
}
/**
* Creates a new instance of DoubleDataSet
.
*
* @param name name of this DataSet.
* @throws IllegalArgumentException if name
is null
*/
public DoubleDataSet(final String name) {
this(name, 0);
}
/**
*
* Creates a new instance of DoubleDataSet
.
*
* The user than specify via the copy parameter, whether the dataset operates directly on the input arrays
* themselves or on a copies of the input arrays. If the dataset operates directly on the input arrays, these arrays
* must not be modified outside of this data set.
*
* @param name name of this data set.
* @param xValues X coordinates
* @param yValues Y coordinates
* @param initalSize initial buffer size
* @param deepCopy if true, the input array is copied
* @throws IllegalArgumentException if any of parameters is null
or if arrays with coordinates have
* different lengths
*/
public DoubleDataSet(final String name, final double[] xValues, final double[] yValues, final int initalSize,
final boolean deepCopy) {
this(name);
AssertUtils.notNull("X data", xValues);
AssertUtils.notNull("Y data", yValues);
dataMaxIndex = Math.min(xValues.length, Math.min(yValues.length, initalSize));
AssertUtils.equalDoubleArrays(xValues, yValues, initalSize);
if (deepCopy) {
this.xValues = new double[dataMaxIndex];
this.yValues = new double[dataMaxIndex];
System.arraycopy(xValues, 0, this.xValues, 0, Math.min(xValues.length, initalSize));
System.arraycopy(yValues, 0, this.yValues, 0, Math.min(yValues.length, initalSize));
} else {
this.xValues = xValues;
this.yValues = yValues;
}
}
/**
* Creates a new instance of DoubleDataSet
.
*
* @param name name of this DataSet.
* @param initalSize initial buffer size
* @throws IllegalArgumentException if name
is null
*/
public DoubleDataSet(final String name, final int initalSize) {
super(name, 2);
AssertUtils.gtEqThanZero("initalSize", initalSize);
xValues = new double[initalSize];
yValues = new double[initalSize];
dataMaxIndex = 0;
}
/**
* Add point to the end of the data set
*
* @param x index
* @param y index
* @return itself
*/
public DoubleDataSet add(final double x, final double y) {
return add(this.getDataCount(), x, y, null);
}
/**
* Add point to the DoublePoints object
*
* @param x index
* @param y index
* @param label the data label
* @return itself
*/
public DoubleDataSet add(final double x, final double y, final String label) {
return add(this.getDataCount(), x, y, label);
}
/**
*
* Initialises the data set with specified data.
*
* Note: The method copies values from specified double arrays.
*
* @param xValuesNew X coordinates
* @param yValuesNew Y coordinates
* @return itself
*/
public DoubleDataSet add(final double[] xValuesNew, final double[] yValuesNew) {
lock();
AssertUtils.notNull("X coordinates", xValuesNew);
AssertUtils.notNull("Y coordinates", yValuesNew);
AssertUtils.equalDoubleArrays(xValuesNew, yValuesNew);
lock().writeLockGuard(() -> {
final int newLength = this.getDataCount() + xValuesNew.length;
// need to allocate new memory
if (newLength > xValues.length) {
final double[] xValuesNewAlloc = new double[newLength];
final double[] yValuesNewAlloc = new double[newLength];
// copy old data
System.arraycopy(xValues, 0, xValuesNewAlloc, 0, getDataCount());
System.arraycopy(yValues, 0, yValuesNewAlloc, 0, getDataCount());
xValues = xValuesNewAlloc;
yValues = yValuesNewAlloc;
}
// N.B. getDataCount() should equal dataMaxIndex here
System.arraycopy(xValuesNew, 0, xValues, getDataCount(), xValuesNew.length);
System.arraycopy(yValuesNew, 0, yValues, getDataCount(), xValuesNew.length);
dataMaxIndex = Math.max(0, dataMaxIndex + xValuesNew.length);
recomputeLimits(DIM_X);
recomputeLimits(DIM_Y);
});
fireInvalidated(ChartBits.DataSetDataAdded);
return getThis();
}
/**
* add point to the data set
*
* @param index data point index at which the new data point should be added
* @param newValues coordinate of the new data point
* @return itself (fluent design)
*/
@Override
public DoubleDataSet add(final int index, final double... newValues) {
return add(index, newValues[0], newValues[1], null);
}
/**
* add point to the data set
*
* @param index data point index at which the new data point should be added
* @param x horizontal coordinate of the new data point
* @param y vertical coordinate of the new data point
* @param label data point label (see CategoryAxis)
* @return itself (fluent design)
*/
public DoubleDataSet add(final int index, final double x, final double y, final String label) {
lock().writeLockGuard(() -> {
final int indexAt = Math.max(0, Math.min(index, getDataCount() + 1));
// enlarge array if necessary
final int minArraySize = Math.min(xValues.length - 1, yValues.length - 1);
if (dataMaxIndex > minArraySize) {
final double[] xValuesNew = new double[dataMaxIndex + 1];
final double[] yValuesNew = new double[dataMaxIndex + 1];
// copy old data before required index
System.arraycopy(xValues, 0, xValuesNew, 0, indexAt);
System.arraycopy(yValues, 0, yValuesNew, 0, indexAt);
// copy old data after required index
System.arraycopy(xValues, indexAt, xValuesNew, indexAt + 1, xValues.length - indexAt);
System.arraycopy(yValues, indexAt, yValuesNew, indexAt + 1, yValues.length - indexAt);
// shift old label and style keys
for (int i = xValues.length; i >= indexAt; i--) {
final String oldLabelData = getDataLabelMap().get(i);
if (oldLabelData != null) {
getDataLabelMap().put(i + 1, oldLabelData);
getDataLabelMap().remove(i);
}
final String oldStyleData = getDataStyleMap().get(i);
if (oldStyleData != null) {
getDataStyleMap().put(i + 1, oldStyleData);
getDataStyleMap().remove(i);
}
}
xValues = xValuesNew;
yValues = yValuesNew;
}
xValues[indexAt] = x;
yValues[indexAt] = y;
if (label != null && !label.isEmpty()) {
addDataLabel(indexAt, label);
}
dataMaxIndex++;
getAxisDescription(DIM_X).add(x);
getAxisDescription(DIM_Y).add(y);
});
fireInvalidated(ChartBits.DataSetDataAdded);
return getThis();
}
/**
* clear all data points
*
* @return itself (fluent design)
*/
public DoubleDataSet clearData() {
lock().writeLockGuard(() -> {
dataMaxIndex = 0;
Arrays.fill(xValues, 0.0);
Arrays.fill(yValues, 0.0);
getDataLabelMap().clear();
getDataStyleMap().clear();
getAxisDescriptions().forEach(AxisDescription::clear);
});
fireInvalidated(ChartBits.DataSetDataRemoved);
return getThis();
}
@Override
public double get(final int dimImdex, final int index) {
return dimImdex == DIM_X ? xValues[index] : yValues[index];
}
@Override
public int getDataCount() {
return Math.min(dataMaxIndex, xValues.length);
}
@Override
public double[] getXValues() {
return xValues;
}
@Override
public double[] getYValues() {
return yValues;
}
/**
* remove point from data set
*
* @param index data point which should be removed
* @return itself (fluent design)
*/
@Override
public EditableDataSet remove(final int index) {
return remove(index, index + 1);
}
/**
* removes sub-range of data points
*
* @param fromIndex start index
* @param toIndex stop index
* @return itself (fluent design)
*/
public DoubleDataSet remove(final int fromIndex, final int toIndex) {
lock().writeLockGuard(() -> {
AssertUtils.indexInBounds(fromIndex, getDataCount(), "fromIndex");
AssertUtils.indexInBounds(toIndex, getDataCount(), "toIndex");
AssertUtils.indexOrder(fromIndex, "fromIndex", toIndex, "toIndex");
final int diffLength = toIndex - fromIndex;
final int newLength = xValues.length - diffLength;
final double[] xValuesNew = new double[newLength];
final double[] yValuesNew = new double[newLength];
System.arraycopy(xValues, 0, xValuesNew, 0, fromIndex);
System.arraycopy(yValues, 0, yValuesNew, 0, fromIndex);
System.arraycopy(xValues, toIndex, xValuesNew, fromIndex, newLength - fromIndex);
System.arraycopy(yValues, toIndex, yValuesNew, fromIndex, newLength - fromIndex);
xValues = xValuesNew;
yValues = yValuesNew;
// remove old label and style keys
for (int i = 0; i < diffLength; i++) {
final String oldLabelData = getDataLabelMap().get(toIndex + i);
if (oldLabelData != null) {
getDataLabelMap().put(fromIndex + i, oldLabelData);
getDataLabelMap().remove(toIndex + i);
}
final String oldStyleData = getDataStyleMap().get(toIndex + i);
if (oldStyleData != null) {
getDataStyleMap().put(fromIndex + i, oldStyleData);
getDataStyleMap().remove(toIndex + i);
}
}
dataMaxIndex = Math.max(0, dataMaxIndex - diffLength);
getAxisDescriptions().forEach(AxisDescription::clear);
});
fireInvalidated(ChartBits.DataSetDataRemoved);
return getThis();
}
/**
* clear old data and overwrite with data from 'other' data set (deep copy)
*
* @param other the source data set
* @return itself (fluent design)
*/
public DoubleDataSet set(final DataSet2D other) {
lock().writeLockGuard(() -> other.lock().writeLockGuard(() -> {
// deep copy data point labels and styles
getDataLabelMap().clear();
for (int index = 0; index < other.getDataCount(); index++) {
final String label = other.getDataLabel(index);
if (label != null && !label.isEmpty()) {
this.addDataLabel(index, label);
}
}
getDataStyleMap().clear();
for (int index = 0; index < other.getDataCount(); index++) {
final String style = other.getStyle(index);
if (style != null && !style.isEmpty()) {
this.addDataStyle(index, style);
}
}
this.setStyle(other.getStyle());
this.set(other.getXValues(), other.getYValues(), true);
}));
fireInvalidated(ChartBits.DataSetData);
return getThis();
}
/**
*
* Initialises the data set with specified data.
*
* Note: The method copies values from specified double arrays.
*
* @param xValues X coordinates
* @param yValues Y coordinates
* @return itself
*/
public DoubleDataSet set(final double[] xValues, final double[] yValues) {
return set(xValues, yValues, true);
}
/**
*
* Initialises the data set with specified data.
*
* Note: The method copies values from specified double arrays.
*
* @param xValues X coordinates
* @param yValues Y coordinates
* @param copy true: makes an internal copy, false: use the pointer as is (saves memory allocation
* @return itself
*/
public DoubleDataSet set(final double[] xValues, final double[] yValues, final boolean copy) {
AssertUtils.notNull("X coordinates", xValues);
AssertUtils.notNull("Y coordinates", yValues);
AssertUtils.equalDoubleArrays(xValues, yValues);
lock().writeLockGuard(() -> {
if (!copy) {
this.xValues = xValues;
this.yValues = yValues;
dataMaxIndex = xValues.length;
recomputeLimits(DIM_X);
recomputeLimits(DIM_Y);
return;
}
if (xValues.length == this.xValues.length) {
System.arraycopy(xValues, 0, this.xValues, 0, getDataCount());
System.arraycopy(yValues, 0, this.yValues, 0, getDataCount());
} else {
/*
* copy into new arrays, forcing array length equal to the xValues length
*/
this.xValues = Arrays.copyOf(xValues, xValues.length);
this.yValues = Arrays.copyOf(yValues, xValues.length);
}
dataMaxIndex = xValues.length;
recomputeLimits(DIM_X);
recomputeLimits(DIM_Y);
});
fireInvalidated(ChartBits.DataSetData);
return getThis();
}
@Override
public DoubleDataSet set(final int index, final double... newValue) {
lock().writeLockGuard(() -> {
xValues[index] = newValue[0];
yValues[index] = newValue[1];
dataMaxIndex = Math.max(index, dataMaxIndex);
getAxisDescriptions().forEach(AxisDescription::clear);
});
fireInvalidated(ChartBits.DataSetData);
return getThis();
}
@Override
public EditableDataSet set(final DataSet other, final boolean copy) {
throw new UnsupportedOperationException("Copy setter not implemented");
}
}