From 8caf8fa7fd38103699c0ce42b6a667e6af169c36 Mon Sep 17 00:00:00 2001 From: Peter Powers <pmpowers@usgs.gov> Date: Wed, 22 Sep 2021 17:24:43 -0600 Subject: [PATCH] additional sequences class tests --- .../usgs/earthquake/nshmp/data/Sequences.java | 36 +++----- .../earthquake/nshmp/data/SequencesTests.java | 84 +++++++++++++++++++ 2 files changed, 95 insertions(+), 25 deletions(-) diff --git a/src/main/java/gov/usgs/earthquake/nshmp/data/Sequences.java b/src/main/java/gov/usgs/earthquake/nshmp/data/Sequences.java index 023cd033..a5acd173 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/data/Sequences.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/data/Sequences.java @@ -20,6 +20,10 @@ public class Sequences { private Sequences() {} + /** + * Check that the supplied arrays are not empty, are the same size, and that + * the supplied xs increase monotonically. + */ static void validateArrays(double[] xs, double[] ys) { checkArgument(xs.length > 0, "x-values may not be empty"); checkArgument(xs.length == ys.length, "x- and y-values are different sizes"); @@ -30,9 +34,10 @@ public class Sequences { /** * Trim points from the start or end of a sequence for which y-values are - * zero. If no such leading or trailing points exist, sequence conatins only a + * zero. If no such leading or trailing points exist, sequence contains only a * single point, or all y-values are zero, method returns the supplied - * sequence. + * sequence. If supplied sequence is mutable, returned sequence is mutable; + * otherwise returned sequence is immutable. */ static XySequence trim(ArrayXySequence xy) { if (xy.size() == 1 || xy.isClear()) { @@ -93,7 +98,7 @@ public class Sequences { return ((int) Maths.round(((max - min) / delta), 6)) + 1; } - /* + /** * Ensure validity of sequence discretization parameters. Confirms that for a * specified range [min..max] and Δ that (1) min, max, and Δ are finite, (2) * max > min, and (3) Δ > 0. Returns the supplied Δ for use inline. @@ -107,8 +112,9 @@ public class Sequences { return Δ; } - // TODO docs; consider moving to cumulate method in data/sequence package; - // not necessarily MFD specific + /** + * Create a new XySequence with reverse cumulative values. + */ public static XySequence toCumulative(XySequence incremental) { MutableXySequence cumulative = MutableXySequence.copyOf(incremental); double sum = 0.0; @@ -216,32 +222,12 @@ public class Sequences { : sequence; } - /* - * TODO clean - * - * Method rounds (max-min)/Δ to 1e-6 before casting to an integer to - * determine the number of elements in the sequence. If (max-min)/Δ is - * reasonably close to an integer but max is off by some double-precision - * error (e.g. 6.7999999999), then max of 6.8 will be the upper end of the - * sequence. - */ - // private static double[] buildSequence(double min, double max, double Δ) { - // checkSequenceParameters(min, max, Δ); - // int size = ((int) Maths.round(((max - min) / Δ), 6)) + 1; - // checkArgument(Range.openClosed(0, 100000).contains(size), "sequence - // size"); - // return IntStream.range(0, size) - // .mapToDouble(i -> min + Δ * i) - // .toArray(); - // } - private static double[] buildSequence(double min, double Δ, int size) { checkArgument(Range.openClosed(0, 100000).contains(size), "sequence size"); return IntStream.range(0, size) .mapToDouble(i -> min + Δ * i) .toArray(); } - } } diff --git a/src/test/java/gov/usgs/earthquake/nshmp/data/SequencesTests.java b/src/test/java/gov/usgs/earthquake/nshmp/data/SequencesTests.java index 185e9137..42c67e57 100644 --- a/src/test/java/gov/usgs/earthquake/nshmp/data/SequencesTests.java +++ b/src/test/java/gov/usgs/earthquake/nshmp/data/SequencesTests.java @@ -1,10 +1,13 @@ package gov.usgs.earthquake.nshmp.data; import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.Arrays; +import java.util.Optional; import org.junit.jupiter.api.Test; @@ -12,6 +15,76 @@ import com.google.common.primitives.Doubles; class SequencesTests { + @Test + final void validateArraysTests() { + // empty xs array + assertThrows(IllegalArgumentException.class, () -> { + Sequences.validateArrays(new double[0], new double[0]); + }); + // xs and ys different sizes + assertThrows(IllegalArgumentException.class, () -> { + Sequences.validateArrays(new double[2], new double[3]); + }); + // xs not monotonic + assertThrows(IllegalArgumentException.class, () -> { + Sequences.validateArrays(new double[] { 1, 0 }, new double[2]); + }); + // xs not monotonic + assertDoesNotThrow(() -> { + Sequences.validateArrays(new double[] { 0, 1 }, new double[2]); + }); + // single values makes it through monotonic test + assertDoesNotThrow(() -> { + Sequences.validateArrays(new double[1], new double[1]); + }); + } + + @Test + final void trimTests() { + double[] xs1 = new double[1]; + double[] ys1 = new double[1]; + + double[] xs3 = new double[] { 1, 2, 3 }; + double[] ys3zero = new double[3]; + double[] ys3ones = new double[] { 1, 1, 1 }; + + // size and clear check + ArrayXySequence xy1 = (ArrayXySequence) XySequence.create(xs1, ys1); + assertSame(xy1, Sequences.trim(xy1)); + ArrayXySequence xy3a = (ArrayXySequence) XySequence.create(xs3, ys3zero); + assertSame(xy3a, Sequences.trim(xy3a)); + + // start and end y values > 0 + ArrayXySequence xy3b = (ArrayXySequence) XySequence.create(xs3, ys3ones); + assertSame(xy3b, Sequences.trim(xy3b)); + + double[] xs4toTrim = new double[] { 1, 2, 3, 4 }; + double[] ys4toTrim = new double[] { 1, 1, 1, 0 }; + double[] xs4expect = new double[] { 1, 2, 3 }; + double[] ys4expect = new double[] { 1, 1, 1 }; + + // extra test that gets upper end y = 0 + ArrayXySequence xy4toTrim = (ArrayXySequence) XySequence.create(xs4toTrim, ys4toTrim); + ArrayXySequence xy4expect = (ArrayXySequence) XySequence.create(xs4expect, ys4expect); + assertEquals(xy4expect, Sequences.trim(xy4toTrim)); + + double[] xs5toTrim = new double[] { 1, 2, 3, 4, 5 }; + double[] ys5toTrim = new double[] { 0, 1, 1, 1, 0 }; + double[] xs5expect = new double[] { 2, 3, 4 }; + double[] ys5expect = new double[] { 1, 1, 1 }; + + // immutable trimmed + ArrayXySequence xy5toTrim = (ArrayXySequence) XySequence.create(xs5toTrim, ys5toTrim); + ArrayXySequence xy5expect = (ArrayXySequence) XySequence.create(xs5expect, ys5expect); + assertEquals(xy5expect, Sequences.trim(xy5toTrim)); + + // mutable trimmed + MutableArrayXySequence xy5toTrimMutable = (MutableArrayXySequence) MutableXySequence.create( + xs5toTrim, + Optional.of(ys5toTrim)); + assertEquals(xy5expect, Sequences.trim(xy5toTrimMutable)); + } + @Test final void nonZeroIndexTests() { double[] values = new double[] { 0.0, 0.0, 1.0, 1.0, 0.0, 0.0 }; @@ -25,6 +98,17 @@ class SequencesTests { assertEquals(-1, Sequences.lastNonZeroIndex(zeros), 0.0); } + @Test + final void toCumulativeTests() { + double[] xs = new double[] { 1, 2, 3, 4, 5 }; + double[] ys = new double[] { 1, 1, 1, 1, 1 }; + double[] ysExpect = new double[] { 5, 4, 3, 2, 1 }; + + XySequence xyActual = Sequences.toCumulative(XySequence.create(xs, ys)); + XySequence xyExpect = XySequence.create(xs, ysExpect); + assertEquals(xyExpect, xyActual); + } + @Test final void arrayBuilderTests() { -- GitLab