Skip to content

Commit

Permalink
fixes autoranging for CircularDoubleErrorDataSet (issue #378) + addit…
Browse files Browse the repository at this point in the history
…ional unit-tests and follow-up fixes
  • Loading branch information
RalphSteinhagen authored and wirew0rm committed Mar 8, 2021
1 parent d198469 commit cd202c7
Show file tree
Hide file tree
Showing 11 changed files with 385 additions and 205 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import java.util.ArrayDeque;

import de.gsi.dataset.AxisDescription;
import de.gsi.dataset.DataSet;
import de.gsi.dataset.event.AddedDataEvent;
import de.gsi.dataset.event.UpdatedDataEvent;

/**
* TODO: Change to ErrorDataSet and calculate standard deviation.
Expand All @@ -13,10 +15,17 @@
public class AveragingDataSet extends AbstractDataSet<AveragingDataSet> implements DataSet {
private static final long serialVersionUID = 1L;
private int averageSize = 1;
private int fuzzyCount = 0;
private int fuzzyCount;
private InternalDataSet dataset;
private final ArrayDeque<DataSet> deque = new ArrayDeque<>();

/**
* @param name data set name (assumes 2-dim DataSet
*/
public AveragingDataSet(final String name) {
this(name, 2, 0);
}

/**
* @param name data set name
* @param nDims number of dimensions
Expand Down Expand Up @@ -150,12 +159,12 @@ public InternalDataSet(DataSet ds) {
ds.getDataCount(), true);
}

public boolean isCompatible(DataSet d) {
return Math.abs(super.getDataCount() - d.getDataCount()) <= fuzzyCount;
public boolean isIncompatible(DataSet d) {
return Math.abs(super.getDataCount() - d.getDataCount()) > fuzzyCount;
}

public void opAdd(DataSet d) {
if (!isCompatible(d)) {
if (isIncompatible(d)) {
throw new IllegalArgumentException("Datasets do not match");
}

Expand All @@ -172,7 +181,7 @@ public void opScale(double f) {
}

public void opSub(DataSet d) {
if (!isCompatible(d)) {
if (isIncompatible(d)) {
throw new IllegalArgumentException("Datasets do not match");
}
yValues.size(d.getDataCount());
Expand All @@ -189,26 +198,36 @@ public double getValue(int dimIndex, double... x) {

@Override
public DataSet set(final DataSet other, final boolean copy) {
if (other instanceof AveragingDataSet) {
this.fuzzyCount = ((AveragingDataSet) other).getFuzzyCount();
this.averageSize = ((AveragingDataSet) other).getAverageSize();
lock().writeLockGuard(() -> other.lock().writeLockGuard(() -> {
if (other instanceof AveragingDataSet) {
this.fuzzyCount = ((AveragingDataSet) other).getFuzzyCount();
this.averageSize = ((AveragingDataSet) other).getAverageSize();
if (copy) {
this.clear();
((AveragingDataSet) other).deque.forEach(ds -> this.add(new DefaultDataSet(ds)));
} else {
this.dataset = ((AveragingDataSet) other).dataset;
this.deque.clear();
this.deque.addAll(((AveragingDataSet) other).deque);
}
getAxisDescriptions().forEach(AxisDescription::clear);
for (int dim = 0; dim < getDimension(); dim++) {
recomputeLimits(dim);
}
return;
}
// non AveragingDataSet: add the other data set as a single data set
this.clear();
if (copy) {
this.clear();
((AveragingDataSet) other).deque.forEach(ds -> this.add(new DefaultDataSet(ds)));
this.add(new DefaultDataSet(other));
} else {
this.dataset = ((AveragingDataSet) other).dataset;
this.deque.clear();
this.deque.addAll(((AveragingDataSet) other).deque);
this.add(other);
}
return this;
}
// non AveragingDataSet: add the other data set as a single data set
this.clear();
if (copy) {
this.add(new DefaultDataSet(other));
} else {
this.add(other);
}
return this;
getAxisDescriptions().forEach(AxisDescription::clear);
for (int dim = 0; dim < getDimension(); dim++) {
recomputeLimits(dim);
}
}));
return fireInvalidated(new UpdatedDataEvent(this, "set(DataSet, boolean=" + copy + ")"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import de.gsi.dataset.DataSetError;
import de.gsi.dataset.event.AddedDataEvent;
import de.gsi.dataset.event.RemovedDataEvent;
import de.gsi.dataset.event.UpdatedDataEvent;
import de.gsi.dataset.utils.AssertUtils;
import de.gsi.dataset.utils.CircularBuffer;
import de.gsi.dataset.utils.DoubleCircularBuffer;
Expand All @@ -26,18 +27,18 @@ public class CircularDoubleErrorDataSet extends AbstractErrorDataSet<CircularDou
* Creates a new instance of <code>CircularDoubleErrorDataSet</code>.
*
* @param name name of this DataSet.
* @param initalSize maximum circular buffer capacity
* @param initialSize maximum circular buffer capacity
* @throws IllegalArgumentException if <code>name</code> is <code>null</code>
*/
public CircularDoubleErrorDataSet(final String name, final int initalSize) {
public CircularDoubleErrorDataSet(final String name, final int initialSize) {
super(name, 2, ErrorType.NO_ERROR, ErrorType.ASYMMETRIC);
AssertUtils.gtEqThanZero("initalSize", initalSize);
xValues = new DoubleCircularBuffer(initalSize);
yValues = new DoubleCircularBuffer(initalSize);
yErrorsPos = new DoubleCircularBuffer(initalSize);
yErrorsNeg = new DoubleCircularBuffer(initalSize);
dataLabels = new CircularBuffer<>(initalSize);
dataStyles = new CircularBuffer<>(initalSize);
AssertUtils.gtEqThanZero("initialSize", initialSize);
xValues = new DoubleCircularBuffer(initialSize);
yValues = new DoubleCircularBuffer(initialSize);
yErrorsPos = new DoubleCircularBuffer(initialSize);
yErrorsNeg = new DoubleCircularBuffer(initialSize);
dataLabels = new CircularBuffer<>(initialSize);
dataStyles = new CircularBuffer<>(initialSize);
}

/**
Expand Down Expand Up @@ -87,9 +88,10 @@ public CircularDoubleErrorDataSet add(final double x, final double y, final doub
dataLabels.put(label);
dataStyles.put(style);

// assumes in X sorted data range
getAxisDescription(DIM_X).setMin(xValues.get(0));
getAxisDescription(DIM_X).setMax(xValues.get(xValues.available() - 1));
getAxisDescription(DIM_Y).add(y);
getAxisDescription(DIM_Y).clear();
});

return fireInvalidated(new AddedDataEvent(this));
Expand All @@ -112,24 +114,45 @@ public CircularDoubleErrorDataSet add(final double[] xVals, final double[] yVals
AssertUtils.notNull("Y coordinates", yVals);
AssertUtils.notNull("Y error neg", yErrNeg);
AssertUtils.notNull("Y error pos", yErrPos);
AssertUtils.equalDoubleArrays(xVals, yVals);
AssertUtils.equalDoubleArrays(xVals, yErrNeg);
AssertUtils.equalDoubleArrays(xVals, yErrPos);
final int dataCount = Math.min(Math.min(xVals.length, yVals.length), Math.min(yErrNeg.length, yErrPos.length));
return add(xVals, yVals, yErrNeg, yErrPos, dataCount);
}

lock().writeLockGuard(() -> {
this.xValues.put(xVals, xVals.length);
this.yValues.put(yVals, yVals.length);
this.yErrorsNeg.put(yErrNeg, yErrNeg.length);
this.yErrorsPos.put(yErrPos, yErrPos.length);
dataLabels.put(new String[yErrPos.length], yErrPos.length);
dataStyles.put(new String[yErrPos.length], yErrPos.length);
/**
* <p>
* Initialises the data set with specified data.
* </p>
* Note: The method copies values from specified double arrays.
*
* @param xVals the new x coordinates
* @param yVals the new y coordinates
* @param yErrNeg the +dy errors
* @param yErrPos the -dy errors
* @param dataCount maximum number of data points to copy (e.g. in case array store more than needs to be copied)
* @return itself
*/
public CircularDoubleErrorDataSet add(final double[] xVals, final double[] yVals, final double[] yErrNeg, final double[] yErrPos, final int dataCount) {
AssertUtils.notNull("X coordinates", xVals);
AssertUtils.notNull("Y coordinates", yVals);
AssertUtils.notNull("Y error neg", yErrNeg);
AssertUtils.notNull("Y error pos", yErrPos);
AssertUtils.gtOrEqual("X coordinates", dataCount, xVals.length);
AssertUtils.gtOrEqual("Y coordinates", dataCount, yVals.length);
AssertUtils.gtOrEqual("Y error neg", dataCount, yErrNeg.length);
AssertUtils.gtOrEqual("Y error pos", dataCount, yErrPos.length);

lock().writeLockGuard(() -> {
this.xValues.put(xVals, dataCount);
this.yValues.put(yVals, dataCount);
this.yErrorsNeg.put(yErrNeg, dataCount);
this.yErrorsPos.put(yErrPos, dataCount);
dataLabels.put(new String[yVals.length], dataCount);
dataStyles.put(new String[yVals.length], dataCount);

// assumes in X sorted data range
getAxisDescription(DIM_X).setMin(xValues.get(0));
getAxisDescription(DIM_X).setMax(xValues.get(xValues.available() - 1));
for (int i = 0; i < yVals.length; i++) {
getAxisDescription(DIM_Y).add(yVals[i] + yErrPos[i]);
getAxisDescription(DIM_Y).add(yVals[i] - yErrNeg[i]);
}
getAxisDescription(DIM_Y).clear();
});

return fireInvalidated(new AddedDataEvent(this));
Expand Down Expand Up @@ -206,6 +229,23 @@ public CircularDoubleErrorDataSet reset() {

@Override
public DataSet set(final DataSet other, final boolean copy) {
throw new UnsupportedOperationException("copy setting transposed data set is not implemented");
lock().writeLockGuard(() -> other.lock().writeLockGuard(() -> {
this.reset();
if (other.getDataCount() == 0) {
return;
}
// copy data
final int count = other.getDataCount();
if (other instanceof DataSetError) {
this.add(other.getValues(DIM_X), other.getValues(DIM_Y), ((DataSetError) other).getErrorsNegative(DIM_Y), ((DataSetError) other).getErrorsPositive(DIM_Y), other.getDataCount());
} else {
this.add(other.getValues(DIM_X), other.getValues(DIM_Y), new double[count], new double[count], other.getDataCount());
}

copyMetaData(other);
copyDataLabelsAndStyles(other, copy);
copyAxisDescription(other);
}));
return fireInvalidated(new UpdatedDataEvent(this, "set(DataSet, boolean=" + copy + ")"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
import de.gsi.dataset.DataSetError;
import de.gsi.dataset.event.AddedDataEvent;
import de.gsi.dataset.event.RemovedDataEvent;
import de.gsi.dataset.event.UpdatedDataEvent;
import de.gsi.dataset.spi.utils.DoublePointError;
import de.gsi.dataset.utils.AssertUtils;
import de.gsi.dataset.utils.LimitedQueue;

/**
Expand All @@ -21,37 +23,37 @@ public class FifoDoubleErrorDataSet extends AbstractErrorDataSet<DoubleErrorData
private static final int SAFE_BET = 1;
private static final long serialVersionUID = -7153702141838930486L;
protected final transient LimitedQueue<DataBlob> data;
protected double maxDistance = Double.MAX_VALUE;
protected double maxDistance;

/**
* Creates a new instance of <code>FifoDoubleErrorDataSet</code>.
*
* @param name name of this DataSet.
* @param initalSize maximum circular buffer capacity
* @param initialSize maximum circular buffer capacity
* @throws IllegalArgumentException if <code>name</code> is <code>null</code>
*/
public FifoDoubleErrorDataSet(final String name, final int initalSize) {
this(name, initalSize, Double.MAX_VALUE);
public FifoDoubleErrorDataSet(final String name, final int initialSize) {
this(name, initialSize, Double.MAX_VALUE);
}

/**
* Creates a new instance of <code>FifoDoubleErrorDataSet</code>.
*
* @param name name of this DataSet.
* @param initalSize maximum circular buffer capacity
* @param initialSize maximum circular buffer capacity
* @param maxDistance maximum range before data points are being dropped
* @throws IllegalArgumentException if <code>name</code> is <code>null</code>
*/
public FifoDoubleErrorDataSet(final String name, final int initalSize, final double maxDistance) {
public FifoDoubleErrorDataSet(final String name, final int initialSize, final double maxDistance) {
super(name, 2, ErrorType.NO_ERROR, ErrorType.SYMMETRIC);
if (initalSize <= 0) {
throw new IllegalArgumentException("negative or zero initalSize = " + initalSize);
if (initialSize <= 0) {
throw new IllegalArgumentException("negative or zero initialSize = " + initialSize);
}
if (maxDistance <= 0) {
throw new IllegalArgumentException("negative or zero maxDistance = " + maxDistance);
}
this.maxDistance = maxDistance;
data = new LimitedQueue<>(initalSize);
data = new LimitedQueue<>(initialSize);
}

/**
Expand Down Expand Up @@ -109,6 +111,27 @@ public FifoDoubleErrorDataSet add(final double x, final double y, final double y
return this;
}

/**
* <p>
* Initialises the data set with specified data.
* </p>
* Note: The method copies values from specified double arrays.
*
* @param xVals the new x coordinates
* @param yVals the new y coordinates
* @param yErrNeg the +dy errors
* @param yErrPos the -dy errors
* @return itself
*/
public FifoDoubleErrorDataSet add(final double[] xVals, final double[] yVals, final double[] yErrNeg, final double[] yErrPos) {
AssertUtils.notNull("X coordinates", xVals);
AssertUtils.notNull("Y coordinates", yVals);
AssertUtils.notNull("Y error neg", yErrNeg);
AssertUtils.notNull("Y error pos", yErrPos);
final int dataCount = Math.min(Math.min(xVals.length, yVals.length), Math.min(yErrNeg.length, yErrPos.length));
return add(xVals, yVals, yErrNeg, yErrPos, dataCount);
}

/**
* <p>
* Initialises the data set with specified data.
Expand All @@ -119,12 +142,12 @@ public FifoDoubleErrorDataSet add(final double x, final double y, final double y
* @param yValues the new y coordinates
* @param yErrorsNeg the -dy errors
* @param yErrorsPos the +dy errors
* @param dataCount maximum number of data points to copy (e.g. in case array store more than needs to be copied)
* @return itself
*/
public FifoDoubleErrorDataSet add(final double[] xValues, final double[] yValues, final double[] yErrorsNeg,
final double[] yErrorsPos) {
public FifoDoubleErrorDataSet add(final double[] xValues, final double[] yValues, final double[] yErrorsNeg, final double[] yErrorsPos, final int dataCount) {
lock().writeLockGuard(() -> {
for (int i = 0; i < xValues.length; i++) {
for (int i = 0; i < dataCount; i++) {
this.add(xValues[i], yValues[i], yErrorsNeg[i], yErrorsPos[i]);
}
});
Expand Down Expand Up @@ -226,9 +249,9 @@ protected static class DataBlob extends DoublePointError {
protected String style;
protected String tag;

protected DataBlob(final double x, final double y, final double errorYNeg, final double errorYPos, final String tag,
final String style) {
super(x, y, errorYNeg, errorYPos);
protected DataBlob(final double x, final double y, final double errorYNeg, final double errorYPos, final String tag, final String style) {
//noinspection SuspiciousNameCombination
super(x, y, errorYNeg, errorYPos); // NOPMD NOSONAR - super's x/y error is reinterpreted as +ey -ey in this class
this.tag = tag;
this.style = style;
}
Expand All @@ -244,6 +267,20 @@ public String getStyle() {

@Override
public DataSet set(final DataSet other, final boolean copy) {
throw new UnsupportedOperationException("copy setting transposed data set is not implemented");
lock().writeLockGuard(() -> other.lock().writeLockGuard(() -> {
this.reset();
// copy data
final int count = other.getDataCount();
if (other instanceof DataSetError) {
this.add(other.getValues(DIM_X), other.getValues(DIM_Y), ((DataSetError) other).getErrorsNegative(DIM_Y), ((DataSetError) other).getErrorsPositive(DIM_Y), other.getDataCount());
} else {
this.add(other.getValues(DIM_X), other.getValues(DIM_Y), new double[count], new double[count], other.getDataCount());
}

copyMetaData(other);
copyDataLabelsAndStyles(other, copy);
copyAxisDescription(other);
}));
return fireInvalidated(new UpdatedDataEvent(this, "set(DataSet, boolean=" + copy + ")"));
}
}
Loading

0 comments on commit cd202c7

Please sign in to comment.