SmoothingPolynomialBicubicSplineInterpolator.java

  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.math3.analysis.interpolation;

  18. import org.apache.commons.math3.exception.DimensionMismatchException;
  19. import org.apache.commons.math3.exception.NoDataException;
  20. import org.apache.commons.math3.exception.NonMonotonicSequenceException;
  21. import org.apache.commons.math3.exception.NotPositiveException;
  22. import org.apache.commons.math3.exception.NullArgumentException;
  23. import org.apache.commons.math3.util.MathArrays;
  24. import org.apache.commons.math3.util.Precision;
  25. import org.apache.commons.math3.optim.nonlinear.vector.jacobian.GaussNewtonOptimizer;
  26. import org.apache.commons.math3.fitting.PolynomialFitter;
  27. import org.apache.commons.math3.analysis.polynomials.PolynomialFunction;
  28. import org.apache.commons.math3.optim.SimpleVectorValueChecker;

  29. /**
  30.  * Generates a bicubic interpolation function.
  31.  * Prior to generating the interpolating function, the input is smoothed using
  32.  * polynomial fitting.
  33.  *
  34.  * @since 2.2
  35.  * @deprecated To be removed in 4.0 (see MATH-1166).
  36.  */
  37. @Deprecated
  38. public class SmoothingPolynomialBicubicSplineInterpolator
  39.     extends BicubicSplineInterpolator {
  40.     /** Fitter for x. */
  41.     private final PolynomialFitter xFitter;
  42.     /** Degree of the fitting polynomial. */
  43.     private final int xDegree;
  44.     /** Fitter for y. */
  45.     private final PolynomialFitter yFitter;
  46.     /** Degree of the fitting polynomial. */
  47.     private final int yDegree;

  48.     /**
  49.      * Default constructor. The degree of the fitting polynomials is set to 3.
  50.      */
  51.     public SmoothingPolynomialBicubicSplineInterpolator() {
  52.         this(3);
  53.     }

  54.     /**
  55.      * @param degree Degree of the polynomial fitting functions.
  56.      * @exception NotPositiveException if degree is not positive
  57.      */
  58.     public SmoothingPolynomialBicubicSplineInterpolator(int degree)
  59.         throws NotPositiveException {
  60.         this(degree, degree);
  61.     }

  62.     /**
  63.      * @param xDegree Degree of the polynomial fitting functions along the
  64.      * x-dimension.
  65.      * @param yDegree Degree of the polynomial fitting functions along the
  66.      * y-dimension.
  67.      * @exception NotPositiveException if degrees are not positive
  68.      */
  69.     public SmoothingPolynomialBicubicSplineInterpolator(int xDegree, int yDegree)
  70.         throws NotPositiveException {
  71.         if (xDegree < 0) {
  72.             throw new NotPositiveException(xDegree);
  73.         }
  74.         if (yDegree < 0) {
  75.             throw new NotPositiveException(yDegree);
  76.         }
  77.         this.xDegree = xDegree;
  78.         this.yDegree = yDegree;

  79.         final double safeFactor = 1e2;
  80.         final SimpleVectorValueChecker checker
  81.             = new SimpleVectorValueChecker(safeFactor * Precision.EPSILON,
  82.                                            safeFactor * Precision.SAFE_MIN);
  83.         xFitter = new PolynomialFitter(new GaussNewtonOptimizer(false, checker));
  84.         yFitter = new PolynomialFitter(new GaussNewtonOptimizer(false, checker));
  85.     }

  86.     /**
  87.      * {@inheritDoc}
  88.      */
  89.     @Override
  90.     public BicubicSplineInterpolatingFunction interpolate(final double[] xval,
  91.                                                           final double[] yval,
  92.                                                           final double[][] fval)
  93.         throws NoDataException, NullArgumentException,
  94.                DimensionMismatchException, NonMonotonicSequenceException {
  95.         if (xval.length == 0 || yval.length == 0 || fval.length == 0) {
  96.             throw new NoDataException();
  97.         }
  98.         if (xval.length != fval.length) {
  99.             throw new DimensionMismatchException(xval.length, fval.length);
  100.         }

  101.         final int xLen = xval.length;
  102.         final int yLen = yval.length;

  103.         for (int i = 0; i < xLen; i++) {
  104.             if (fval[i].length != yLen) {
  105.                 throw new DimensionMismatchException(fval[i].length, yLen);
  106.             }
  107.         }

  108.         MathArrays.checkOrder(xval);
  109.         MathArrays.checkOrder(yval);

  110.         // For each line y[j] (0 <= j < yLen), construct a polynomial, with
  111.         // respect to variable x, fitting array fval[][j]
  112.         final PolynomialFunction[] yPolyX = new PolynomialFunction[yLen];
  113.         for (int j = 0; j < yLen; j++) {
  114.             xFitter.clearObservations();
  115.             for (int i = 0; i < xLen; i++) {
  116.                 xFitter.addObservedPoint(1, xval[i], fval[i][j]);
  117.             }

  118.             // Initial guess for the fit is zero for each coefficients (of which
  119.             // there are "xDegree" + 1).
  120.             yPolyX[j] = new PolynomialFunction(xFitter.fit(new double[xDegree + 1]));
  121.         }

  122.         // For every knot (xval[i], yval[j]) of the grid, calculate corrected
  123.         // values fval_1
  124.         final double[][] fval_1 = new double[xLen][yLen];
  125.         for (int j = 0; j < yLen; j++) {
  126.             final PolynomialFunction f = yPolyX[j];
  127.             for (int i = 0; i < xLen; i++) {
  128.                 fval_1[i][j] = f.value(xval[i]);
  129.             }
  130.         }

  131.         // For each line x[i] (0 <= i < xLen), construct a polynomial, with
  132.         // respect to variable y, fitting array fval_1[i][]
  133.         final PolynomialFunction[] xPolyY = new PolynomialFunction[xLen];
  134.         for (int i = 0; i < xLen; i++) {
  135.             yFitter.clearObservations();
  136.             for (int j = 0; j < yLen; j++) {
  137.                 yFitter.addObservedPoint(1, yval[j], fval_1[i][j]);
  138.             }

  139.             // Initial guess for the fit is zero for each coefficients (of which
  140.             // there are "yDegree" + 1).
  141.             xPolyY[i] = new PolynomialFunction(yFitter.fit(new double[yDegree + 1]));
  142.         }

  143.         // For every knot (xval[i], yval[j]) of the grid, calculate corrected
  144.         // values fval_2
  145.         final double[][] fval_2 = new double[xLen][yLen];
  146.         for (int i = 0; i < xLen; i++) {
  147.             final PolynomialFunction f = xPolyY[i];
  148.             for (int j = 0; j < yLen; j++) {
  149.                 fval_2[i][j] = f.value(yval[j]);
  150.             }
  151.         }

  152.         return super.interpolate(xval, yval, fval_2);
  153.     }
  154. }