View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.math4.legacy.analysis.interpolation;
18  
19  import org.apache.commons.math4.legacy.analysis.MultivariateFunction;
20  import org.apache.commons.math4.core.jdkmath.JdkMath;
21  import org.junit.Assert;
22  import org.junit.Test;
23  
24  /**
25   * Test case for the {@link MicrosphereProjectionInterpolator
26   * "microsphere projection"} interpolator.
27   */
28  public final class MicrosphereProjectionInterpolatorTest {
29      /**
30       * Test of interpolator for a plane.
31       * <p>
32       * y = 2 x<sub>1</sub> - 3 x<sub>2</sub> + 5
33       */
34      @Test
35      public void testLinearFunction2D() {
36          MultivariateFunction f = new MultivariateFunction() {
37              @Override
38              public double value(double[] x) {
39                  if (x.length != 2) {
40                      throw new IllegalArgumentException();
41                  }
42                  return 2 * x[0] - 3 * x[1] + 5;
43              }
44          };
45  
46          final double darkFraction = 0.5;
47          final double darkThreshold = 1e-2;
48          final double background = Double.NaN;
49          final double exponent = 1.1;
50          final boolean shareSphere = true;
51          final double noInterpolationTolerance = Math.ulp(1d);
52  
53          // N-dimensional interpolator.
54          final MultivariateInterpolator interpolator
55              = new MicrosphereProjectionInterpolator(2, 500,
56                                                      darkFraction,
57                                                      darkThreshold,
58                                                      background,
59                                                      exponent,
60                                                      shareSphere,
61                                                      noInterpolationTolerance);
62  
63          // 2D interpolator.
64          final MultivariateInterpolator interpolator2D
65              = new MicrosphereProjectionInterpolator(new InterpolatingMicrosphere2D(16,
66                                                                                     darkFraction,
67                                                                                     darkThreshold,
68                                                                                     background),
69                                                      exponent,
70                                                      shareSphere,
71                                                      noInterpolationTolerance);
72  
73          final double min = -1;
74          final double max = 1;
75          final double range = max - min;
76          final int res = 5;
77          final int n = res * res; // Number of sample points.
78          final int dim = 2;
79          double[][] x = new double[n][dim];
80          double[] y = new double[n];
81          int index = 0;
82          for (int i = 0; i < res; i++) {
83              final double x1Val = toCoordinate(min, range, res, i);
84              for (int j = 0; j < res; j++) {
85                  final double x2Val = toCoordinate(min, range, res, j);
86                  x[index][0] = x1Val;
87                  x[index][1] = x2Val;
88                  y[index] = f.value(x[index]);
89                  ++index;
90              }
91          }
92  
93          final MultivariateFunction p = interpolator.interpolate(x, y);
94          final MultivariateFunction p2D = interpolator2D.interpolate(x, y);
95  
96          double[] c = new double[dim];
97          double expected;
98          double result;
99          double result2D;
100 
101         final int sampleIndex = 2;
102         c[0] = x[sampleIndex][0];
103         c[1] = x[sampleIndex][1];
104         expected = f.value(c);
105         result = p.value(c);
106         result2D = p2D.value(c);
107         Assert.assertEquals("on sample point (exact)", expected, result2D, JdkMath.ulp(1d));
108         Assert.assertEquals("on sample point (ND vs 2D)", result2D, result, JdkMath.ulp(1d));
109 
110         // Interpolation.
111         c[0] = 0.654321;
112         c[1] = -0.345678;
113         expected = f.value(c);
114         result = p.value(c);
115         result2D = p2D.value(c);
116         Assert.assertEquals("interpolation (exact)", expected, result2D, 1e-1);
117         Assert.assertEquals("interpolation (ND vs 2D)", result2D, result, 1e-1);
118 
119         // Extrapolation.
120         c[0] = 0 - 1e-2;
121         c[1] = 1 + 1e-2;
122         expected = f.value(c);
123         result = p.value(c);
124         result2D = p2D.value(c);
125         Assert.assertFalse(Double.isNaN(result));
126         Assert.assertFalse(Double.isNaN(result2D));
127         Assert.assertEquals("extrapolation (exact)", expected, result2D, 1e-1);
128         Assert.assertEquals("extrapolation (ND vs 2D)", result2D, result, 1e-2);
129 
130         // Far away.
131         c[0] = 20;
132         c[1] = -30;
133         result = p.value(c);
134         Assert.assertTrue(result + " should be NaN", Double.isNaN(result));
135         result2D = p2D.value(c);
136         Assert.assertTrue(result2D + " should be NaN", Double.isNaN(result2D));
137     }
138 
139     /**
140      * @param min Minimum of the coordinate range.
141      * @param range Extent of the coordinate interval.
142      * @param res Number of pixels.
143      * @param pixel Pixel index.
144      */
145     private static double toCoordinate(double min,
146                                        double range,
147                                        int res,
148                                        int pixel) {
149         return pixel * range / (res - 1) + min;
150     }
151 }