Mercurial > dive4elements > river
diff flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Parameters.java @ 3318:dbe2f85bf160
merged flys-artifacts/2.8
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:14:35 +0200 |
parents | 79dd823733e2 |
children | 56f62b5209f5 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Parameters.java Fri Sep 28 12:14:35 2012 +0200 @@ -0,0 +1,313 @@ +package de.intevation.flys.artifacts.model; + +import de.intevation.flys.artifacts.math.Linear; + +import gnu.trove.TDoubleArrayList; + +import java.io.Serializable; + +import org.apache.log4j.Logger; + +public class Parameters +implements Serializable +{ + private static Logger log = Logger.getLogger(Parameters.class); + + public interface Visitor { + + void visit(double [] row); + + } // interface Visitor + + public static final double EPSILON = 1e-4; + + protected String [] columnNames; + protected TDoubleArrayList [] columns; + + public Parameters() { + } + + public Parameters(String [] columnNames) { + if (columnNames == null || columnNames.length < 1) { + throw new IllegalArgumentException("columnNames too short."); + } + this.columnNames = columnNames; + columns = new TDoubleArrayList[columnNames.length]; + for (int i = 0; i < columns.length; ++i) { + columns[i] = new TDoubleArrayList(); + } + } + + public int columnIndex(String name) { + for (int i = 0; i < columnNames.length; ++i) { + if (columnNames[i].equals(name)) { + return i; + } + } + if (log.isDebugEnabled()) { + log.debug("columnIndex: " + name + " not found in columnNames"); + } + return -1; + } + + public int newRow() { + + int N = columns[0].size(); + + for (int i = 0; i < columns.length; ++i) { + columns[i].add(Double.NaN); + } + + return N; + } + + public double get(int row, int index) { + return columns[index].getQuick(row); + } + + public double get(int i, String columnName) { + int index = columnIndex(columnName); + return index >= 0 + ? columns[index].getQuick(i) + : Double.NaN; + } + + public void set(int row, int index, double value) { + columns[index].setQuick(row, value); + } + + public void set(int i, String columnName, double value) { + int idx = columnIndex(columnName); + if (idx >= 0) { + columns[idx].setQuick(i, value); + } + } + + public boolean set(int row, int [] indices, double [] values) { + boolean invalid = false; + for (int i = 0; i < indices.length; ++i) { + double v = values[i]; + if (Double.isNaN(v)) { + invalid = true; + } + else { + columns[indices[i]].setQuick(row, v); + } + } + return invalid; + } + + public int size() { + return columns[0].size(); + } + + public int getNumberColumns() { + return columnNames.length; + } + + public String [] getColumnNames() { + return columnNames; + } + + public void removeNaNs() { + W.removeNaNs(columns); + } + + public int [] columnIndices(String [] columns) { + int [] indices = new int[columns.length]; + for (int i = 0; i < columns.length; ++i) { + indices[i] = columnIndex(columns[i]); + } + return indices; + } + + public double [] get(int row, String [] columns) { + return get(row, columns, new double[columns.length]); + } + + public double [] get(int row, String [] columns, double [] values) { + for (int i = 0; i < columns.length; ++i) { + int idx = columnIndex(columns[i]); + values[i] = idx < 0 + ? Double.NaN + : this.columns[idx].getQuick(row); + } + + return values; + } + + public void get(int row, int [] columnIndices, double [] values) { + for (int i = 0; i < columnIndices.length; ++i) { + int index = columnIndices[i]; + values[i] = index >= 0 && index < columns.length + ? columns[index].getQuick(row) + : Double.NaN; + } + } + + public int binarySearch(String columnName, double value) { + return binarySearch(columnIndex(columnName), value); + } + + /** + * Performes a binary search in the column identified by its + * index. + * @return Index of found element or negative insertion point (shifted by one) + */ + public int binarySearch(int columnIndex, double value) { + TDoubleArrayList column = columns[columnIndex]; + return column.binarySearch(value); + } + + public int binarySearch(String columnName, double value, double epsilon) { + return binarySearch(columnIndex(columnName), value, epsilon); + } + + public int binarySearch(int columnIndex, double value, double epsilon) { + if (epsilon < 0d) epsilon = -epsilon; + double vl = value - epsilon; + double vh = value + epsilon; + + TDoubleArrayList column = columns[columnIndex]; + int lo = 0, hi = column.size()-1; + while (hi >= lo) { + int mid = (lo + hi) >> 1; + double v = column.getQuick(mid); + if (v < vl) lo = mid + 1; + else if (v > vh) hi = mid - 1; + else return mid; + } + + return -(lo + 1); + } + + public double [] interpolate(int columnIndex, double key) { + return interpolate(columnIndex, key, new double[columns.length]); + } + + public double [] interpolate(String columnName, double key) { + return interpolate( + columnIndex(columnName), key, new double[columns.length]); + } + + public double [] interpolate( + String columnName, + double key, + double [] values + ) { + return interpolate(columnIndex(columnName), key, values); + } + + public double [] interpolate( + int columnIndex, + double key, + double [] values + ) { + int row = binarySearch(columnIndex, key, EPSILON); + + if (row >= 0) { // direct hit + for (int i = 0; i < values.length; ++i) { + values[i] = columns[i].getQuick(row); + } + } + else { + row = -row - 1; + if (row < 1 || row >= size()) { + return null; + } + double v1 = columns[columnIndex].getQuick(row-1); + double v2 = columns[columnIndex].getQuick(row); + double factor = Linear.factor(key, v1, v2); + for (int i = 0; i < values.length; ++i) { + values[i] = Linear.weight( + factor, + columns[i].getQuick(row-1), + columns[i].getQuick(row)); + } + } + return values; + } + + + public double [] interpolate( + String keyName, + double key, + String [] columnNames + ) { + int keyIndex = columnIndex(keyName); + return keyIndex < 0 + ? null + : interpolate(keyIndex, key, columnNames); + } + + public double [] interpolate( + int keyIndex, + double key, + String [] columnNames + ) { + int row = binarySearch(keyIndex, key, EPSILON); + + if (row >= 0) { // direct match + double [] values = new double[columnNames.length]; + for (int i = 0; i < values.length; ++i) { + int ci = columnIndex(columnNames[i]); + values[i] = ci < 0 + ? Double.NaN + : columns[ci].getQuick(row); + } + return values; + } + + row = -row - 1; + if (row < 1 || row >= size()) { + log.debug("interpolate: row is out of bounds"); + return null; + } + + double v1 = columns[keyIndex].getQuick(row-1); + double v2 = columns[keyIndex].getQuick(row); + double factor = Linear.factor(key, v1, v2); + + double [] values = new double[columnNames.length]; + + for (int i = 0; i < values.length; ++i) { + int ci = columnIndex(columnNames[i]); + values[i] = ci < 0 + ? Double.NaN + : Linear.weight( + factor, + columns[ci].getQuick(row-1), + columns[ci].getQuick(row)); + } + + return values; + } + + public boolean isSorted(String columnName) { + return isSorted(columnIndex(columnName)); + } + + public boolean isSorted(int columnIndex) { + TDoubleArrayList column = columns[columnIndex]; + for (int i = 1, N = column.size(); i < N; ++i) { + if (column.getQuick(i-1) > column.getQuick(i)) { + return false; + } + } + return true; + } + + public void visit(Visitor visitor) { + visit(visitor, new double[columns.length]); + } + + public void visit(Visitor visitor, double [] data) { + for (int i = 0, R = size(); i < R; ++i) { + for (int j = 0; j < data.length; ++j) { + data[j] = columns[j].getQuick(i); + } + visitor.visit(data); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :