1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.hipparchus.analysis.interpolation;
23
24 import java.lang.reflect.InvocationTargetException;
25 import java.lang.reflect.Method;
26
27 import org.hipparchus.analysis.MultivariateFunction;
28 import org.hipparchus.exception.LocalizedCoreFormats;
29 import org.hipparchus.exception.MathIllegalArgumentException;
30 import org.hipparchus.exception.MathIllegalStateException;
31 import org.hipparchus.random.RandomGenerator;
32 import org.hipparchus.random.UnitSphereRandomVectorGenerator;
33 import org.hipparchus.random.Well1024a;
34 import org.hipparchus.random.Well19937a;
35 import org.hipparchus.util.FastMath;
36 import org.junit.Assert;
37 import org.junit.Test;
38
39
40
41
42
43 public final class MicrosphereProjectionInterpolatorTest {
44
45
46
47
48
49 @Test
50 public void testLinearFunction2D() {
51 MultivariateFunction f = new MultivariateFunction() {
52 @Override
53 public double value(double[] x) {
54 if (x.length != 2) {
55 throw new IllegalArgumentException();
56 }
57 return 2 * x[0] - 3 * x[1] + 5;
58 }
59 };
60
61 final double darkFraction = 0.5;
62 final double darkThreshold = 1e-2;
63 final double background = Double.NaN;
64 final double exponent = 1.1;
65 final boolean shareSphere = true;
66 final double noInterpolationTolerance = Math.ulp(1d);
67 final RandomGenerator random = new Well1024a(0x1c7a150c83a6d9dal);
68
69
70 final MultivariateInterpolator interpolator
71 = new MicrosphereProjectionInterpolator(new InterpolatingMicrosphere(2, 500,
72 darkFraction,
73 darkThreshold,
74 background,
75 new UnitSphereRandomVectorGenerator(2, random)),
76 exponent,
77 shareSphere,
78 noInterpolationTolerance);
79
80
81 final MultivariateInterpolator interpolator2D
82 = new MicrosphereProjectionInterpolator(new InterpolatingMicrosphere2D(16,
83 darkFraction,
84 darkThreshold,
85 background),
86 exponent,
87 shareSphere,
88 noInterpolationTolerance);
89
90 final double min = -1;
91 final double max = 1;
92 final double range = max - min;
93 final int res = 5;
94 final int n = res * res;
95 final int dim = 2;
96 double[][] x = new double[n][dim];
97 double[] y = new double[n];
98 int index = 0;
99 for (int i = 0; i < res; i++) {
100 final double x1Val = toCoordinate(min, range, res, i);
101 for (int j = 0; j < res; j++) {
102 final double x2Val = toCoordinate(min, range, res, j);
103 x[index][0] = x1Val;
104 x[index][1] = x2Val;
105 y[index] = f.value(x[index]);
106 ++index;
107 }
108 }
109
110 final MultivariateFunction p = interpolator.interpolate(x, y);
111 final MultivariateFunction p2D = interpolator2D.interpolate(x, y);
112
113 double[] c = new double[dim];
114 double expected, result, result2D;
115
116 final int sampleIndex = 2;
117 c[0] = x[sampleIndex][0];
118 c[1] = x[sampleIndex][1];
119 expected = f.value(c);
120 result = p.value(c);
121 result2D = p2D.value(c);
122 Assert.assertEquals("on sample point (exact)", expected, result2D, FastMath.ulp(1d));
123 Assert.assertEquals("on sample point (ND vs 2D)", result2D, result, FastMath.ulp(1d));
124
125
126 c[0] = 0.654321;
127 c[1] = -0.345678;
128 expected = f.value(c);
129 result = p.value(c);
130 result2D = p2D.value(c);
131 Assert.assertEquals("interpolation (exact)", expected, result2D, 1e-1);
132 Assert.assertEquals("interpolation (ND vs 2D)", result2D, result, 1e-1);
133
134
135 c[0] = 0 - 1e-2;
136 c[1] = 1 + 1e-2;
137 expected = f.value(c);
138 result = p.value(c);
139 result2D = p2D.value(c);
140 Assert.assertFalse(Double.isNaN(result));
141 Assert.assertFalse(Double.isNaN(result2D));
142 Assert.assertEquals("extrapolation (exact)", expected, result2D, 1e-1);
143 Assert.assertEquals("extrapolation (ND vs 2D)", result2D, result, 1e-2);
144
145
146 c[0] = 20;
147 c[1] = -30;
148 result = p.value(c);
149 Assert.assertTrue(result + " should be NaN", Double.isNaN(result));
150 result2D = p2D.value(c);
151 Assert.assertTrue(result2D + " should be NaN", Double.isNaN(result2D));
152 }
153
154 @Test
155 public void testWrongDimensions() {
156 checkWrongArguments(0, 1, 0.5, 0.0, 0.0,
157 LocalizedCoreFormats.NUMBER_TOO_SMALL_BOUND_EXCLUDED);
158 checkWrongArguments(1, 0, 0.5, 0.0, 0.0,
159 LocalizedCoreFormats.NUMBER_TOO_SMALL_BOUND_EXCLUDED);
160 checkWrongArguments(1, 1, 0.5, -1.0, 0.0,
161 LocalizedCoreFormats.NUMBER_TOO_SMALL);
162 }
163
164 private void checkWrongArguments(int dimension,
165 int size,
166 double maxDarkFraction,
167 double darkThreshold,
168 double background,
169 LocalizedCoreFormats expected) {
170 try {
171 new InterpolatingMicrosphere(dimension, size, maxDarkFraction, darkThreshold, background, null);
172 Assert.fail("an exception should have been thrown");
173 } catch (MathIllegalArgumentException miae) {
174 Assert.assertEquals(expected, miae.getSpecifier());
175 }
176 }
177
178 @Test
179 public void testCopy() {
180 UnitSphereRandomVectorGenerator random =
181 new UnitSphereRandomVectorGenerator(3, new Well19937a(0x265318ael));
182 InterpolatingMicrosphere original = new InterpolatingMicrosphere(3, 30, 0.5, 0.2, 0.0, random);
183 InterpolatingMicrosphere copy = original.copy();
184 Assert.assertFalse(original == copy);
185 Assert.assertEquals(original.getDimension(), copy.getDimension());
186 Assert.assertEquals(original.getSize(), copy.getSize());
187 }
188
189 @Test
190 public void testSizeLimit() {
191 UnitSphereRandomVectorGenerator random =
192 new UnitSphereRandomVectorGenerator(3, new Well19937a(0x453l));
193 InterpolatingMicrosphere ims = new InterpolatingMicrosphere(3, 30, 0.5, 0.2, 0.0, random);
194 try {
195 Method add = InterpolatingMicrosphere.class.getDeclaredMethod("add", double[].class, Boolean.TYPE);
196 add.setAccessible(true);
197 try {
198 add.invoke(ims, random.nextVector(), true);
199 Assert.fail("an exception should have been thrown");
200 } catch (InvocationTargetException ite) {
201 MathIllegalStateException miae = (MathIllegalStateException) ite.getCause();
202 Assert.assertEquals(LocalizedCoreFormats.MAX_COUNT_EXCEEDED, miae.getSpecifier());
203 }
204 } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException e) {
205 Assert.fail(e.getLocalizedMessage());
206 }
207 }
208
209 @Test
210 public void testInconsistentDimensions() {
211 final int d1 = 5;
212 final int d2 = 3;
213 try {
214 UnitSphereRandomVectorGenerator random =
215 new UnitSphereRandomVectorGenerator(d1, new Well19937a(0x1l));
216 new InterpolatingMicrosphere(d2, 30, 0.5, 0.2, 0.0, random);
217 Assert.fail("an exception should have been thrown");
218 } catch (MathIllegalArgumentException miae) {
219 Assert.assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, miae.getSpecifier());
220 Assert.assertEquals(d1, ((Integer) miae.getParts()[0]).intValue());
221 Assert.assertEquals(d2, ((Integer) miae.getParts()[1]).intValue());
222 }
223 }
224
225
226
227
228
229
230
231 private static double toCoordinate(double min,
232 double range,
233 int res,
234 int pixel) {
235 return pixel * range / (res - 1) + min;
236 }
237 }