/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.math.surface; import java.util.List; import java.util.Map; import org.apache.commons.lang.ObjectUtils; import com.opengamma.analytics.math.interpolation.GridInterpolator2D; import com.opengamma.analytics.math.interpolation.Interpolator2D; import com.opengamma.analytics.math.interpolation.data.Interpolator1DDataBundle; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.tuple.DoublesPair; import com.opengamma.util.tuple.Pair; import com.opengamma.util.tuple.Triple; /** * A surface that is defined by a set of nodal points (i.e. <i>x-y-z</i> data) and an interpolator to return values of <i>z</i> for values * of <i>(x, y)</i> that do not lie on nodal <i>(x, y)</i> values. */ public class InterpolatedDoublesSurface extends DoublesSurface { /** * @param xData An array of <i>x</i> data points, not null * @param yData An array of <i>y</i> data points, not null, contains same number of entries as <i>x</i> * @param zData An array of <i>z</i> data points, not null, contains same number of entries as <i>x</i> * @param interpolator The interpolator, not null * @return An interpolated surface with automatically-generated name */ public static InterpolatedDoublesSurface from(final double[] xData, final double[] yData, final double[] zData, final Interpolator2D interpolator) { return new InterpolatedDoublesSurface(xData, yData, zData, interpolator); } /** * @param xData An array of <i>x</i> data points, not null * @param yData An array of <i>y</i> data points, not null, contains same number of entries as <i>x</i> * @param zData An array of <i>z</i> data points, not null, contains same number of entries as <i>x</i> * @param interpolator The interpolator, not null * @return An interpolated surface with automatically-generated name */ public static InterpolatedDoublesSurface from(final Double[] xData, final Double[] yData, final Double[] zData, final Interpolator2D interpolator) { return new InterpolatedDoublesSurface(xData, yData, zData, interpolator); } /** * @param xData A list of <i>x</i> data points, not null * @param yData A list of <i>y</i> data points, not null, contains same number of entries as <i>x</i> * @param zData A list of <i>z</i> data points, not null, contains same number of entries as <i>x</i> * @param interpolator The interpolator, not null * @return An interpolated surface with automatically-generated name */ public static InterpolatedDoublesSurface from(final List<Double> xData, final List<Double> yData, final List<Double> zData, final Interpolator2D interpolator) { return new InterpolatedDoublesSurface(xData, yData, zData, interpolator); } /** * @param xyData An array of <i>x-y</i> data points, not null * @param zData An array of <i>z</i> data points, not null, contains same number of entries as <i>x-y</i> * @param interpolator The interpolator, not null * @return An interpolated surface with automatically-generated name */ public static InterpolatedDoublesSurface from(final DoublesPair[] xyData, final Double[] zData, final Interpolator2D interpolator) { return new InterpolatedDoublesSurface(xyData, zData, interpolator); } /** * @param xyData An array of <i>x-y</i> data points, not null * @param zData An array of <i>z</i> data points, not null, contains same number of entries as <i>x-y</i> * @param interpolator The interpolator, not null * @return An interpolated surface with automatically-generated name */ public static InterpolatedDoublesSurface from(final DoublesPair[] xyData, final double[] zData, final Interpolator2D interpolator) { return new InterpolatedDoublesSurface(xyData, zData, interpolator); } /** * @param xyData A list of <i>x-y</i> data points, not null * @param zData A list of <i>z</i> data points, not null, contains same number of entries as <i>x-y</i> * @param interpolator The interpolator, not null * @return An interpolated surface with automatically-generated name */ public static InterpolatedDoublesSurface from(final List<DoublesPair> xyData, final List<Double> zData, final Interpolator2D interpolator) { return new InterpolatedDoublesSurface(xyData, zData, interpolator); } /** * @param xyzData A map of <i>x-y</i> data points to <i>z</i> data points, not null * @param interpolator The interpolator, not null * @return An interpolated surface with automatically-generated name */ public static InterpolatedDoublesSurface from(final Map<DoublesPair, Double> xyzData, final Interpolator2D interpolator) { return new InterpolatedDoublesSurface(xyzData, interpolator); } /** * @param xyzData A list of <i>x-y-z</i> data points, not null * @param interpolator The interpolator, not null * @return An interpolated surface with automatically-generated name */ public static InterpolatedDoublesSurface from(final List<Triple<Double, Double, Double>> xyzData, final Interpolator2D interpolator) { return new InterpolatedDoublesSurface(xyzData, interpolator); } /** * @param xData An array of <i>x</i> data points, not null * @param yData An array of <i>y</i> data points, not null, contains same number of entries as <i>x</i> * @param zData An array of <i>z</i> data points, not null, contains same number of entries as <i>x</i> * @param interpolator The interpolator, not null * @param name The name of the surface * @return An interpolated surface with automatically-generated name */ public static InterpolatedDoublesSurface from(final double[] xData, final double[] yData, final double[] zData, final Interpolator2D interpolator, final String name) { return new InterpolatedDoublesSurface(xData, yData, zData, interpolator, name); } /** * @param xData An array of <i>x</i> data points, not null * @param yData An array of <i>y</i> data points, not null, contains same number of entries as <i>x</i> * @param zData An array of <i>z</i> data points, not null, contains same number of entries as <i>x</i> * @param interpolator The interpolator, not null * @param name The name of the surface * @return An interpolated surface with automatically-generated name */ public static InterpolatedDoublesSurface from(final Double[] xData, final Double[] yData, final Double[] zData, final Interpolator2D interpolator, final String name) { return new InterpolatedDoublesSurface(xData, yData, zData, interpolator, name); } /** * @param xData A list of <i>x</i> data points, not null * @param yData A list of <i>y</i> data points, not null, contains same number of entries as <i>x</i> * @param zData A list of <i>z</i> data points, not null, contains same number of entries as <i>x</i> * @param interpolator The interpolator, not null * @param name The name of the surface * @return An interpolated surface with automatically-generated name */ public static InterpolatedDoublesSurface from(final List<Double> xData, final List<Double> yData, final List<Double> zData, final Interpolator2D interpolator, final String name) { return new InterpolatedDoublesSurface(xData, yData, zData, interpolator, name); } /** * @param xyData An array of <i>x-y</i> data points, not null * @param zData An array of <i>z</i> data points, not null, contains same number of entries as <i>x-y</i> * @param interpolator The interpolator, not null * @param name The name of the surface * @return An interpolated surface with automatically-generated name */ public static InterpolatedDoublesSurface from(final DoublesPair[] xyData, final Double[] zData, final Interpolator2D interpolator, final String name) { return new InterpolatedDoublesSurface(xyData, zData, interpolator, name); } /** * @param xyData An array of <i>x-y</i> data points, not null * @param zData An array of <i>z</i> data points, not null, contains same number of entries as <i>x-y</i> * @param interpolator The interpolator, not null * @param name The name of the surface * @return An interpolated surface with automatically-generated name */ public static InterpolatedDoublesSurface from(final DoublesPair[] xyData, final double[] zData, final Interpolator2D interpolator, final String name) { return new InterpolatedDoublesSurface(xyData, zData, interpolator, name); } /** * @param xyData A list of <i>x-y</i> data points, not null * @param zData A list of <i>z</i> data points, not null, contains same number of entries as <i>x-y</i> * @param interpolator The interpolator, not null * @param name The name of the surface * @return An interpolated surface with automatically-generated name */ public static InterpolatedDoublesSurface from(final List<DoublesPair> xyData, final List<Double> zData, final Interpolator2D interpolator, final String name) { return new InterpolatedDoublesSurface(xyData, zData, interpolator, name); } /** * @param xyzData A map of <i>x-y</i> data points to <i>z</i> data points, not null * @param interpolator The interpolator, not null * @param name The name of the surface * @return An interpolated surface with automatically-generated name */ public static InterpolatedDoublesSurface from(final Map<DoublesPair, Double> xyzData, final Interpolator2D interpolator, final String name) { return new InterpolatedDoublesSurface(xyzData, interpolator, name); } /** * @param xyzData A list of <i>x-y-z</i> data points, not null * @param interpolator The interpolator, not null * @param name The name of the surface * @return An interpolated surface with automatically-generated name */ public static InterpolatedDoublesSurface from(final List<Triple<Double, Double, Double>> xyzData, final Interpolator2D interpolator, final String name) { return new InterpolatedDoublesSurface(xyzData, interpolator, name); } /** * Creates a surface based on a regular grid. * @param xVector The x data of the grid. Not null. * @param yVector The x data of the grid. Not null. * @param zData The z data. Not null. Contains a number of entries which is the product of the number of entries of xVector and yVector. * The z data should be in the order of xVector repeated yVector.length times, i.e. x[0]-y[0], x[1]-y[0], x[2]-y[0], ..., x[0]-y[1], x[1], y[1], etc. * @param interpolator The interpolator, not null * @return An interpolated surface with automatically-generated name. */ public static InterpolatedDoublesSurface fromGrid(final double[] xVector, final double[] yVector, final double[] zData, final Interpolator2D interpolator) { final int nX = xVector.length; final int nY = yVector.length; ArgumentChecker.isTrue(zData.length == nX * nY, "Sizes not compatible"); final double[] xData = new double[nX * nY]; final double[] yData = new double[nX * nY]; for (int loopy = 0; loopy < nY; loopy++) { System.arraycopy(xVector, 0, xData, loopy * nX, nX); } for (int loopx = 0; loopx < nX; loopx++) { for (int loopy = 0; loopy < nY; loopy++) { yData[loopx + loopy * nX] = yVector[loopy]; } } return from(xData, yData, zData, interpolator); } private final GridInterpolator2D _interpolator; private Map<Double, Interpolator1DDataBundle> _data; /** * @param xData An array of <i>x</i> data points, not null * @param yData An array of <i>y</i> data points, not null, contains same number of entries as <i>x</i> * @param zData An array of <i>z</i> data points, not null, contains same number of entries as <i>x</i> * @param interpolator The interpolator, not null */ public InterpolatedDoublesSurface(final double[] xData, final double[] yData, final double[] zData, final Interpolator2D interpolator) { super(xData, yData, zData); ArgumentChecker.notNull(interpolator, "interpolator"); ArgumentChecker.isTrue(interpolator instanceof GridInterpolator2D, "Interpolator must be a GridInterpolator2D"); //TODO remove me _interpolator = (GridInterpolator2D) interpolator; init(); } /** * @param xData An array of <i>x</i> data points, not null, no null elements * @param yData An array of <i>y</i> data points, not null, no null elements. Contains same number of entries as <i>x</i> * @param zData An array of <i>z</i> data points, not null, not null elements. Contains same number of entries as <i>x</i> * @param interpolator The interpolator, not null */ public InterpolatedDoublesSurface(final Double[] xData, final Double[] yData, final Double[] zData, final Interpolator2D interpolator) { super(xData, yData, zData); ArgumentChecker.notNull(interpolator, "interpolator"); ArgumentChecker.isTrue(interpolator instanceof GridInterpolator2D, "Interpolator must be a GridInterpolator2D"); //TODO remove me _interpolator = (GridInterpolator2D) interpolator; init(); } /** * @param xData A list of <i>x</i> data points, not null, no null elements * @param yData A list of <i>y</i> data points, not null, no null elements. Contains same number of entries as <i>x</i> * @param zData A list of <i>z</i> data points, not null, no null elements. Contains same number of entries as <i>x</i> * @param interpolator The interpolator, not null */ public InterpolatedDoublesSurface(final List<Double> xData, final List<Double> yData, final List<Double> zData, final Interpolator2D interpolator) { super(xData, yData, zData); ArgumentChecker.notNull(interpolator, "interpolator"); ArgumentChecker.isTrue(interpolator instanceof GridInterpolator2D, "Interpolator must be a GridInterpolator2D"); //TODO remove me _interpolator = (GridInterpolator2D) interpolator; init(); } /** * @param xyData An array of <i>x-y</i> data points, not null, no null elements * @param zData An array of <i>z</i> data points, not null. Contains same number of entries as <i>x-y</i> * @param interpolator The interpolator, not null */ public InterpolatedDoublesSurface(final DoublesPair[] xyData, final double[] zData, final Interpolator2D interpolator) { super(xyData, zData); ArgumentChecker.notNull(interpolator, "interpolator"); ArgumentChecker.isTrue(interpolator instanceof GridInterpolator2D, "Interpolator must be a GridInterpolator2D"); //TODO remove me _interpolator = (GridInterpolator2D) interpolator; init(); } /** * @param xyData An array of <i>x-y</i> data points, not null, no null elements * @param zData An array of <i>z</i> data points, not null, no null elements. Contains same number of entries as <i>x-y</i> * @param interpolator The interpolator, not null */ public InterpolatedDoublesSurface(final DoublesPair[] xyData, final Double[] zData, final Interpolator2D interpolator) { super(xyData, zData); ArgumentChecker.notNull(interpolator, "interpolator"); ArgumentChecker.isTrue(interpolator instanceof GridInterpolator2D, "Interpolator must be a GridInterpolator2D"); //TODO remove me _interpolator = (GridInterpolator2D) interpolator; init(); } /** * @param xyData A list of <i>x-y</i> data points, not null, no null elements * @param zData A list of <i>z</i> data points, not null, no null elements. Contains same number of entries as <i>x-y</i> * @param interpolator The interpolator, not null */ public InterpolatedDoublesSurface(final List<DoublesPair> xyData, final List<Double> zData, final Interpolator2D interpolator) { super(xyData, zData); ArgumentChecker.notNull(interpolator, "interpolator"); ArgumentChecker.isTrue(interpolator instanceof GridInterpolator2D, "Interpolator must be a GridInterpolator2D"); //TODO remove me _interpolator = (GridInterpolator2D) interpolator; init(); } /** * @param xyzData A map of <i>x-y</i> data points to <i>z</i> data points, not null, no null elements * @param interpolator The interpolator, not null */ public InterpolatedDoublesSurface(final Map<DoublesPair, Double> xyzData, final Interpolator2D interpolator) { super(xyzData); ArgumentChecker.notNull(interpolator, "interpolator"); ArgumentChecker.isTrue(interpolator instanceof GridInterpolator2D, "Interpolator must be a GridInterpolator2D"); //TODO remove me _interpolator = (GridInterpolator2D) interpolator; init(); } /** * @param xyzData A list of <i>x-y-z</i> data points, not null, no null elements * @param interpolator The interpolator, not null */ public InterpolatedDoublesSurface(final List<Triple<Double, Double, Double>> xyzData, final Interpolator2D interpolator) { super(xyzData); ArgumentChecker.notNull(interpolator, "interpolator"); ArgumentChecker.isTrue(interpolator instanceof GridInterpolator2D, "Interpolator must be a GridInterpolator2D"); //TODO remove me _interpolator = (GridInterpolator2D) interpolator; init(); } /** * @param xData An array of <i>x</i> data points, not null * @param yData An array of <i>y</i> data points, not null, contains same number of entries as <i>x</i> * @param zData An array of <i>z</i> data points, not null, contains same number of entries as <i>x</i> * @param interpolator The interpolator, not null * @param name The name of the surface */ public InterpolatedDoublesSurface(final double[] xData, final double[] yData, final double[] zData, final Interpolator2D interpolator, final String name) { super(xData, yData, zData, name); ArgumentChecker.notNull(interpolator, "interpolator"); ArgumentChecker.isTrue(interpolator instanceof GridInterpolator2D, "Interpolator must be a GridInterpolator2D"); //TODO remove me _interpolator = (GridInterpolator2D) interpolator; init(); } /** * @param xData An array of <i>x</i> data points, not null, no null elements * @param yData An array of <i>y</i> data points, not null, no null elements. Contains same number of entries as <i>x</i> * @param zData An array of <i>z</i> data points, not null, not null elements. Contains same number of entries as <i>x</i> * @param interpolator The interpolator, not null * @param name The name of the surface */ public InterpolatedDoublesSurface(final Double[] xData, final Double[] yData, final Double[] zData, final Interpolator2D interpolator, final String name) { super(xData, yData, zData, name); ArgumentChecker.notNull(interpolator, "interpolator"); ArgumentChecker.isTrue(interpolator instanceof GridInterpolator2D, "Interpolator must be a GridInterpolator2D"); //TODO remove me _interpolator = (GridInterpolator2D) interpolator; init(); } /** * @param xData A list of <i>x</i> data points, not null, no null elements * @param yData A list of <i>y</i> data points, not null, no null elements. Contains same number of entries as <i>x</i> * @param zData A list of <i>z</i> data points, not null, no null elements. Contains same number of entries as <i>x</i> * @param interpolator The interpolator, not null * @param name The name of the surface */ public InterpolatedDoublesSurface(final List<Double> xData, final List<Double> yData, final List<Double> zData, final Interpolator2D interpolator, final String name) { super(xData, yData, zData, name); ArgumentChecker.notNull(interpolator, "interpolator"); ArgumentChecker.isTrue(interpolator instanceof GridInterpolator2D, "Interpolator must be a GridInterpolator2D"); //TODO remove me _interpolator = (GridInterpolator2D) interpolator; init(); } /** * @param xyData An array of <i>x-y</i> data points, not null, no null elements * @param zData An array of <i>z</i> data points, not null. Contains same number of entries as <i>x-y</i> * @param interpolator The interpolator, not null * @param name The name of the surface */ public InterpolatedDoublesSurface(final DoublesPair[] xyData, final double[] zData, final Interpolator2D interpolator, final String name) { super(xyData, zData, name); ArgumentChecker.notNull(interpolator, "interpolator"); ArgumentChecker.isTrue(interpolator instanceof GridInterpolator2D, "Interpolator must be a GridInterpolator2D"); //TODO remove me _interpolator = (GridInterpolator2D) interpolator; init(); } /** * @param xyData An array of <i>x-y</i> data points, not null, no null elements * @param zData An array of <i>z</i> data points, not null, no null elements. Contains same number of entries as <i>x-y</i> * @param interpolator The interpolator, not null * @param name The name of the surface */ public InterpolatedDoublesSurface(final DoublesPair[] xyData, final Double[] zData, final Interpolator2D interpolator, final String name) { super(xyData, zData, name); ArgumentChecker.notNull(interpolator, "interpolator"); ArgumentChecker.isTrue(interpolator instanceof GridInterpolator2D, "Interpolator must be a GridInterpolator2D"); //TODO remove me _interpolator = (GridInterpolator2D) interpolator; init(); } /** * @param xyData A list of <i>x-y</i> data points, not null, no null elements * @param zData A list of <i>z</i> data points, not null, no null elements. Contains same number of entries as <i>x-y</i> * @param interpolator The interpolator, not null * @param name The name of the surface */ public InterpolatedDoublesSurface(final List<DoublesPair> xyData, final List<Double> zData, final Interpolator2D interpolator, final String name) { super(xyData, zData, name); ArgumentChecker.notNull(interpolator, "interpolator"); ArgumentChecker.isTrue(interpolator instanceof GridInterpolator2D, "Interpolator must be a GridInterpolator2D"); //TODO remove me _interpolator = (GridInterpolator2D) interpolator; init(); } /** * @param xyzData A map of <i>x-y</i> data points to <i>z</i> data points, not null, no null elements * @param interpolator The interpolator, not null * @param name The name of the surface */ public InterpolatedDoublesSurface(final Map<DoublesPair, Double> xyzData, final Interpolator2D interpolator, final String name) { super(xyzData, name); ArgumentChecker.notNull(interpolator, "interpolator"); ArgumentChecker.isTrue(interpolator instanceof GridInterpolator2D, "Interpolator must be a GridInterpolator2D"); //TODO remove me _interpolator = (GridInterpolator2D) interpolator; init(); } /** * @param xyzData A list of <i>x-y-z</i> data points, not null, no null elements * @param interpolator The interpolator, not null * @param name The name of the surface */ public InterpolatedDoublesSurface(final List<Triple<Double, Double, Double>> xyzData, final Interpolator2D interpolator, final String name) { super(xyzData, name); ArgumentChecker.notNull(interpolator, "interpolator"); ArgumentChecker.isTrue(interpolator instanceof GridInterpolator2D, "Interpolator must be a GridInterpolator2D"); //TODO remove me _interpolator = (GridInterpolator2D) interpolator; init(); } // TODO this logic should be in the interpolator private void init() { final double[] x = getXDataAsPrimitive(); final double[] y = getYDataAsPrimitive(); final double[] z = getZDataAsPrimitive(); _data = _interpolator.getDataBundleFromUnsorted(x, y, z, false); } /** * {@inheritDoc} */ @Override public Double getZValue(final Double x, final Double y) { ArgumentChecker.notNull(x, "x"); ArgumentChecker.notNull(y, "y"); return _interpolator.interpolate(_data, DoublesPair.of(x.doubleValue(), y.doubleValue())); } /** * {@inheritDoc} */ @Override public Double getZValue(final Pair<Double, Double> xy) { ArgumentChecker.notNull(xy, "xy"); return _interpolator.interpolate(_data, DoublesPair.of(xy)); } /** * @return The interpolator */ public Interpolator2D getInterpolator() { return _interpolator; } public Map<Double, ? extends Interpolator1DDataBundle> getInterpolatorData() { return _data; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + _interpolator.hashCode(); return result; } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (!super.equals(obj)) { return false; } if (getClass() != obj.getClass()) { return false; } final InterpolatedDoublesSurface other = (InterpolatedDoublesSurface) obj; return ObjectUtils.equals(_interpolator, other._interpolator); } }