001 package util.wavelet; 002 import java.util.List; 003 import java.util.Collections; 004 005 /** A wrapper for an array of signal values and their coordinate. 006 * @author John Talbot 007 */ 008 public class SignalAndCoordinate extends Signal { 009 010 /** Coordinates stored as a list permits the use of {@link Collections#binarySearch}. */ 011 java.util.List<Float> coordinates; 012 013 /** 014 * Construct using the given signal array, noise array and coordinate positions. 015 * 016 * @param value signal value array 017 * @param noise the noise array 018 * @param noiseMultiplier noise multiplier (when sigmas = 3.0 confidence = 99.9 percent) 019 * @param coordinates x positions 020 */ 021 public SignalAndCoordinate(float[] value, float[] noise, float noiseMultiplier, java.util.List<Float> coordinates) { 022 super(value, noise, noiseMultiplier); 023 this.coordinates = coordinates; 024 } 025 026 /** 027 * Get the x coordinate for the given position. The coordinate is read-only. 028 * 029 * @param position the position for which the coordinate is sought 030 * @return the x coordinate at the given position 031 */ 032 public float getCoordinate(int position) { 033 return coordinates.get(position); 034 } 035 036 /* 037 * Get the interpolated or extrapolated signal value at the given coordinate. 038 * 039 * @param coordinate the coordinate (must be within range) 040 * @return the interpolated value at coordinate 041 */ 042 public float getValueAtCoordinate(float coordinate) { 043 int position = Collections.binarySearch(coordinates, coordinate); 044 if (position >= 0 && position < size()) { 045 // TODO: second order approximation using float coordinate0 = getCoordinate(position-1); 046 float coordinate1 = getCoordinate(position); 047 float coordinate2 = getCoordinate(position + 1); 048 float value1 = getValue(position); 049 float value2 = getValue(position + 1); 050 if (coordinate1 == coordinate2) return value1; // pre-condition failure (should not happen) TODO: throw exception here 051 else return (value2 - value1) / (coordinate2 - coordinate1) / (coordinate - coordinate1) + value1; 052 } else { // out of range coordinate 053 if (position == -1) 054 return getValue(0); // TODO: extrapolation 055 else if (position == size()) 056 return getValue(size() - 1); // TODO: extrapolation 057 else 058 return 0f; // should never happen 059 } 060 } 061 }